28. Dispatch HTTP Verbs
from django.http import HttpResponse
def my_view(request):
if request.method == 'GET':
# view logic
return HttpResponse('result')
if request.method == 'POST':
# view logic
return HttpResponse('result')
from django.views.generic import View
from django.http import HttpResponse
class MyView(View):
?
?
29. dispatch()
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method;
# if a method doesn't exist, defer to the error handler.
# Also defer to the error handler if the
# request method isn't on the approved list.
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
30. From FBV to CBV
FBV CBV
from django.http import HttpResponse
def my_view(request):
if request.method == 'GET':
# view logic
return HttpResponse('result')
if request.method == 'POST':
# view logic
return HttpResponse('result')
from django.views.generic import View
from django.http import HttpResponse
class MyView(View):
def get(self, request):
# view logic
return HttpResponse('result')
def post(self, request):
# view logic
return HttpResponse('result')
32. Display A Blog Post (FBV v.s. CBV)
http://blog.mysite.com/post/12997/
FBV CBV
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request,
'post_detail.html',
{'post’: post})
class PostDetailView(DetailView):
model = Post
42. class SecretMessageMixin(object):
def get_context_data(self,**kwargs):self).get_context_data(**kwargs)
context[“secret_message] = ‘Hello’
return context
class PostDetailView(SecretMessageMixin, DetailView):
model = Post
Customize - Mixins
{% extends ‘base.html’ %}
div
Secret Message is {{ secret_message }}
/div
views.py
post_detail.html
43. Mixins
1. Mixins should inherit from Python’s built-in object type
2. Base view by Django always go to the right
3. Mixins go to the left of the base view
class SecretMessageMixin(object):
…
class PostDetailView(SecretMessageMixin, DetailView):
model = Post
1
3 2
45. Tip1. Access Control
from django.contrib.auth.decorators import login_required
class LoginRequiredMixin(object):
@classmethod
def as_view(cls, **initkwargs):
view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
return login_required(view)
class PostDetail(LoginRequiredMixin, DetailView):
model = Post
47. Tip2. Where should I put my code ?
dispatch()
get_context_data()
form_valid()
form_invalid()
get_queryset()
• Custom actions on every Http request
• Add additional object to context
• Custom Actions on Views with Valid Forms
• Custom Actions on Views with Invalid Forms
• Filter posts by query string
48. Custom Actions on Views with Valid Forms form_valid()
Custom Actions on Views with Invalid Forms form_invalid()
from django.views.generic import CreateView
from braces.views import LoginRequiredMixin
from .models import Post
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ('title', ‘content')
def form_invalid(self, form):
# Do custom logic
return super(PostCreateView, self).form_valid(form)
def form_valid(self, form):
# Do custom logic
return super(PostCreateView, self).form_valid(form)
49. Filter posts by query string get_queryset()
from django.views.generic import ListView
from .models import Post
class PostListView(ListView):
model = Post
def get_queryset(self):
queryset = super(PostListView, self).get_queryset()
q = self.request.GET.get('q')
if q:
queryset = qs.filter(title__icontains=q)
return queryset
{# templates/blog/_post_search.html #}
form action={% url “post-list %} method=GET
input type=text name=q/
button type=submitSearch/
/form
50. Tip3. Access url parameters
http://blog.mysite.com/author/john/
url(r’^author/(?Pusernamew+)/$’, AuthorPostListView.as_view())
from django.views.generic import ListView
from .models import Post
class AuthorPostListView.as_view(ListView):
model = Post
paginate_by = 10
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs['author'])
queryset = super(AuthorPostListView.as_view, self).get_queryset()
return queryset.filter(author=user)
51. Tip4. Using the View Object
class PostMixin(object):
@cached_property
def likes_and_favorites(self):
likes = self.objects.likes()
favorites = self.objects.favorites()
return {
'likes': likes,
'favorites': favorites,
'favorites_count': favorites.count(),
}
from django.utils.functional import cached_property
from django.views.generic import UpdateView
from .tasks import notify_users_who_favorited
class PostUpdateView(PostMixin, UpdateView):
model = Post
fields = ('title', 'content')
def form_valid(self, form):
notify_users_who_favorited(
instance=self.object,
favorites = self.like_and_favorites['favorites']
)
58. Guidelines
• Less view code is better
• Never repeat code in views
• Views should handle presentation logic
• Keep your view simple
• Use FBV for 403, 404, 500 error handlers
• Keep your mixins simple