Ale*_*dev 9 python django django-models
我想在我的django应用程序中为每个模型添加几个字段.这次是created_at,updated_at和notes.20个模型中每个模型的复制代码似乎都很愚蠢.所以,我决定使用抽象基类来添加这些字段.问题是从抽象基类继承的字段首先出现在admin的字段列表中.声明每个ModelAdmin类的字段顺序不是一个选项,它甚至比手动字段声明更重复代码.
在我的最终解决方案中,我修改了模型构造函数以在创建新实例之前重新排序_meta中的字段:
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 ...
Run Code Online (Sandbox Code Playgroud)
它按预期工作,但我想知道,有没有更好的方法来实现我的目标?
我遇到了同样的问题,但我发现这些解决方案存在问题,所以这就是我所做的:
class BaseAdmin(admin.ModelAdmin):
def get_fieldsets(self, request, obj = None):
res = super(BaseAdmin, self).get_fieldsets(request, obj)
# I only need to move one field; change the following
# line to account for more.
res[0][1]['fields'].append(res[0][1]['fields'].pop(0))
return res
Run Code Online (Sandbox Code Playgroud)
与更改模型中的字段相比,更改管理员中的字段集对我来说更有意义.
如果您主要需要Django管理员的订购,您还可以通过对Django的管理类进行子类化来创建"通用"-admin类.请参阅http://docs.djangoproject.com/en/dev/intro/tutorial02/#customize-the-admin-form以自定义管理员中字段的显示.您可以根据需要覆盖管理员__init__在创建管理实例时设置字段/字段集.你可以这样做:
class MyAdmin(admin.ModelAdmin):
def __init__(self, model, admin_site):
general_fields = ['notes', 'created_at', 'updated_at']
fields = [f.name for f in self.model._meta.fields if f.name not in general_fields]
self.fields = fields + general_fields
super(admin.ModelAdmin, self).__init__(model, admin_site)
Run Code Online (Sandbox Code Playgroud)
除此之外,我认为修改(私人)不是一个好习惯_field_name_cache!