简体   繁体   English

重新排序Django模型中的字段

[英]Reordering fields in Django model

I want to add few fields to every model in my django application. 我想在我的django应用程序中为每个模型添加几个字段。 This time it's created_at , updated_at and notes . 这次是created_atupdated_atnotes Duplicating code for every of 20+ models seems dumb. 20个模型中每个模型的复制代码似乎都很愚蠢。 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. 问题是从抽象基类继承的字段首先出现在admin的字段列表中。 Declaring field order for every ModelAdmin class is not an option, it's even more duplicate code than with manual field declaration. 声明每个ModelAdmin类的字段顺序不是一个选项,它甚至比手动字段声明更重复代码。

In my final solution, I modified model constructor to reorder fields in _meta before creating new instance: 在我的最终解决方案中,我修改了模型构造函数,以便在创建新实例之前重新排序_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 ... 

It works as intended, but I'm wondering, is there a better way to acheive my goal? 它按预期工作,但我想知道,有没有更好的方法来实现我的目标?

I was having the very same problem, but I found these solutions to be problematic, so here's what I did: 我遇到了同样的问题,但我发现这些解决方案存在问题,所以这就是我所做的:

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

Changing the fieldset in the admin makes more sense to me, than changing the fields in the model. 与更改模型中的字段相比,更改管理员中的字段集对我来说更有意义。

If you mainly need the ordering for Django's admin you could also create your "generic"-admin class via sub-classing Django's admin class. 如果您主要需要Django管理员的订购,您还可以通过对Django的管理类进行子类化来创建您的“通用”-admin类。 See http://docs.djangoproject.com/en/dev/intro/tutorial02/#customize-the-admin-form for customizing the display of fields in the admin. 请参阅http://docs.djangoproject.com/en/dev/intro/tutorial02/#customize-the-admin-form以自定义管理员中字段的显示。 You could overwrite the admin's __init__ to setup fields/fieldsets on creation of the admin instance as you wish. 您可以根据需要覆盖管理员的__init__来设置管理实例的字段/字段集。 Eg you could do something like: 你可以这样做:

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)

Besides that i think it's not a good practice to modify the (private) _field_name_cache ! 除此之外,我认为修改(私有) _field_name_cache不是一个好习惯!

I ALSO didn't like the other solutions, so I instead just modified the migrations files directly. 我也不喜欢其他解决方案,所以我只是直接修改了迁移文件。

Whenever you create a new table in models.py, you will have to run "python manage.py makemigrations" (I believe this in Django >= v1.7.5). 每当你在models.py中创建一个新表时,你将不得不运行“python manage.py makemigrations”(我相信这在Django> = v1.7.5)。 Once you do this, open up the newly created migrations file in your_app_path/migrations/ directory and simply move the rows to the order you want them to be in. Then run "python manage.py migrate". 执行此操作后,在your_app_path / migrations /目录中打开新创建的迁移文件,然后只需将行移动到您希望它们所在的顺序。然后运行“python manage.py migrate”。 Voila! 瞧! By going into "python manage.py dbshell" you can see that the order of the columns is exactly how you wanted them! 通过进入“python manage.py dbshel​​l”,您可以看到列的顺序正是您想要的!

Downside to this method: You have to do this manually for each table you create, but fortunately the overhead is minimal. 此方法的缺点:您必须为您创建的每个表手动执行此操作,但幸运的是,开销很小。 And this can only be done when you're creating a new table, not to modify an existing one. 这只能在您创建新表时进行,而不是修改现有表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM