Django内联链接到模型编辑

7

我知道这个问题已经被问了很多次,但是随着Django不断更新新版本,我会再次提出这个问题:

我正在使用模型User(Django User,不在我的models.py中),并创建另一个与User相关联的模型。

models.py

class Plan(models.Model):
    user = models.ForeignKey(User)

我可以通过在admin.py中添加以下代码,简单地显示我的用户中的每个Plan

class PlanInline(admin.TabularInline):
    model = Plan
    extra = 0

class MyUserAdmin(UserAdmin):
    ordering = ('-date_joined', 'username')
    inlines = [PlanInline,]

admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)

但事情将变得更加棘手。我希望添加一个模型,它具有指向 Plan 的外键:

class Order(models.Model):
    plan = models.ForeignKey('Plan')

我希望能够查看每个计划的所有订单。截至今天,在Django管理界面中无法嵌套内联(除非编辑HTML,但我想避免这种情况):

User 
     -> Plan 1 
              -> Order 1
              -> Order 2

     -> Plan 2
              -> Order 3

所以我的想法是在“用户管理”中只显示每个计划的链接,指向编辑“计划”的页面,并将“订单”作为内联显示:
class OrderInline(admin.TabularInline):
    model = Order
    extra = 0

class PlanAdmin(admin.ModelAdmin):
    inlines = [OrderInline,]

admin.site.register(Plan, PlanAdmin)

问题是,我如何在用户管理中显示一个计划的链接?
class MyUserAdmin(UserAdmin):
    ordering = ('-date_joined', 'username')
    ??? LINK ????

我看到了一些关于这个主题的解决方案:Django InlineModelAdmin: Show partially an inline model and link to the complete model,但它们有点“不干净”,因为它们要求我们在代码中编写HTML和绝对路径。

然后我看到了Djangoproject上的这个票:https://code.djangoproject.com/ticket/13163。它似乎正是我要找的,而且这个票已经“修复”了。所以我尝试添加像修复程序中的show_change_link = True一样的内容:

class PlanInline(admin.TabularInline):
    model = Plan
    extra = 0
    show_change_link = True

class MyUserAdmin(UserAdmin):
    ordering = ('-date_joined', 'username')
    show_change_link = True
    inlines = [UserProfileInline, PlanInline]

但是它没有起作用(我也没有日志或错误信息)。

有没有一种干净的方法可以做到这一点?


我不确定那个票是否符合你所描述的,但无论如何它只是在四天前关闭的。你是在运行 Django 存储库的 HEAD 吗? - Daniel Roseman
你是在运行 Django 仓库的 HEAD 吗?抱歉,我不太明白(我不是以英语为母语的人)。现在你指出来了,我猜修复程序要么是针对 1.7 版本的,要么是我的 Django 没有更新到修复版本。 - Raphael Laurent
2个回答

10

1
现在应该是正确的答案。 - lucemia

6
我建议添加一个自定义的 PlanInline 方法,用于返回链接并检查是否有所帮助。可以按照以下方式进行设计:
from django.utils.safestring import mark_safe
from django.core.urlresolvers import reverse

class PlanInline(TabularInline):
   model = Plan
   readonly_fields = ('change_link',)
   ...other options here...

   def change_link(self, obj):
      return mark_safe('<a href="%s">Full edit</a>' % \
                        reverse('admin:myapp_plan_change',
                        args=(obj.id,)))

基本上我们所要做的就是创建一个自定义方法,该方法返回到更改页面的链接(此特定实现未经测试,如果有任何解析错误,请见谅),然后将其添加到readonly_fields中,如此处所述:https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.readonly_fields 关于change_link方法的一些注意事项:您需要在视图名称中替换'myapp'为您实际的应用程序名称。 mark_safe方法只是将文本标记为安全,以使模板引擎将其呈现为html。

1
是的,这就是我选择的解决方案,因为似乎还没有其他方法(这个答案的变体:https://dev59.com/dHI95IYBdhLWcg3w2h56#21079750) - Raphael Laurent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接