Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: parametric class-based views

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.

like image 395
onurmatik Avatar asked Jun 25 '11 14:06

onurmatik


People also ask

What does As_view do in Django?

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.

Why we use class-based views Django?

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.

What is Object_list in Django?

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.


1 Answers

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...

like image 116
Bernhard Vallant Avatar answered Oct 15 '22 13:10

Bernhard Vallant