SlideShare a Scribd company logo
Two Scoops of Django
Chapter 9 Common Patterns for Forms

Alfred
Forms
This chapter goes explicitly into the
concepts of forms, models and CBVs. There
are five common patterns.
Pattern 1: Simple ModelForm
with default Validators
Pattern 1: Simple ModelForm
with default Validators

• Auto generated a model form based on the
Flavor model.
Pattern 2: Custom Form Field
Validators in ModelForm
Pattern 2: Custom Form Field
Validators in ModelForm

• Customize your validator.
Pattern 2: Custom Form Field
Validators in ModelForm(cont.)

• To use it

•what if we wanted to use validate_tasty() in just forms?	

•what if we wanted to assign it to other fields?
Pattern 2: Custom Form Field
Validators in ModelForm(cont.)

• To create a customized form...
#forms.py	
from django import forms	
from core.validators import validate_tasty	
from .models import Flavor	

!
class FlavorForm(forms.ModelForm):	
def __init__(self, *args, **kwargs):	
super(FlavorForm, self).__init__(args, kwargs)	
self.fields["title"].validators.append(validate_tasty)	
self.fields["slug"].validators.append(validate_tasty)	

!
class Meta:	
model = Flavor
Pattern 2: Custom Form Field
Validators in ModelForm(cont.)
#views.py	
from django.contrib import messages	
from django.views.generic import CreateView, UpdateView, DetailView	
from braces.views import LoginRequiredMixin	
from .models import Flavor	
from .forms import FlavorForm	

!

class FlavorActionMixin(object):	
model = Flavor	
@property	
def action(self):	
msg = "{0} is missing action.".format(self.__class__)	
raise NotImplementedError(msg)	

!
!

def form_valid(self, form):	
msg = "Flavor {0}!".format(self.action)	
messages.info(self.request, msg)	
return super(FlavorActionMixin, self).form_valid(form)	

class FlavorCreateView(LoginRequiredMixin, FlavorActionMixin, CreateView):	
model = Flavor	
action = "created"	
form_class = FlavorForm	

!

class FlavorUpdatedView(LoginRequiredMixin, FlavorActionMixin, UpdateView):	
model = Flavor	
action = "updated"	
form_class = FlavorForm	

!

class FlavorDetailView(DetailView):	
model = Flavor
Pattern 3: Overriding the clean
stage of Validation
Pattern 3: Overriding the clean
stage of Validation

• Multi-field validation	

• Validation involving existing data from the
database that has already been validated.	

clean() and clean<field_name>()	

•

clean() method is the place to validate two or more fields
against each other, since it’s not specific to any one particular
field.	


•

The clean validation stage is a better place to attach validation
against persistent data.
Pattern 3: Overriding the clean
stage of Validation(cont.)

• We are going to check the remaining amount
is enough or not...

class IceCreamOrderForm(forms.ModelForm):	
slug = forms.ChoiceField("Flavor")	
toppings = forms.CharField()	

!
!

def __init__(self, *args, **kwargs):	
super(IceCreamOrderForm, self).__init__(*args, **kwargs)	
self.fields["slug"].choices = [ (x.slug, x.title) for x in Flavor.objects.all() ]	
def clean_slug(self):	
slug = self.cleaned_data["slug"]	
if Flavor.objects.get(slug=slug).scoops_remainin <= 0:	
msg = u"sorry, we are out of flavor"	
raise forms.ValidationError(msg)	
return slug
Pattern 3: Overriding the clean
stage of Validation(cont.)

• And then check multiple fields..
class IceCreamOrderForm(forms.ModelForm):	
...	
def clean(self):	
cleaned_data = super(IceCreamOrderForm, self).clean()	
slug = cleaned_data.get("slug", "")	
toppings = cleaned_data.get("toppings", "")	
if u"chocolate" in slug.lower() and u"chocolate" in toppings.lower():	
msg = u"Your order has too much chocolate."	
raise forms.ValidationError(msg)	
return cleaned_data
Pattern 4: Hacking Form Fields
Pattern 4: Hacking Form Fields

• you have a ice cream store, some of fields
are required, some are not.

from django.db import models	
from django.core.urlresolvers import reverse	
# Create your models here.	

!
class IceCreamStore(models.Model):	
title = models.CharField(max_length=100)	
block_address = models.TextField()	
phone = models.CharField(max_length=20, blank=True)	
description = models.TextField(blank=True)	
def get_absolute_url(self):	
return reverse("store_detail", kwargs={"pk":self.pk})
Pattern 4: Hacking Form
Fields(cont.)

• Old style v.s. better style

from django import forms	
from models import IceCreamStore	
class IceCreamStoreUpdateForm(forms.ModelForm):	

