I want to add few fields to every model in my django application. This time it's created_at, updated_at and notes. Duplicating code for every of 20+ models seems dumb. So, I decided to use abstract base class which would add these fields. The problem is that fields inherited from abstract base class come first in the field list in admin. Declaring field order for every ModelAdmin class is not an option, it's even more duplicate code than with manual field declaration.
In my final solution, I modified model constructor to reorder fields in _meta before creating new instance:
class MyModel(models.Model):
# Service fields
notes = my_fields.NotesField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
last_fields = ("notes", "created_at", "updated_at")
def __init__(self, *args, **kwargs):
new_order = [f.name for f in self._meta.fields]
for field in self.last_fields:
new_order.remove(field)
new_order.append(field)
self._meta._field_name_cache.sort(key=lambda x: new_order.index(x.name))
super(MyModel, self).__init__(*args, **kwargs)
class ModelA(MyModel):
field1 = models.CharField()
field2 = models.CharField()
#etc ...
It works as intended, but I'm wondering, is there a better way to acheive my goal?
_field_name_cacheattribute onself._metaso the hunt continues for a way to do it in Django 4 ... P.S. I find answers here focussed on Admin views pointless, it is the standard form order I'm interested in as respected byas_table()and their ilk and I have no interest in the Admin site.self._meta.concrete_fieldsis the thing to use, alas it's immutable assigning to it causes trouble. Still delving._field_name_cachedoes not seem to exist anymore andlocal_fieldsbeing the only mutable similar item does not seem to cause the same effects. Also note that this "solution" here is for an instance of the model not for the model creation itself.