gpt4 book ai didi

python - 使用模型(管理)继承时命名空间 ModelAdmin.get_urls 的 Django 方式是什么?

转载 作者:行者123 更新时间:2023-11-28 18:45:25 25 4
gpt4 key购买 nike

长话短说

在使用 ModelAdmin.get_urlsModelAdmins 通过继承扩展时,是否有一种方法可以定义(命名空间)命名良好的 View ?

最好不要求助于 ModelAdmin.model._meta 或其他一些稍微有问题的解决方案。

借口

在使用和继承自定义 ModelAdmins 时,通过 get_urls 添加的 View 名称会被覆盖。

也就是说, View 名称 admin:tighten 在以下示例中被覆盖:

class Screw(models.Model):
"A screw"

class HexCapScrew(Screw):
"A hex cap screw"


class ScrewAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super(ScrewAdmin, self).get_urls()
extra_urls = patterns('',
url(r'^tighten/$', self.tighten, name='tighten'),
)
return extra_urls + urls

def tighten(self, request):
pass

class HexCapScrewAdmin(ScrewAdmin):
pass


admin.site.register(Screw, ScrewAdmin)
admin.site.register(HexCapScrew, HexCapScrewAdmin)

在 shell 上会发生以下情况:

In [1]: reverse('admin:tighten')
Out[1]: u'/admin/parts/hexscrew/tighten/'

这当然是可以理解的,因为 HexCapScrewAdmin 的注册覆盖了 ScrewAdmin 中的tighten,但是现在不可能逆转 ScrewAdmin。收紧

首选解决方案

但是我希望能够

  1. 分别引用两个 View 和
  2. 最好在自己的实例命名空间中拥有 View 。

到目前为止的进展

我想到的最好的设置是以下设置(可以直接复制粘贴到某些应用程序进行测试):

from django.contrib import admin
from django.db import models

class Screw(models.Model):
"A screw"
class Meta:
app_label = 'parts'


class HexCapScrew(Screw):
"A hex cap screw"
class Meta:
app_label = 'parts'
proxy = True


class ScrewAdmin(admin.ModelAdmin):
def tighten(self, request):
pass

def get_urls(self):
urls = super(ScrewAdmin, self).get_urls()
extra_urls = patterns('',
url(r'^tighten/$', self.tighten, name='tighten'),
)
# Find out the slugified name of the model this admin is bound to
# TODO: Feels dirty
model_name = self.model._meta.model_name

# Add the to `extra_urls` to their own namespace
namespaced_extra_urls = patterns('',
url(r'^', include(extra_urls, namespace=model_name, app_name='screw')),
)
return namespaced_extra_urls + urls


class HexCapScrewAdmin(ScrewAdmin):
pass

admin.site.register(Screw, ScrewAdmin)
admin.site.register(HexCapScrew, HexCapScrewAdmin)

现在我有以下内容:

In [1]: reverse('admin:screw:tighten')
Out[1]: u'/admin/parts/screw/tighten/'

In [2]: reverse('admin:hexscrew:tighten')
Out[2]: u'/admin/parts/hexscrew/tighten/'

In [3]: reverse('admin:screw:tighten', current_app='hexscrew')
Out[3]: u'/admin/parts/hexscrew/tighten/'

这很好用,但包含一些 hackery。

这是可用的最好的还是我只是遗漏了什么?有什么建议吗?

(至少还有一种方法是像 Django 的 ModelAdmin.get_urls 使用 ModelAdmin.model._metaparametrize the view names 那样,但我会使用命名空间。 )

最佳答案

如果你看看管理员做这件事的方式here ,您会看到除了定义 url 之外,模型管理员还将 app_label 和 model_name 作为 url 名称的前缀,从而避免了子类化问题。它还具有防止未授权用户访问 View 的优势(使用 self.admin_site.admin_view 装饰器)。您的 get_urls() 方法将变为:

 def get_urls(self):
from django.conf.urls import url

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

info = self.model._meta.app_label, self.model._meta.model_name

urlpatterns = super(ScrewAdmin, self).get_urls()
urlpatterns.append(
url(r'^tighten/$', wrap(self.tighten), name='%s_%s_tighten' % info))
return urlpatterns

然后,您可以像这样查找您的网址:reverse('admin:app_screw_tighten')reverse('admin:app_hex_screw_tighten')

关于python - 使用模型(管理)继承时命名空间 ModelAdmin.get_urls 的 Django 方式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21125734/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com