添加时的Django Admin Model无法呈现相关的更改链接

时间:2019-04-05 12:03:55

标签: python django django-admin django-1.11

提供以下管理员设置:

class BrokerLocationSetForm(forms.ModelForm):
    class Meta:
        model = BrokerLocationSet
        fields = ('broker', 'program', 'label', 'locations')
        widgets = {
            'locations': autocomplete.ModelSelect2Multiple(url='admin-autocomplete-location', forward=('broker','program')),
        }
class BrokerLocationSetAdmin(admin.ModelAdmin):
    model = BrokerLocationSet
    form = BrokerLocationSetForm
    list_display=['broker', 'program', 'label']
admin.site.register(BrokerLocationSet, BrokerLocationSetAdmin)

当我尝试导航以在admin中为BrokerLocationSetForm添加视图时,会引发以下错误:

raise NoReverseMatch(msg) NoReverseMatch: Reverse for 'program_program_change' with arguments '(u'__fk__',)' not found. 1 pattern(s) tried: [u'admin/program/program/(?P<program_pk>\\d+)/change/$']

当我在shell中调试时:

 reverse('admin:broker_broker_change', 'myapp.urls', args=(u'__fk__',))

它输出:

  

u'/ admin / broker / broker / fk / change /'

但是:

reverse('admin:program_program_change', 'myapp.urls', args=(u'__fk__',))

我收到与上述相同的错误。经过一些调试后,我感觉到admin正在以某种方式将字符串而不是int传递给反向函数,同时它期望一个整数如下:

reverse('admin:program_program_change', 'myapp.urls', args=(u'1',))
  

u'/ admin / program / program / 1 / change /'

由于django管理员执行了此操作url reversing magic,因此我不确定应该在哪里自定义此错误以进行修复。我已经有了相当新的代码库,并且可以完全理解。

如何通过自定义管理模型或表单来解决上述错误。我不想更新'admin:program_program_change',但可能提供了通往同一视图的替代路线! 。可能吗 ?请指教!

1 个答案:

答案 0 :(得分:0)

但是我找到了解决方案,我不确定这是否是最好的解决方案。由于ProgramAdmin需要一个数字参数,而BrokerLocationSetAdmin的弹出链接需要一个带有字符串参数的路由。例如

reverse('admin:program_program_change', 'myapp.urls', args=(u'__fk__',))

解决方案是通过覆盖其ProgramAdmin方法,将另一个同名管理路径注入get_urls模型,如下所示:

class ProgramAdmin(admin.ModelAdmin):
   ...
   ...
   def get_urls(self):
        from django.conf.urls import url
        from functools import update_wrapper

        def wrap(view):
            def wrapper(*args, **kwargs):
                return self.admin_site.admin_view(view)(*args, **kwargs)
            wrapper.model_admin = self
            return update_wrapper(wrapper, view)

        urls = super(ProgramAdmin, self).get_urls()
        info = self.model._meta.app_label, self.model._meta.model_name
        alt_urls=[
            url(r'^(?P<program_pk>\w+)/change/$', wrap(self.change_view), name='%s_%s_change' % info),
        ]
        return urls+alt_urls

现在我们有两条名称相同但路径参数不同的路由,例如:

/admin/program/program/<program_pk>/change/ django.contrib.admin.options.change_view    admin:program_program_change
  

admin /程序/程序/(?P \ d +)/更改/ $

/admin/program/program/<program_pk>/change/ django.contrib.admin.options.change_view    admin:program_program_change
  

管理员/程序/程序/(?P \ w +)/更改/ $

根据上下文,将使用路由之一。