我正在尝试使用通用的CreateView类来处理从同一基类继承的一组模型的表单。
class BaseContent(models.Model):
...
class XContent(BaseContent):
...
class YContent(BaseContent):
...
为了保持DRY,我想定义一个CreateView类,它将处理来自BaseContent的所有继承类。
该视图的网址格式为:
url(r'^content/add/(?P<model_name>\w+)/$', ContentCreateView.as_view(), name='content_add')
这样的事情应该有效:
class ContentCreateView(CreateView):
template_name = 'content_form.html'
def get_model(self, request):
# 'content' is the name of the application; model_name is 'xcontent', 'ycontent', ...
return ContentType.objects.get_by_natural_key('content', self.model_name)
但我得到了这个例外:
ContentCreateView is missing a queryset. Define ContentCreateView.model, ContentCreateView.queryset, or override ContentCreateView.get_object().
这个建议似乎并不成立,因为我不愿意设置像model
或queryset
这样的类属性来保持动态模型表单的生成。覆盖get_object
似乎与创建对象无关。
我尝试覆盖get_queryset()
,但此方法不接受request
参数,也无法访问来自网址格式的self.model_name
。
长话短说,如何让CreateView根据从网址传递的参数使用动态表单?
感谢。
答案 0 :(得分:1)
您可以设置model
的{{1}}属性,具体取决于所调用的网址:
urls.py
我承认它并不完美,因为你有点重复自己,但因此你可以为同一个视图设置不同的名称,具体取决于模型!除此之外,你还可以做一些与覆盖url(r'^content/add/x/$',
ContentCreateView.as_view(model=XContent), name='x_content_add'),
url(r'^content/add/y/$',
ContentCreateView.as_view(model=YContent), name='y_content_add')
...
答案 1 :(得分:1)
这个问题已经有一段时间了,但找到了解决方案。您需要覆盖as_view()(django.views.generic.base)中定义的调度方法,如下所示:
class ContentCreateView(CreateView):
def dispatch(self, request, *args, **kwargs):
for app in ['foo', 'bar']:
model = models.get_model(app, kwargs['modelname'])
if model:
self.model = model
break
return super(GenericEdit, self).dispatch(request, *args, **kwargs)
...
...