Django Admin中外键关联模型的类似内联解决方案
我有几个顾客,他们会预约时间。每个预约都有一个顾客,但一个顾客可以预约多个不同时间的预约。
class Customer(model.Model):
def __unicode__(self):
return u'%s' % (self.name,)
name = models.CharField(max_length=30)
# and about ten other fields I'd like to see from the admin view.
class Appointment(models.Model):
datetime = models.DateTimeField()
customer = models.ForeignKey("Customer")
class Meta:
ordering = ('datetime',)
现在,当管理员想要查看按时间排序的预约安排时,有时候他们想了解某个预约的顾客信息。目前,他们需要记住顾客的名字,然后从预约页面跳转到顾客的管理页面,找到记住的顾客,才能查看他们的信息。
理想情况下,如果能在管理员界面直接显示顾客信息就好了。不过,我发现只有当顾客有一个指向预约的外键时,才能在预约的管理页面上创建一个CustomerInline
。但是Django给我报错,提示顾客没有指向预约的外键。有没有人知道类似的功能,但当预约有一个指向顾客的外键时该怎么做?
注意:我简化了模型;实际上,顾客字段除了名字外还有大约10个其他字段(一些是自由文本),所以把所有信息放在__unicode__
里并不实际。
4 个回答
在你的预约(Appointments)管理类(ModelAdmin)中,你需要声明以下这个方法:
class MySuperModelAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if obj:
# create your own model admin instance here, because you will have the Customer's
# id so you know which instance to fetch
# something like the following
inline_instance = MyModelAdminInline(self.model, self.admin_site)
self.inline_instances = [inline_instance]
return super(MySuperModelAdmin, self).get_form(request, obj, **kwargs)
想了解更多信息,可以查看这个函数的源代码,这样你就能知道你可以使用哪些内容。
https://code.djangoproject.com/browser/django/trunk/django/contrib/admin/options.py#L423
在Django中,想要做到这一点并不简单。因为内联(inlines)是为了跟踪关系而设计的,主要是从后往前查找。
一个比较好的替代方法是给用户对象提供一个链接。在列表视图中,这个操作非常简单:
在你的预约模型中添加一个方法,比如:
def customer_admin_link(self):
return '<a href="%s">Customer</a>' % reverse('admin:app_label_customer_change %s') % self.id
customer_admin_link.allow_tags = True
customer_admin_link.short_description = 'Customer'
然后在你的ModelAdmin中添加:
list_display = (..., 'customer_admin_link', ...)
还有一种解决方案可以让你得到想要的效果,不过会稍微复杂一些,那就是定义一个自定义的管理模板。如果你这样做,你基本上可以实现任何功能。这里有一个我之前用过的指南来解释这个过程:
http://www.unessa.net/en/hoyci/2006/12/custom-admin-templates/简单来说,就是从Django的源代码中复制更改表单,并添加代码来显示客户信息。
补充一下@John的回答,说明一下你希望在变更列表中看到什么:
return '<a href="%s">%s</a>' % (
reverse('admin:applabel_customer_change', (self.customer.id,)),
self.customer.name # add more stuff here
)
如果想把这个添加到变更表单中,可以参考:在Django管理后台的变更表单中,在两个模型字段之间添加自定义HTML