際際滷

際際滷Share a Scribd company logo
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
Agenda 
Django Views 
FBVs v.s. CBVs 
Best practices for FBVs 
URL Namespaces 
Loose Coupling 
Summary
Django Views 
Django Views are functions 
y = f(x) # math 
HttpResponse = view(HttpRequest) # FBV 
HttpResponse = View.as_view(HttpRequest) # CBV
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 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})
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): 
class DetailView(generic.DetailView): 
model = Question 
template_name = 'polls/detail.html' 
class ResultsView(generic.DetailView): 
model = Question 
template_name = 'polls/results.html' 
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]
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.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
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})
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(/slideshow/two-scoops-of-django-16-ch7-ch8/41108153/r&)), 
) 
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 
柊骼栽 
豢 o畜骼栽(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, 
url 
from django.views.generic import / 
DetailView 
from tastings.models import Tasting 
urlpatterns = patterns('', 
url(/slideshow/two-scoops-of-django-16-ch7-ch8/41108153/r&)/$', 
DetailView.as_view( 
model=Tasting, 
template_name='tastings/ 
detail.htm'), 
name='detail'), 
url(/slideshow/two-scoops-of-django-16-ch7-ch8/41108153/r&)/results/$', 
DetailView.as_view( 
model=Tasting, 
template_name='tastings/ 
results.html'), 
name='results'), 
) 
authentication?
Loose Coupling 
W_I議蹌 
# 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(/slideshow/two-scoops-of-django-16-ch7-ch8/41108153/r&)/$', 
views.TasteDetailView.as_view(), 
name='detail'), 
url(/slideshow/two-scoops-of-django-16-ch7-ch8/41108153/r&)/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 W?返: 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
Two scoops of django 1.6  - Ch7, Ch8

More Related Content

Two scoops of django 1.6 - Ch7, Ch8

  • 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 Django Views are functions y = f(x) # math HttpResponse = view(HttpRequest) # FBV HttpResponse = View.as_view(HttpRequest) # CBV
  • 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): class DetailView(generic.DetailView): model = Question template_name = 'polls/detail.html' class ResultsView(generic.DetailView): model = Question template_name = 'polls/results.html' 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]
  • 8. 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'
  • 9. Best practices for FBVs Pass HttpRequest Object Pass HttpResponse Object Decorators
  • 10. 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
  • 11. 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})
  • 12. 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(/slideshow/two-scoops-of-django-16-ch7-ch8/41108153/r&)), ) 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})
  • 13. 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> ´´
  • 14. 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
  • 15. Loose Coupling 柊骼栽 豢 o畜骼栽(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)
  • 16. 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(/slideshow/two-scoops-of-django-16-ch7-ch8/41108153/r&)/$', DetailView.as_view( model=Tasting, template_name='tastings/ detail.htm'), name='detail'), url(/slideshow/two-scoops-of-django-16-ch7-ch8/41108153/r&)/results/$', DetailView.as_view( model=Tasting, template_name='tastings/ results.html'), name='results'), ) authentication?
  • 17. Loose Coupling W_I議蹌 # 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(/slideshow/two-scoops-of-django-16-ch7-ch8/41108153/r&)/$', views.TasteDetailView.as_view(), name='detail'), url(/slideshow/two-scoops-of-django-16-ch7-ch8/41108153/r&)/results/$', views.TasteResultsView.as_view(), name='results'), ) <app_label>/<model_name><template_name_suffix>.html -> tastings/tasting_detail.html
  • 18. 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.
  • 19. 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 W?返: 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