two scoops of django 1.6 - ch7, ch8
DESCRIPTION
Ch 7. Function-and Class-Based Views Ch 8. Best Practices for Function-Based ViewsTRANSCRIPT
![Page 1: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/1.jpg)
Two Scoops of DjangoCh 7. Function-and Class-Based Views
Ch 8. Best Practices for Function-Based Views
2014/11/04Michelle Leu @flywindy
![Page 2: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/2.jpg)
Agenda
Django Views
FBVs v.s. CBVs
Best practices for FBVs
URL Namespaces
Loose Coupling
Summary
![Page 3: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/3.jpg)
Django Views
y = f(x) # math
HttpResponse = view(HttpRequest) # FBV
HttpResponse = View.as_view(HttpRequest) # CBV
Django Views are functions
![Page 4: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/4.jpg)
Django Views
keep business logic out of Views
model methods
manger methods
general utility helper function
forms
Business logic is the part of the program
that encodes the real-world business rules that determine how data can be created,
displayed, stored, and changed…….
(From wikipedia)
![Page 5: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/5.jpg)
FBVs (Function Based Views)
Django 1.7 Tutorial Part 3 # polls/views.py…from django.shortcuts import renderfrom polls.models import Question
def index(request): latest_question_list = Question.objects.all().order_by('-pub_date')[:5] context = {'latest_question_list': latest_question_list} return render(request, 'polls/index.html', context)
def detail(request, question_id): question = get_object_or_404(Question, pk=question_id) return render(request, 'polls/detail.html', {'question': question})
def results(request, question_id): question = get_object_or_404(Question, pk=question_id) return render(request, 'polls/results.html', {'question': question})
![Page 6: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/6.jpg)
CBVs (Class Based Views)
Django 1.7 Tutorial Part 4
# polls/views.py…from django.views import genericfrom polls.models import Question
class IndexView(generic.ListView): template_name = 'polls/index.html' context_object_name = 'latest_question_list'
def get_queryset(self): """Return the last five published questions.""" return Question.objects.order_by('-pub_date')[:5]
class DetailView(generic.DetailView): model = Question template_name = 'polls/detail.html'
class ResultsView(generic.DetailView): model = Question template_name = 'polls/results.html'
![Page 7: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/7.jpg)
CBVs v.s. FBVs
![Page 8: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/8.jpg)
CBVs v.s. FBVs
For new comer: FBVs
For new project: CBVs
For past project: FBVs for most views, CBVs only for views that need to be subclassed.
Write custom 403, 404, and 500 error handlers: FBVs # root URLconf
handler500 = 'mysite.views.my_custom_error_view'
![Page 9: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/9.jpg)
Best practices for FBVs
Pass HttpRequest Object
Pass HttpResponse Object
Decorators
![Page 10: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/10.jpg)
Decorators
simple decorator template
# EXAMPLE 8.5import functools
def decorator(view_func):
@functools.wraps(view_func) def new_view_func(request, *args, **kwargs): # modify HttpRequest object here response = view_func(request, *args, **kwargs) # modify HttpResponse object here return response
return new_view_func
![Page 11: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/11.jpg)
Decorators
# EXAMPLE 8.6# sprinkles/decorators.pyfrom functools import wrapsfrom . import utils
def check_sprinkles(view_func): @wraps(view_func) def new_view_func(request, *args, **kwargs): # modify HttpRequest object here request = utils.can_sprinkle(request) # request.can_sprinkle response = view_func(request, *args, **kwargs) # modify HttpResponse object here return response return new_view_func
# EXAMPLE 8.7# sprinkles/views.py...from .decorators import /check_sprinkles
@check_sprinklesdef sprinkle_detail(request, pk): sprinkle = get_object_or_404(Sprinkle, pk=pk)
return render(request, "sprinkles/sprinkle_detail.html", {"sprinkle": sprinkle})
![Page 12: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/12.jpg)
URL Namespacesallow you to uniquely reverse named URL patterns even if different applications use the same URL names.
are specified using the ':' operator. For example, the main index page of the admin application is referenced using 'admin:index'. This indicates a namespace of 'admin', and a named URL of ‘index'.
can also be nested.
# EXAMPLE 7.3# urls.py at root of projectfrom django.conf.urls import include, url
urlpatterns += patterns('', url(r'^tastings/', include('tastings.urls', namespace='tastings')),)
![Page 13: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/13.jpg)
URL Namespacesallow you to uniquely reverse named URL patterns even if different applications use the same URL names.
are specified using the ':' operator. For example, the main index page of the admin application is referenced using 'admin:index'. This indicates a namespace of 'admin', and a named URL of ‘index'.
can also be nested.
# EXAMPLE 7.3# urls.py at root of projectfrom django.conf.urls import include, url
urlpatterns += patterns('', url(r'^tastings/', include('tastings.urls', namespace='tastings')),)
# EXAMPLE 7.4# tastings/views.py snippet……class TasteUpdateView(UpdateView): model = Tasting def get_success_url(self): return reverse("tastings:detail", kwargs={"pk": self.object.pk})
![Page 14: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/14.jpg)
URL Namespaces
# EXAMPLE 7.5# tastings/detail.html snippet……<ul> {% for tasting in tastings %} <li> <a href="{% url "tastings:detail" tasting.pk %}">{{ tasting.title }}</a> <small> (<a href="{% url "tastings:update" tasting.pk %}">update</a>) </small> </li> {% endfor %}<ul>……
![Page 15: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/15.jpg)
Why URL Namespaces?
Makes for shorter, more obvious and DRY URL names
Increases interoperability with Third-party libraries
Easier searches, upgrades, and refactors
Allow for more app and template reverse tricks
![Page 16: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/16.jpg)
Loose Coupling
鬆散耦合
相對於 緊密耦合(tight coupling)
In computing and systems design a loosely coupled system is one in which each of its components has, or makes use of, little or no knowledge of the definitions of other separate components ….… (From wikipedia)
![Page 17: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/17.jpg)
Loose Coupling# BAD EXAMPLE 7.1
from django.conf.urls import patterns, urlfrom django.views.generic import /DetailView
from tastings.models import Tasting
urlpatterns = patterns('', url(r'^(?P<pk>\d+)/$', DetailView.as_view( model=Tasting, template_name='tastings/detail.html'), name='detail'), url(r'^(?P<pk>\d+)/results/$', DetailView.as_view( model=Tasting, template_name='tastings/results.html'), name='results'),)
authentication︖?
![Page 18: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/18.jpg)
閃開,讓專業的來!
Loose Coupling
# EXAMPLE 7.1# tastings/views.py
from django.views.generic import /DetailView
from tastings.models import Tasting
class TasteDetailView(DetailView): model = Tasting
class TasteResultsView(TasteDetailView): template_name = 'tastings/results.html'
# EXAMPLE 7.1# tastings/urls.py
from django.conf.urls import patterns, url
from . import views
urlpatterns = patterns('', url(r'^(?P<pk>\d+)/$', views.TasteDetailView.as_view(), name='detail'), url(r'^(?P<pk>\d+)/results/$', views.TasteResultsView.as_view(), name='results'),)
<app_label>/<model_name><template_name_suffix>.html -> tastings/tasting_detail.html
![Page 19: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/19.jpg)
Summary
Don’t Repeat Yourself. (DRY)
Do one thing and do it well.
Views should handle presentation logic.
Less code is better, and keep it simple.
Complex nested-if blocks are to be avoided.
![Page 20: Two scoops of django 1.6 - Ch7, Ch8](https://reader031.vdocuments.mx/reader031/viewer/2022020105/559c1e271a28abd3298b4676/html5/thumbnails/20.jpg)
References
Classy Class-Based Views: http://ccbv.co.uk/
Django project 1.7 tutorial: https://docs.djangoproject.com/en/1.7/intro/tutorial01/
Django project 1.7 - URL namespaces: https://docs.djangoproject.com/en/1.7/topics/http/urls/#url-namespaces
Django Girls 學習⼿手冊: http://djangogirlstaipei.gitbooks.io/django-girls-taipei-tutorial/
two-scoops-of-django-1.6 issues: https://github.com/twoscoops/two-scoops-of-django-1.6/issues?q=is%3Aopen+is%3Aissue