Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Two scoops of django 1.6 - Ch7 & Ch8

flywindy
November 04, 2014

Two scoops of django 1.6 - Ch7 & Ch8

Ch 7. Function-and Class-Based Views
Ch 8. Best Practices for Function-Based Views

flywindy

November 04, 2014
Tweet

More Decks by flywindy

Other Decks in Programming

Transcript

  1. Two Scoops of Django Ch 7. Function-and Class-Based Views Ch

    8. Best Practices for Function-Based Views 2014/11/04 Michelle Leu @flywindy
  2. Agenda Django Views FBVs v.s. CBVs Best practices for FBVs

    URL Namespaces Loose Coupling Summary
  3. Django Views y = f(x) # math HttpResponse = view(HttpRequest)

    # FBV HttpResponse = View.as_view(HttpRequest) # CBV Django Views are functions
  4. 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)
  5. FBVs (Function Based Views) Django 1.7 Tutorial Part 3 #

    polls/views.py … from django.shortcuts import render from 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})
  6. CBVs (Class Based Views) Django 1.7 Tutorial Part 4 #

    polls/views.py … from django.views import generic from 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'
  7. 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'
  8. Decorators simple decorator template # EXAMPLE 8.5 import 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
  9. Decorators # EXAMPLE 8.6 # sprinkles/decorators.py from functools import wraps

    from . 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_sprinkles def sprinkle_detail(request, pk): sprinkle = get_object_or_404(Sprinkle, pk=pk) return render(request, "sprinkles/sprinkle_detail.html", {"sprinkle": sprinkle})
  10. URL Namespaces allow 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 project from django.conf.urls import include, url urlpatterns += patterns('', url(r'^tastings/', include('tastings.urls', namespace='tastings')), )
  11. URL Namespaces allow 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 project from 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})
  12. 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> ……
  13. 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
  14. 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)
  15. Loose Coupling # BAD EXAMPLE 7.1 from django.conf.urls import patterns,

    url from 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︖?
  16. 閃開,讓專業的來! 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
  17. 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.
  18. 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