在Django管理界面中格式化多个多对多关联模型
我有两个简化的Django模型:
class Product(models.Model):
name = models.TextField()
price = models.IntegerField()
class Invoice(models.Model):
company = models.TextField()
customer = models.TextField()
products = models.ManyToManyField(Product)
我想在管理后台的发票页面上看到相关的产品,以一个漂亮的表格形式展示产品的各个字段,并且能够链接到各个产品的详细页面。
我最开始的想法是使用管理后台的内联功能,但Django为每个相关产品使用了一个下拉选择框。这种方式不能直接链接到产品页面,而且因为我有成千上万的产品,每个下拉框都会单独加载所有产品的名称,这样就变得非常慢。
于是我转而使用ModelAdmin.filter_horizontal,正如这里所建议的那样,这种方式使用了一个不同的控件实例,里面有一个所有产品的列表和一个相关产品的列表,你可以从前者中添加或移除产品到后者。这解决了速度慢的问题,但仍然没有显示相关产品的字段,而且也无法链接。
那么,我该怎么做呢?调整视图?重写ModelForms?我在谷歌上搜索了一下,没找到这样的代码示例……
2 个回答
这是一个老问题,但我今天又想到了它。
你可以在这里找到答案 - https://blog.ionelmc.ro/2012/01/19/tweaks-for-making-django-admin-faster/
代码如下:
class MyAdmin(admin.TabularInline):
fields = 'myfield',
def formfield_for_dbfield(self, db_field, **kwargs):
formfield = super(MyAdmin, self).formfield_for_dbfield(db_field, **kwargs)
if db_field.name == 'myfield':
# dirty trick so queryset is evaluated and cached in .choices
formfield.choices = formfield.choices
return formfield
这样做可以把你的等待时间从大约5分钟缩短到15秒左右。
也许这不是你想要的,但我想介绍一个叫做InvoiceItem的模型,它可以把发票(Invoice)和产品(Product)联系起来。这样,你就可以用两种一对多的关系,而不是多对多的关系。接着,你可以为InvoiceItem使用一个自定义的表单,并在这个表单中使用raw_id_fields来选择产品。
在InvoiceItem的表单中,你可以添加一些只读字段,这些字段会显示你需要的信息。你需要在表单的init方法中提供这些字段的数据,从InvoiceItem实例中读取。或者,你也可以从raw_id_field这个小部件派生出一个新的小部件,然后在这个小部件的render方法中添加一些来自产品模型的额外数据。