I am trying to use 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 keep things DRY, I want to define one CreateView class that will handle all inherited classes from BaseContent.
The url pattern for that view is:
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 am getting this exception:
ContentCreateView is missing a queryset. Define ContentCreateView.model, ContentCreateView.queryset, or override ContentCreateView.get_object().
This suggestion does not seem to hold as I am not willing to set a class attribute like model
or queryset
to keep the model form generated dynamic. Overriding the get_object
does not seem relevant for creating an object.
I tried overriding get_queryset()
but this method does not accept the request
parameter, nor have access to self.model_name
which comes from the url pattern.
Long story short, how can I make a CreateView use a dynamic form based on a parameter passed from the url?
Thanks.
In Class-based views, you have to call as_view() function so as to return a callable view that takes a request and returns a response. Its the main entry-point in request-response cycle in case of generic views. as_view is the function(class method) which will connect my MyView class with its url.
The most significant advantage of the class-based view is inheritance. In the class-based view, you can inherit another class, and it can be modified for the different use cases. It helps you in following the DRY principle. You won't have to write the same code over and over in your boilerplate.
object_list will contain the list of objects (usually, but not necessarily a queryset) that the view is operating upon. Ancestors (MRO) This view inherits methods and attributes from the following views: django.
You could set the model
attribute from your 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 it's not perfect as you are repeating yourself a bit, but therefore you have the advantage of having different names for the same view, depending on the model! Besides that you could also do something similar with overriding form_class
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With