Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#18540 closed New feature (wontfix)

Improve Model flexibility by allowing a custom Options class

Reported by: gcc Owned by: nobody
Component: Database layer (models, ORM) Version: 1.4
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

For example, if I want to specify that my model has custom permissions, to be able to use them in the admin, I can't subclass Options to add or change the get_*_permission methods, because ModelBase.__new__ does this:

new_class.add_to_class('_meta', Options(meta, **kwargs))

I think it would be great to allow specifying a different Options class in the model's Meta class:

class MyModelOptions(Options):
    def get_view_permission(self):
        return 'view_%s' % self.object_name.lower()

class MyModel(Model):
    class Meta:
        options_class = MyModelOptions

I think the code change would be quite simple:

options_class = getattr(meta, 'options_class', Options)
new_class.add_to_class('_meta', options_class(meta, **kwargs))

Acceptable?

Change History (3)

comment:1 Changed 3 years ago by akaariai

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to wontfix
  • Status changed from new to closed

The big problem is that the whole Options (Model._meta) is private API. It is often used, but it is still private API. So, before the API of the Options is public I don't see a point in the meta option of overriding the state class. For this reason wontfix.

I do see that one could do nice things with custom Options class. I am not denying that. But we need some API for Options first. If you absolutely need to override the options class, you can use custom metaclass, and then from the custom metaclass use the custom Options class.

Refactoring the code in a way that you have a nice hook for this is IMHO acceptable. Basically, the getattr(meta, 'options_class', Options) could be turned to self.get_options_class(). Override get_options_class() and you got your custom Options class. This all would be private API, but you could use it if you absolutely need.

comment:2 Changed 3 years ago by gcc

Sorry, but I don't understand why adding this code:

options_class = self.get_options_class()
...
def get_options_class(self):
    return Options

is better than this:

options_class = getattr(meta, 'options_class', Options)

Please can you enlighten me?

comment:3 Changed 3 years ago by akaariai

Maybe you are right. But AFAICS the meta options are public. The hook would be non-public. Maybe this is over pedantic on my part, but there is currently zero non-public meta options.

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