maa*_*zza 12 python django django-forms django-admin django-1.5
嗨,我想在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
Run Code Online (Sandbox Code Playgroud)
和我的管理员:
class RowInline(admin.TabularInline):
model = Table.rows.through
fields = ['name']
class TableAdmin(admin.ModelAdmin):
inlines = [
RowInline,
]
exclude = ('rows',)
Run Code Online (Sandbox Code Playgroud)
但是我得到了这个错误
在/ admin/table_app/table/1 /中配置不正确
'RowInline.fields'指的是表单中缺少的字段'name'.
怎么可能?
sj7*_*sj7 19
class RowInline(admin.TabularInline):
model = Table.rows.through
fields = ['name']
Run Code Online (Sandbox Code Playgroud)
这提出了一个问题,因为Table.rows.through代表一个中间模型.如果您想了解这一点,请查看您的数据库.您将看到一个引用此模型的中间表.它可能被命名为apname_table_rows.此中介模型不包含字段名称.它只有两个外键字段:table和row.(它有一个id字段.)
如果需要名称,可以通过行关系将其引用为只读字段.
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',)
Run Code Online (Sandbox Code Playgroud)
Django无法按预期显示它.因为有一个连接表的中间连接表.在你的例子中:
admin.py:
class RowInline(admin.TabularInline):
model = Table.rows.through # You are not addressing directly Row table but intermediary table
fields = ['name']
Run Code Online (Sandbox Code Playgroud)
如上所述,model
在RowInline
数据库中寻址下表时,不是您的Row
表和模型
table: your-app-name_table_row
--------------------------------
id | int not null
table_id | int
row_id | int
Run Code Online (Sandbox Code Playgroud)
您可以认为模型中有一个虚构的表连接两个表.
class Table_Row(Model):
table = ForeignKey(Table)
row = ForeignKey(Row)
Run Code Online (Sandbox Code Playgroud)
因此,如果您按照以下方式编辑内联
class RowInline(admin.TabularInline):
model = Table.rows.through # You are not addressing directly Row table but intermediary table
fields = ['row', 'table']
Run Code Online (Sandbox Code Playgroud)
你不会看到任何错误或异常.因为你的model
in 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
Run Code Online (Sandbox Code Playgroud)
和你的管理员:
class RowInline(admin.TabularInline):
model = Table
fields = ['rows__name']
Run Code Online (Sandbox Code Playgroud)
因为你将拥有真实的模型,而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
Run Code Online (Sandbox Code Playgroud)
和你的管理员:
class RowInline(admin.TabularInline):
model = Table.rows.through
fields = ['row__name']
Run Code Online (Sandbox Code Playgroud)
它会的raise Exception
!因为你的模型中没有真正的表,并且django无法评估__
虚拟模型上的关系,所以它设计在它的头顶.
在你Inline
的寻址ManyToMany
关系中,你正在处理一个虚构的中间模型,你不能使用fields
或exclude
属性,因为你的想象模型没有那些字段,而django无法处理那个想象表的关系.以下是可以接受的
class RowInline(admin.TabularInline):
model = Table.rows.through
# No fields or exclude declarations in here
Run Code Online (Sandbox Code Playgroud)
和django将显示虚拟中介表选项的组合框,并添加一个花哨的绿色+
标志来添加新记录,但是您不能使用内联字段将新记录直接添加到同一单页中的数据库中.Djnago无法在单个页面上处理此问题.
您可以尝试创建真正的中间表并使用through来显示它,但这完全是一个更长的工作,我不测试它以查看其结果.
更新:还有一个原因,为什么django不会让这样的东西.考虑以下:
Table | Table_Row | Row
-----------+-----------+---------
Start 5 | |
Step 1 5 | | 1
Step 2 5 | 5-1 | 1
Run Code Online (Sandbox Code Playgroud)
一开始,你有一个没有相关行的表,你想在表中添加一行...要加入一个表的行,你必须先创建一行,这样你才能执行第1步.之后你创建了你的行行,你可以创建Table_Row
记录来加入这两个.因此在包含多个数据库插入.Django工作人员可能会避免这种用法,因为它包含多个插入,操作与更多表相关.
但这仅仅是对行为原因的假设.