!
phone = forms.CharField(required=True) #duplicate	
description = forms.TextField(required=True) #duplicate	

!
class Meta:	
model = IceCreamStore	
class IceCreamStoreUpdateForm(forms.ModelForm):	

!
!

class Meta:	
model = IceCreamStore	
def __init__(self, *args, **kwargs):	
super(IceCreamStoreUpdateForm, self).__init__(*args, **kwargs)	
self.fields["phone"].required=True	
self.fields["description"].required=True
Pattern 4: Hacking Form
Fields(cont.)

• Much Better Style
from django import forms	
from models import IceCreamStore	

!

class IceCreamStoreCreateForm(forms.ModelForm):	
class Meta:	
model = IceCreamStore	
field = ("title", "block_address", )	

!

class IceCreamStoreUpdateForm(IceCreamStoreCreateForm):	
def __init__(self, *args, **kwargs):	
super(IceCreamStoreUpdateForm, self).__init__(*args, **kwargs)	
self.fields["phone"].required=True	
self.fields["description"].required=True	

!
!

class Meta:	
model = IceCreamStore	
fields = ("title", "block_address", "phone", "description")
Pattern 4: Hacking Form
Fields(cont.)

• Use it in view
from
from
from
from

django.views.generic import CreateView, UpdateView	
forms import IceCreamStoreCreateForm	
forms import IceCreamStoreUpdateForm	
models import IceCreamStore	

!
class IceCreamCreateView(CreateView):	
model=IceCreamStore	
form_class=IceCreamStoreCreateForm	

!
class IceCreamUpdateView(UpdateView):	
model=IceCreamStore	
form_class=IceCreamStoreUpdateForm
Pattern 5: Reusable Searching
Mixin View
Pattern 5: Reusable Searching
Mixin View

• Use a simple search view on multiple models
class TitleSearchMixin(object):	
def get_queryset(self):	
queryset = super(TitleSearchMixin, self).get_queryset()	

!

!

