Изменение порядка полей в модели Django - PullRequest
9 голосов
/ 02 мая 2010

Я хочу добавить несколько полей для каждой модели в моем приложении 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 ... 

Работает как задумано, но мне интересно, есть ли лучший способ достичь моей цели?

Ответы [ 3 ]

7 голосов
/ 08 марта 2011

У меня была та же проблема, но я нашел, что эти решения проблематичны, поэтому вот что я сделал:

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

Изменение набора полей в админке имеет для меня больше смысла, чем изменение полей в модели.

5 голосов
/ 03 мая 2010

Если вам в основном нужен порядок для администратора Django, вы также можете создать свой «общий» класс -admin через подкласс класса администратора Django. См. 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!

1 голос
/ 29 ноября 2015

Мне также не понравились другие решения, поэтому я вместо этого просто изменил файлы миграции напрямую.

Всякий раз, когда вы создаете новую таблицу в models.py, вам придется запускать "python manage.py"makemigrations "(я верю в это в Django> = v1.7.5).После этого откройте только что созданный файл миграций в каталоге your_app_path / migrations / и просто переместите строки в том порядке, в котором вы хотите, чтобы они находились. Затем запустите «python manage.py migrate».Вуаля!Зайдя в «python manage.py dbshell», вы можете увидеть, что порядок столбцов точно такой, как вы хотели!

Недостаток этого метода: вы должны делать это вручную для каждой создаваемой таблицы, нок счастью, накладные расходы минимальны.И это может быть сделано только при создании новой таблицы, а не для изменения существующей.

...