Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Class Based View for both Create and Update

Say I want to create a Class Based View which both updates and creates an object. From a previous question I worked out I could do one of the following things:

1) Use 2 generic views CreateView and UpdateView which I think would mean having two URL's pointing to two different classes.

2) Use a class based view which inherits base View, which I think would mean having two URL's pointing to just 1 class (I created which inherits View).

I have two questions:

a) Which is better?

b) ccbv.co.uk shows a base View, but I don't see any get, post etc methods documented, is this correct?

like image 811
GrantU Avatar asked Jun 19 '13 13:06

GrantU


People also ask

Which is better class-based view or function based view Django?

Class based views are excellent if you want to implement a fully functional CRUD operations in your Django application, and the same will take little time & effort to implement using function based views.

How do class-based views work in Django?

A view is a callable which takes a request and returns a response. This can be more than just a function, and Django provides an example of some classes which can be used as views. These allow you to structure your views and reuse code by harnessing inheritance and mixins.

How do I add a context to a class-based view in Django?

There are two ways to do it – one involves get_context_data, the other is by modifying the extra_context variable. Let see how to use both the methods one by one. Explanation: Illustration of How to use get_context_data method and extra_context variable to pass context into your templates using an example.

What is generic class-based view in Django?

Django's generic views were developed to ease that pain. They take certain common idioms and patterns found in view development and abstract them so that you can quickly write common views of data without having to write too much code.


1 Answers

I ran into a situation where I wanted something like this. Here's what I came up with (do note that if you're trying to use it as an update view and it can't find the requested object, it'll behave as a create view rather than throwing a 404):

from django.views.generic.detail import SingleObjectTemplateResponseMixin from django.views.generic.edit import ModelFormMixin, ProcessFormView  class CreateUpdateView(     SingleObjectTemplateResponseMixin, ModelFormMixin, ProcessFormView ):      def get_object(self, queryset=None):         try:             return super(CreateUpdateView,self).get_object(queryset)         except AttributeError:             return None      def get(self, request, *args, **kwargs):         self.object = self.get_object()         return super(CreateUpdateView, self).get(request, *args, **kwargs)      def post(self, request, *args, **kwargs):         self.object = self.get_object()         return super(CreateUpdateView, self).post(request, *args, **kwargs) 

It turns out that UpdateView and CreateView inherit from exactly the same classes and mixins. The only difference is in the get/post methods. Here's how they're defined in the Django source (1.8.2):

class BaseCreateView(ModelFormMixin, ProcessFormView):     """     Base view for creating an new object instance.      Using this base class requires subclassing to provide a response mixin.     """     def get(self, request, *args, **kwargs):         self.object = None         return super(BaseCreateView, self).get(request, *args, **kwargs)      def post(self, request, *args, **kwargs):         self.object = None         return super(BaseCreateView, self).post(request, *args, **kwargs)   class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView):     """     View for creating a new object instance,     with a response rendered by template.     """     template_name_suffix = '_form'   class BaseUpdateView(ModelFormMixin, ProcessFormView):     """     Base view for updating an existing object.      Using this base class requires subclassing to provide a response mixin.     """     def get(self, request, *args, **kwargs):         self.object = self.get_object()         return super(BaseUpdateView, self).get(request, *args, **kwargs)      def post(self, request, *args, **kwargs):         self.object = self.get_object()         return super(BaseUpdateView, self).post(request, *args, **kwargs)   class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView):     """     View for updating an object,     with a response rendered by template.     """     template_name_suffix = '_form' 

As you can see, the CreateView get and post methods set self.object = None while the UpdateView sets it to self.get_object(). All I've done is combine those two in my CreateUpdateView.get_object method which attempts to call the parent class' get_object and returns None rather than raising an exception if there is no object.

To serve a 404 page when used as an update view, you could probably override as_view and pass it an update_only boolean argument. If update_only is True and the view can't find the object, then raise the 404.

like image 65
scubabuddha Avatar answered Sep 30 '22 19:09

scubabuddha