q = self.request.GET.get("q")	
if q:	
return queryset.filter(title__icontains=q)	
return queryset	
{#form go into store#}	

class FlavorListView(TitleSearchMixin, ListView):	
model = Flavor	

!

class StoreListView(TitleSearchMixin, ListView):	
model = Store

<form action="" method="GET">	
<input type="text" name="q"/>	
<button type="submit">search</
button>	
</form>	
{#form go into flavor#}	
<form action="" method="GET">	
<input type="text" name="q"/>	
<button type="submit">search</
button>	
</form>
Thanks
Alfred

More Related Content

PDF
Two Scoops of Django - Common Patterns for Forms
PDF
Two scoopsofdjango ch16 dealing with the user model
PPTX
Django: Advanced Models
PDF
Django design-patterns
PDF
날로 먹는 Django admin 활용
PPTX
Powerful Generic Patterns With Django
PPTX
DJango admin interface
PDF
Forms, Getting Your Money's Worth
Two Scoops of Django - Common Patterns for Forms
Two scoopsofdjango ch16 dealing with the user model
Django: Advanced Models
Django design-patterns
날로 먹는 Django admin 활용
Powerful Generic Patterns With Django
DJango admin interface
Forms, Getting Your Money's Worth

What's hot (19)

PPT
Common Pitfalls Experienced in Java
DOC
Validation
KEY
Repensando o Desenvolvimento Web com Ruby on Rails
PDF
What's New in newforms-admin
PDF
Working With The Symfony Admin Generator
PDF
Presentation technico-commercial-ruby-on-rails
PDF
The Django Book, Chapter 16: django.contrib
PDF
ZIP
Refatoração + Design Patterns em Ruby
PPT
Form demoinplaywithmysql
PPTX
Xml operations in odoo
PPTX
HTML Form Part 1
PPTX
PPTX
Django ORM - Marcin Markiewicz
PDF
Dig Deeper into WordPress - WD Meetup Cairo
PPT
Django Forms: Best Practices, Tips, Tricks
PDF
Grain final border one
PDF
Django Admin (Python meeutp)
PDF
2013-06-25 - HTML5 & JavaScript Security
Common Pitfalls Experienced in Java
Validation
Repensando o Desenvolvimento Web com Ruby on Rails
What's New in newforms-admin
Working With The Symfony Admin Generator
Presentation technico-commercial-ruby-on-rails
The Django Book, Chapter 16: django.contrib
Refatoração + Design Patterns em Ruby
Form demoinplaywithmysql
Xml operations in odoo
HTML Form Part 1
Django ORM - Marcin Markiewicz
Dig Deeper into WordPress - WD Meetup Cairo
Django Forms: Best Practices, Tips, Tricks
Grain final border one
Django Admin (Python meeutp)
2013-06-25 - HTML5 & JavaScript Security
Ad

Similar to Two scoopsofdjango common patterns for forms (20)

PDF
Django tricks (2)
KEY
Django Pro ORM
PDF
Тестирование и Django
PDF
Profile django
PDF
Testing for Pragmatic People
ODP
Mastering solr
PDF
Django Heresies
PDF
Optimization in django orm
PPTX
Tango with django
PPTX
Lo nuevo de Django 1.7 y 1.8
PDF
Ctools presentation
PPTX
Django forms
PPTX
What is Monkey Patching & How It Can Be Applied in Odoo 17
PDF
BarcelonaJUG2016: walkmod: how to run and design code transformations
PPTX
An Introduction To Python - Functions, Part 1
DOC
Wheels
PDF
What's new in Django 1.7
PDF
Django Good Practices
ODP
Pruebas unitarias con django
PDF
Introduction To Django (Strange Loop 2011)
Django tricks (2)
Django Pro ORM
Тестирование и Django
Profile django
Testing for Pragmatic People
Mastering solr
Django Heresies
Optimization in django orm
Tango with django
Lo nuevo de Django 1.7 y 1.8
Ctools presentation
Django forms
What is Monkey Patching & How It Can Be Applied in Odoo 17
BarcelonaJUG2016: walkmod: how to run and design code transformations
An Introduction To Python - Functions, Part 1
Wheels
What's new in Django 1.7
Django Good Practices
Pruebas unitarias con django
Introduction To Django (Strange Loop 2011)
Ad

Recently uploaded (20)

PDF
cuic standard and advanced reporting.pdf
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
KodekX | Application Modernization Development
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PPTX
Cloud computing and distributed systems.
PPTX
MYSQL Presentation for SQL database connectivity
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
Machine learning based COVID-19 study performance prediction
PDF
Encapsulation theory and applications.pdf
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
Spectroscopy.pptx food analysis technology
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
cuic standard and advanced reporting.pdf
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Network Security Unit 5.pdf for BCA BBA.
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Advanced methodologies resolving dimensionality complications for autism neur...
KodekX | Application Modernization Development
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Cloud computing and distributed systems.
MYSQL Presentation for SQL database connectivity
MIND Revenue Release Quarter 2 2025 Press Release
Building Integrated photovoltaic BIPV_UPV.pdf
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Machine learning based COVID-19 study performance prediction
Encapsulation theory and applications.pdf
The AUB Centre for AI in Media Proposal.docx
Spectroscopy.pptx food analysis technology
Digital-Transformation-Roadmap-for-Companies.pptx
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy

Two scoopsofdjango common patterns for forms

  • 1. Two Scoops of Django Chapter 9 Common Patterns for Forms Alfred
  • 2. Forms This chapter goes explicitly into the concepts of forms, models and CBVs. There are five common patterns.
  • 3. Pattern 1: Simple ModelForm with default Validators
  • 4. Pattern 1: Simple ModelForm with default Validators • Auto generated a model form based on the Flavor model.
  • 5. Pattern 2: Custom Form Field Validators in ModelForm
  • 6. Pattern 2: Custom Form Field Validators in ModelForm • Customize your validator.
  • 7. Pattern 2: Custom Form Field Validators in ModelForm(cont.) • To use it •what if we wanted to use validate_tasty() in just forms? •what if we wanted to assign it to other fields?
  • 8. Pattern 2: Custom Form Field Validators in ModelForm(cont.) • To create a customized form... #forms.py from django import forms from core.validators import validate_tasty from .models import Flavor ! class FlavorForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(FlavorForm, self).__init__(args, kwargs) self.fields["title"].validators.append(validate_tasty) self.fields["slug"].validators.append(validate_tasty) ! class Meta: model = Flavor
  • 9. Pattern 2: Custom Form Field Validators in ModelForm(cont.) #views.py from django.contrib import messages from django.views.generic import CreateView, UpdateView, DetailView from braces.views import LoginRequiredMixin from .models import Flavor from .forms import FlavorForm ! class FlavorActionMixin(object): model = Flavor @property def action(self): msg = "{0} is missing action.".format(self.__class__) raise NotImplementedError(msg) ! ! def form_valid(self, form): msg = "Flavor {0}!".format(self.action) messages.info(self.request, msg) return super(FlavorActionMixin, self).form_valid(form) class FlavorCreateView(LoginRequiredMixin, FlavorActionMixin, CreateView): model = Flavor action = "created" form_class = FlavorForm ! class FlavorUpdatedView(LoginRequiredMixin, FlavorActionMixin, UpdateView): model = Flavor action = "updated" form_class = FlavorForm ! class FlavorDetailView(DetailView): model = Flavor
  • 10. Pattern 3: Overriding the clean stage of Validation
  • 11. Pattern 3: Overriding the clean stage of Validation • Multi-field validation • Validation involving existing data from the database that has already been validated. clean() and clean<field_name>() • clean() method is the place to validate two or more fields against each other, since it’s not specific to any one particular field. • The clean validation stage is a better place to attach validation against persistent data.
  • 12. Pattern 3: Overriding the clean stage of Validation(cont.) • We are going to check the remaining amount is enough or not... class IceCreamOrderForm(forms.ModelForm): slug = forms.ChoiceField("Flavor") toppings = forms.CharField() ! ! def __init__(self, *args, **kwargs): super(IceCreamOrderForm, self).__init__(*args, **kwargs) self.fields["slug"].choices = [ (x.slug, x.title) for x in Flavor.objects.all() ] def clean_slug(self): slug = self.cleaned_data["slug"] if Flavor.objects.get(slug=slug).scoops_remainin <= 0: msg = u"sorry, we are out of flavor" raise forms.ValidationError(msg) return slug
  • 13. Pattern 3: Overriding the clean stage of Validation(cont.) • And then check multiple fields.. class IceCreamOrderForm(forms.ModelForm): ... def clean(self): cleaned_data = super(IceCreamOrderForm, self).clean() slug = cleaned_data.get("slug", "") toppings = cleaned_data.get("toppings", "") if u"chocolate" in slug.lower() and u"chocolate" in toppings.lower(): msg = u"Your order has too much chocolate." raise forms.ValidationError(msg) return cleaned_data
  • 14. Pattern 4: Hacking Form Fields
  • 15. Pattern 4: Hacking Form Fields • you have a ice cream store, some of fields are required, some are not. from django.db import models from django.core.urlresolvers import reverse # Create your models here. ! class IceCreamStore(models.Model): title = models.CharField(max_length=100) block_address = models.TextField() phone = models.CharField(max_length=20, blank=True) description = models.TextField(blank=True) def get_absolute_url(self): return reverse("store_detail", kwargs={"pk":self.pk})
  • 16. Pattern 4: Hacking Form Fields(cont.) • Old style v.s. better style from django import forms from models import IceCreamStore class IceCreamStoreUpdateForm(forms.ModelForm): ! phone = forms.CharField(required=True) #duplicate description = forms.TextField(required=True) #duplicate ! class Meta: model = IceCreamStore class IceCreamStoreUpdateForm(forms.ModelForm): ! ! class Meta: model = IceCreamStore def __init__(self, *args, **kwargs): super(IceCreamStoreUpdateForm, self).__init__(*args, **kwargs) self.fields["phone"].required=True self.fields["description"].required=True
  • 17. Pattern 4: Hacking Form Fields(cont.) • Much Better Style from django import forms from models import IceCreamStore ! class IceCreamStoreCreateForm(forms.ModelForm): class Meta: model = IceCreamStore field = ("title", "block_address", ) ! class IceCreamStoreUpdateForm(IceCreamStoreCreateForm): def __init__(self, *args, **kwargs): super(IceCreamStoreUpdateForm, self).__init__(*args, **kwargs) self.fields["phone"].required=True self.fields["description"].required=True ! ! class Meta: model = IceCreamStore fields = ("title", "block_address", "phone", "description")
  • 18. Pattern 4: Hacking Form Fields(cont.) • Use it in view from from from from django.views.generic import CreateView, UpdateView forms import IceCreamStoreCreateForm forms import IceCreamStoreUpdateForm models import IceCreamStore ! class IceCreamCreateView(CreateView): model=IceCreamStore form_class=IceCreamStoreCreateForm ! class IceCreamUpdateView(UpdateView): model=IceCreamStore form_class=IceCreamStoreUpdateForm
  • 19. Pattern 5: Reusable Searching Mixin View
  • 20. Pattern 5: Reusable Searching Mixin View • Use a simple search view on multiple models class TitleSearchMixin(object): def get_queryset(self): queryset = super(TitleSearchMixin, self).get_queryset() ! ! q = self.request.GET.get("q") if q: return queryset.filter(title__icontains=q) return queryset {#form go into store#} class FlavorListView(TitleSearchMixin, ListView): model = Flavor ! class StoreListView(TitleSearchMixin, ListView): model = Store <form action="" method="GET"> <input type="text" name="q"/> <button type="submit">search</ button> </form> {#form go into flavor#} <form action="" method="GET"> <input type="text" name="q"/> <button type="submit">search</ button> </form>