Django admin встроил многие из многих настраиваемых полей
Привет, я пытаюсь настроить мои встроенные строки в admin django.
Вот мои модели:
class Row(models.Model):
name = models.CharField(max_length=255)
class Table(models.Model):
rows = models.ManyToManyField(Row, blank=True)
name = models.CharField(max_length=255)
def __unicode__(self):
return self.name
и мой администратор:
class RowInline(admin.TabularInline):
model = Table.rows.through
fields = ['name']
class TableAdmin(admin.ModelAdmin):
inlines = [
RowInline,
]
exclude = ('rows',)
Однако я получаю эту ошибку
Неправильно Конфигурировано в /admin/table _app/table/1/
'RowInline.fields' относится к имени поля, которое отсутствует в форма.
Как это возможно?
Ответы
Ответ 1
class RowInline(admin.TabularInline):
model = Table.rows.through
fields = ['name']
Это представляет проблему, поскольку Table.rows.through представляет собой промежуточную модель. Если вы хотите это лучше понять, посмотрите на свою базу данных. Вы увидите промежуточную таблицу, которая ссылается на эту модель. Вероятно, это имя называется apname_table_rows. Эта промежуточная модель не содержит поля, имя. У этого есть только два поля внешнего ключа: таблица и строка. (И он имеет поле id.)
Если вам нужно имя, на него можно ссылаться как поле readonly через отношение строк.
class RowInline(admin.TabularInline):
model = Table.rows.through
fields = ['row_name']
readonly_fields = ['row_name']
def row_name(self, instance):
return instance.row.name
row_name.short_description = 'row name'
class TableAdmin(admin.ModelAdmin):
inlines = [
RowInline,
]
exclude = ('rows',)
Ответ 2
Django не может отображать его, как вы ожидали. Потому что есть таблица промежуточного соединения, которая объединяет ваши таблицы. В вашем примере:
admin.py:
class RowInline(admin.TabularInline):
model = Table.rows.through # You are not addressing directly Row table but intermediary table
fields = ['name']
Как указано выше, model
в RowInline
обращается к следующей таблице в вашей базе данных, а не к вашей таблице Row
и модели
table: your-app-name_table_row
--------------------------------
id | int not null
table_id | int
row_id | int
Вы можете думать, что в вашей модели есть таблица мнимой, которая объединяет две таблицы.
class Table_Row(Model):
table = ForeignKey(Table)
row = ForeignKey(Row)
Итак, если вы отредактируете свою Inline как следующую
class RowInline(admin.TabularInline):
model = Table.rows.through # You are not addressing directly Row table but intermediary table
fields = ['row', 'table']
вы не увидите никакой ошибки или исключения. Поскольку ваш model
в RowInline
обращается к промежуточной таблице, и эта таблица имеет эти поля. Django может виртуализировать мнимую таблицу Table_Row
до этого и может справиться с этим.
Но мы можем использовать отношения в admin, используя __
. Если ваш код имеет отношение ForeignKey
вместо отношения ManyToManyField
, то в вашем администраторе
class Row(models.Model):
name = models.CharField(max_length=255)
class Table(models.Model):
rows = models.ForeignKey(Row, blank=True)
name = models.CharField(max_length=255)
def __unicode__(self):
return self.name
и ваш администратор:
class RowInline(admin.TabularInline):
model = Table
fields = ['rows__name']
Поскольку у вас будут настоящие модели, а djnago может оценить отношение __
к ним
Но если вы попробуете это в своей структуре:
class Row(models.Model):
name = models.CharField(max_length=255)
class Table(models.Model):
rows = models.ManyToManyField(Row, blank=True)
name = models.CharField(max_length=255)
def __unicode__(self):
return self.name
и ваш администратор:
class RowInline(admin.TabularInline):
model = Table.rows.through
fields = ['row__name']
это будет raise Exception
! Поскольку в вашей модели нет таблицы real, и django не может оценивать отношения __
на виртуальных моделях, которые она создает поверх своей головы.
Вывод:
В ваших Inline
адресных ManyToMany
отношениях вы имеете дело с воображаемой посреднической моделью, и вы не можете использовать атрибуты fields
или exclude
, потому что ваша воображаемая модель не имеет этих полей, а django не может обрабатывать отношения над этой воображаемой таблицей. Следующее будет приемлемым
class RowInline(admin.TabularInline):
model = Table.rows.through
# No fields or exclude declarations in here
а django отобразит комбинированные поля для параметров вашей виртуальной промежуточной таблицы и добавит яркий зеленый знак +
для добавления новых записей, но вы не сможете иметь встроенные поля для добавления новых записей непосредственно в свою базу данных на одной и той же странице, Djnago не может справиться с этим на одной странице.
Вы можете попробовать создать промежуточную таблицу real и показать ее с помощью через, но это полная работа, и я не проверяйте его, чтобы увидеть его результаты.
Обновление: Существует также причина, по которой django не позволяет что-то подобное. Рассмотрим следующее:
Table | Table_Row | Row
-----------+-----------+---------
Start 5 | |
Step 1 5 | | 1
Step 2 5 | 5-1 | 1
В начале у вас есть таблица без связанных строк, вы хотите добавить строку в таблицу... Для присоединения строки к таблице, , вы должны сначала создать строку, поэтому вы выполните шаг 1. После того, как вы создадите свою строку, вы можете создать запись Table_Row
, чтобы присоединиться к этим двум. Таким образом, in содержит более одной вставки базы данных. Команда Django может избежать такого использования, поскольку она содержит несколько вставок, а операция связана с большим количеством таблиц.
Но это всего лишь предположение о причине поведения.
Ответ 3
В вашем admin.py попробуйте это
class RowInline(admin.TabularInline):
model = Table.rows.through
list_display = ('name',)
class TableAdmin(admin.ModelAdmin):
inlines = [
RowInline,
]
readonly_fields = ('rows',)