two scoops of django 1.6 - ch7, ch8

Post on 08-Jul-2015

373 Views

Category:

Documents

8 Downloads

Preview:

Click to see full reader

DESCRIPTION

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

TRANSCRIPT

Two Scoops of DjangoCh 7. Function-and Class-Based Views

Ch 8. Best Practices for Function-Based Views

2014/11/04Michelle Leu @flywindy

Agenda

Django Views

FBVs v.s. CBVs

Best practices for FBVs

URL Namespaces

Loose Coupling

Summary

Django Views

y = f(x) # math

HttpResponse = view(HttpRequest) # FBV

HttpResponse = View.as_view(HttpRequest) # CBV

Django Views are functions

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)

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})

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'

CBVs v.s. FBVs

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'

Best practices for FBVs

Pass HttpRequest Object

Pass HttpResponse Object

Decorators

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

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})

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')),)

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})

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>……

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

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)

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︖?

閃開,讓專業的來!

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

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.

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

top related