================= Class-Based Views ================= The Old Way ----------- You probably use one of these two ways for making a view that renders a form and then validates it on submit:: @login_required def awesome_view(request): if request.method == "POST": form = AwesomeForm(request.POST) if form.is_valid(): form.save() return HttpResponseRedirect(reverse('awesome')) else: form = AwesomeForm() return render(“awesome.html”, {'form': form}) Or:: @login_required def awesome_view(request): form = AwesomeForm(request.POST or None) if form.is_valid(): form.save() return HttpResponseRedirect(reverse('awesome') return render("awesome.html", {'form': form}) These both work and they're fine but you often have to repeat yourself and you have to deal with ``if`` conditions when debugging. Not much fun, not very clean. The New Way ----------- So, here's a class-based way of doing it:: Class MyAwesomeView(TemplateView): template_name = "awesome.html" def get(self, request): form = AwesomeForm() return self.render_to_response({'form': form}) def post(self, request): form = AwesomeForm(request.POST) if form.is_valid(): form.save() return HttpResponseRedirect(reverse('awesome')) return self.render_to_response({'form': form}) You have a ``template_name`` variable at the top that specifies the template for the view. Below that is the ``get()`` method that handles all ``GET`` requests. Typically it just takes ``self`` and ``request`` but if your route requires more arguments, they'll need to be specified here, too. And, surprise, surprise, below that is ``post()`` that takes care of your ``POST`` requests. Same arguments as ``get()`` since it has to be hit by the same route. What about @login_required? --------------------------- True, we don't have ``@login_required`` on our methods and it won't work if you just add it there. What you can do, though, is wrap the ``dispatch()`` method and that will wrap all methods from that view with whatever decorators you provide. Example below:: @method_decorator(login_required) def dispatch(self, *args, **kwargs): return super(MyAwesomeView, self).dispatch(*args, **kwargs) Add this into your class and you should be safe from all those nasty unauthenticated users. URLs ---- How do you add these views to your URLs? Glad you asked:: from project.views import MyAwesomeView [...] url(r’^awesome/$’, MyAwesomeView.as_view(), name=”awesome”) [...] If you really hate having to import each view, at the bottom of your ``views.py`` file, you can do something like: ``awesome_view = MyAwesomeView.as_view()`` and then set your URLs view as ``app.awesome_view``. I don't think this is needed, but to each his/her own. Thanks and I hope that helps everyone get a small grip on class-based views. There are many other class-based views available, such as ``FormView`` for handling form rendering and validation (so this entire method wouldn't be needed) but there are very little docs for them. **Let's write them!**