重新排序Django模型中的字段

时间:2010-05-02 14:30:17

标签: python django django-models

我想在我的django应用程序中为每个模型添加几个字段。这次是created_atupdated_atnotes。 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 ... 

它按预期工作,但我想知道,有没有更好的方法来实现我的目标?

3 个答案:

答案 0 :(得分:7)

我遇到了同样的问题,但我发现这些解决方案存在问题,所以这就是我所做的:

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

更改管理员中的字段集对我来说比改变模型中的字段更有意义。

答案 1 :(得分:5)

如果您主要需要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)

除此之外,我认为修改(私人)_field_name_cache不是一个好习惯!

答案 2 :(得分:1)

我也不喜欢其他解决方案,所以我只是直接修改了迁移文件。

每当你在models.py中创建一个新表时,你都必须运行" python manage.py makemigrations" (我相信这在Django> = v1.7.5)。执行此操作后,在 your_app_path / migrations / 目录中打开新创建的迁移文件,然后只需将行移动到您希望它们所在的顺序。然后运行" python manage.py迁移&#34 ;.瞧!进入" python manage.py dbshel​​l"你可以看到列的顺序正是你想要的那样!

此方法的缺点:您必须为您创建的每个表手动执行此操作,但幸运的是,开销很小。这只能在您创建新表时进行,而不是修改现有表。