首先,我对Python& Django,所以这可能是一个简单的问题。现在,我有一个这样的模型:
models.py
class Base(models.Model):
class Meta:
abstract = True
# base properties
class X(Base):
# extra props
class Y(Base):
# extra props
然后我想要一个X的视图和一个Y的视图,它基本上会做同样的事情,例如:
views.py
class BaseView(object):
template_name = "app/view.html"
Type = None
def __init__(self, type):
self.Type = type
def get_context_data(self, **kwargs):
context = super(BaseView, self).get_context_data(**kwargs)
context['data'] = get_object_or_404(self.Type, pk=kwargs["id"])
return context
class XView(BaseView, generic.TemplateView):
def __init__(self):
BaseView.__init__(self, X)
class YView(BaseView, generic.TemplateView):
def __init__(self):
BaseView.__init__(self, Y)
urls.py
urlpatterns = [
url(r'^xxxx/(?P<id>[0-9]+)$', views.XView.as_view(), name="view_x"),
url(r'^yyyy/(?P<id>[0-9]+)$', views.YView.as_view(), name="view_y"),
]
像这样,我将不得不重复所有(或大部分)表格,观点等。反正有没有避免这种重复? X和Y之间的差异只是表格中由django完美生成的几个字段。
我需要根据URL区分模型,例如:/ x /或example.com/Y/,其他所有内容都差不多。
仅供参考,使用Python 3,Django 1.9。
答案 0 :(得分:2)
您应该按照它们应该使用的方式使用Django通用视图类。如果您的所有类都在根据URL中的ID将对象传递给模板,则应使用内置的DetailView类;然后,您可以直接在URLconf中将模型和模板名称作为参数传递,而无需根据需要定义子类。
from django.views.generic import DetailView
urlpatterns = [
url(r'^xxxx/(?P<pk>[0-9]+)$', DetailView.as_view(model=X, template_name = "app/view.html"), name="view_x"),
url(r'^yyyy/(?P<pk>[0-9]+)$', DetailView.as_view(model=X, template_name = "app/view.html"), name="view_y"),
]
(注意DetailView期望URL参数被称为pk
而不是id
。)
如果您确实想为视图添加更多自定义行为,则可以继承DetailView;在多种URL模式中使用相同的视图类仍然是完全可能的。
答案 1 :(得分:1)
您可以通过几种方式删除重复项。在您的urls.py中,您可以将参数直接传递给您的视图:
# urls.py
urlpatterns = [
url(r'^xxxx/(?P<id>[0-9]+)$', views.BaseView.as_view(Type=X), name="view_x"),
url(r'^yyyy/(?P<id>[0-9]+)$', views.BaseView.as_view(Type=Y), name="view_x"),
]
这样,您就不需要定义XView
和YView
。您可以更进一步,并使用您的URL参数进行模型。
# urls.py
urlpatterns = [
url(r'^(?P<model>\w+)/(?P<id>[0-9]+)$', views.BaseView.as_view(), name='view_base'),
]
# views.py
class BaseView(View):
type_map = {
'xxxx': X,
'yyyy': Y,
}
def dispatch(self, request, *args, **kwargs):
model = kwargs.get('model')
self.type = self.type_map.get(model)
if self.type is None:
raise Http404
return super(BaseView, self).dispatch(request, *args, **kwargs)