#34555: Dynamic model fields without using a metaclass
-------------------------------------+-------------------------------------
               Reporter:  hottwaj    |          Owner:  nobody
                   Type:  New        |         Status:  new
  feature                            |
              Component:  Database   |        Version:  4.2
  layer (models, ORM)                |       Keywords:  ModelBase
               Severity:  Normal     |  init_subclass
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 I'd like to be able to write some abstract model "templates" that can be
 re-used/customised in various other django apps.  Some of these templates
 require ForeignKeys to other "templates" which are also abstract.
 Obviously ForeignKeys to Abstract models are not possible

 Having used metaclasses in a similar situation before, but hoping to find
 a less complex approach, I thought I might be able to implement this by
 providing a __init_subclass__ method on my "template" model, with that
 method designed to set up the ForeignKey to a given concrete model, but
 this does not work.  It seems that __init_subclass__ is called after
 ModelBase.__new__ collects fields that require "contribute_to_class", so
 the fields I add in __init_subclass__ are never "seen" by e.g. the
 migration builder.

 Example approach below (but note this does not work for reasons explained
 above):

 {{{#!python
 from django.db.models import Model, ForeignKey, CASCADE, CharField

 class BaseBookModel(Model):
     class Meta:
         abstract = True

     def __init_subclass__(cls, author_model_cls: Type[Model], **kwargs,):
         super().__init_subclass__(**kwargs)
         author = ForeignKey(author_model_cls, on_delete = CASCADE)
         cls.add_to_class('author', author)

 class Author(Model):
     name = CharField(max_len = 256, unique = True)

 class Book(BaseBookModel, author_model_cls = Author):
     pass
 }}}

 Essentially what I'd like is some way of doing some extra work after
 BaseModel.__new__ is called without resorting to having to write a
 metaclass for BaseBookModel - I'm just adding some extra fields and a
 metaclass is complex for most mortals to read let alone write.  There does
 not seem to be an appropriate hook method that I can override to do this
 for every subclass of BaseBookModel

 Thanks for reading and appreciate any thoughts!

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34555>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/010701880664eb04-afaaa5e4-3c3c-465d-a6f5-558ea4376edb-000000%40eu-central-1.amazonses.com.

Reply via email to