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

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

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!

Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.