Opened 15 years ago

Last modified 9 months ago

#5793 new New feature

Allow custom attributes in Meta classes

Reported by: eikke@… Owned by: nobody
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords:
Cc: Loic Bistuer, jamespic@…, Ryan Hiebert, Rich Rauenzahn, Carlos Palol, Sardorbek Imomaliev, Gordon Wrigley, omelched Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


In some cass it is useful to be able to store meta information on models inside the model class. In Django the Meta subclass is used to achieve this. Trying to add a custom attribute to a model's Meta inner class results in an exception though, thrown from django.db.models.options, which does indeed check any valid attribute names and raises an exception when unknown names are found.
Is there any reason for this somewhat strange behaviour, not to allow a developer to add non-standard meta information to a model class (which can later on be used in eg view code)?


Change History (23)

comment:1 Changed 14 years ago by James Bennett

Resolution: wontfix
Status: newclosed

I'm going to call this a wontfix; Meta exists to set up a lot of "internal use" APIs, and the validation has to be strict to ensure that potential errors in that process are caught (e.g., if your Meta contains an attribute order, how can the validator tell whether you meant to add your own custom info or actually wanted ordering?).

And given that Django models are simply Python classes, and you're free to set up any attributes on them you like and then make use of them, I'm not sure that the use case of adding custom information in Meta is compelling enough.

comment:2 Changed 12 years ago by miracle2k

Resolution: wontfix
Status: closedreopened

I'd like to ask this be given another thought.

I'm not really convinced by the validation argument; first, this seems a more basic problem at it's core, particular in scripting languages. There are lots of places where a typo could lead to an API silently not being activated (think certain kwargs-scenarios, or a typo in the name of subclass methods etc). At some point you just need to actually check whether the code you've written actually does what its supposed to.

Secondly, if one really wants meta-validation, there is a middle ground: Require custom meta attributes to be pre-registered.

I just think this would be really nice for libraries that provide model base classes to accept configuration. Say for example django-treebeard and it's node_order_by (which is currently simply added to the class itself, which works, yes, but there's a reason why we have Meta in the first place).

comment:3 Changed 12 years ago by James Bennett

Resolution: wontfix
Status: reopenedclosed

If you disagree with a wontfix designation, the correct place to bring it up is on the django-developers list.

comment:4 Changed 12 years ago by miracle2k

For those Googling, it turns out there is a way to work around this using a custom model metaclass:

comment:5 Changed 12 years ago by robmadole

Inspired by the django-easytree code, I've created django-immutablefield for anyone interested.

comment:6 Changed 9 years ago by Russell Keith-Magee

Easy pickings: unset
Resolution: wontfix
Severity: Normal
Status: closednew
Triage Stage: UnreviewedAccepted
Type: New feature
UI/UX: unset

This ticket was raised on Django-developers in response to a duplicated report (#21081). The devil is in the details, but I can at least see that there is a use case here. I share @ubernostrum's concern about Meta becoming a dumping ground for flags that shouldn't be kept on Meta, but it doesn't follow that there is no reason why an end-user would want to define an extension to the built-in set.

comment:7 Changed 9 years ago by Shai Berger

On the list, Tim Chase gave this example:

class MyModel(Model):
  class Meta:
    class MyApp:
      secure_fields = ["cc_num", "ssn"]

The idea was that app-specific properties should be namespaced to avoid clashes. I think the approach is fine, I just don't see why these classes need to be in Meta; I see nothing wrong with

class MyModel(Model):
  class Meta:
  class MyApp:
    secure_fields = ["cc_num", "ssn"]

This leaves the app-specific metadata separate from fields and methods, so the "API" is clean enough; it avoids clashes reasonably well; and it requires no changes in Django.

Note that this was the approach taken by Admin at first -- and my impression (though I wasn't "there" at the time) is that it changed because Admin classes became too large for comfort as nested classes, not because the first idea was considered so bad.

I think for most use-cases -- in particular, including the two noted on the list, marking fields as "to be published" or "to be censored", this can work well.

The point about extending the ORM stands, but this does not seem to be the use-case that motivates the current requests.

comment:8 in reply to:  7 Changed 9 years ago by Shai Berger

Replying to shai:

The point about extending the ORM stands, but this does not seem to be the use-case that motivates the current requests.

I have to take that back -- it is true as far as the requests on the mailing list postings are concerned, but #21081 actually is about extending the ORM.

comment:11 Changed 6 years ago by Simon Litchfield

Cc: Simon Litchfield added

+1 - it's kinda daft to encourage the ORM to be extendable, while at the same time restricting what Meta options we're allowed

Why not just move DEFAULT_NAMES into the Model class? problem solved, zero breakage.

comment:12 Changed 6 years ago by Simon Litchfield

Cc: Simon Litchfield removed
Easy pickings: set

comment:13 Changed 6 years ago by Tim Graham

Component: MetasystemDatabase layer (models, ORM)
Easy pickings: unset

comment:14 Changed 6 years ago by Loic Bistuer

Cc: Loic Bistuer added

How about an API to register new model options (e.g. models.Options.register_option('mptt_manager_name')).

The AppConfig.ready() comes in too late to register this, but AppConfig.__init__() should work.

comment:15 Changed 5 years ago by James Pic

Cc: jamespic@… added

comment:16 Changed 5 years ago by James Pic

Question: is this ticket just about Model.Meta or also for ModelForm.Meta ? /me wondering if another, similar ticket could be opened about ModelForm.Meta

comment:17 Changed 5 years ago by Adam Johnson

James I think this ticket is about Model.Meta but whatever the API it ends up with could be copied over to ModelForm.Meta, so idk if it makes sense to create a second ticket for that yet

comment:18 Changed 5 years ago by Maxime Vdb

It would be indeed very useful: I have a custom database backend (for Redshift) and I would like to support advanced options for this backend (these options would modify the SQL for table creation for instance). There is apparently no other way than defining that on the Meta dict (due to the migration system) but it is not possible to define custom options.

Did you guys agree on the design yet?

comment:19 Changed 5 years ago by Dylan Young

This would actually enable users to develop on Django much more easily; I imagine you would get a slew of new ORM developments coming in quite quickly.

Some thoughts:

1) How to hook into the migration system for database changes? i.e. If I wanted to add partial indices and have the migrations autogenerate from my custom Meta option for this. The 'register_option' idea is probably good for this.

2) How to play nice with migrations for state changes?

comment:20 Changed 4 years ago by Ryan Hiebert

Cc: Ryan Hiebert added

comment:21 Changed 3 years ago by Rich Rauenzahn

Cc: Rich Rauenzahn added

comment:22 Changed 3 years ago by Carlos Palol

Cc: Carlos Palol added

comment:23 Changed 2 years ago by Sardorbek Imomaliev

Cc: Sardorbek Imomaliev added

comment:24 Changed 18 months ago by Gordon Wrigley

Cc: Gordon Wrigley added

comment:25 Changed 9 months ago by omelched

Cc: omelched added
Note: See TracTickets for help on using tickets.
Back to Top