Django: Class Based Parametric Views

I am trying to use the generic CreateView class to handle forms for a set of models inherited from the same base class.

class BaseContent(models.Model): ... class XContent(BaseContent): ... class YContent(BaseContent): ... 

To save DRY stuff, I want to define a single CreateView class that will handle all the inherited classes from BaseContent.

URL pattern for this view:

 url(r'^content/add/(?P<model_name>\w+)/$', ContentCreateView.as_view(), name='content_add') 

Something like this should work:

 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) 

But I get this exception:

 ContentCreateView is missing a queryset. Define ContentCreateView.model, ContentCreateView.queryset, or override ContentCreateView.get_object(). 

This suggestion does not seem to be fulfilled, because I do not want to set a class attribute, such as model or queryset , so that the model form is dynamically generated. Overriding get_object not like creating an object.

I tried to override get_queryset() , but this method does not accept the request parameter and does not have access to self.model_name , which comes from the url template.

In short, how can I get CreateView to use a dynamic form based on a parameter passed from a URL?

Thanks.

+7
source share
2 answers

You can set the model attribute from your urls.py , depending on the URL being called:

 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') 

I admit that this is not ideal, since you are repeating yourself a bit, but therefore you have the advantage of having different names for the same representation, depending on the model! Alternatively, you can also do something similar with overriding form_class ...

+1
source

There was this problem for some time, but found a solution. You need to override the submit method defined in as_view () (django.views.generic.base), something like this:

 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) ... ... 
+1
source

All Articles