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 ju...
Pattern 2: Custom Form Field
Validators in ModelForm(cont.)

• To create a customized form...
#forms.py	
from django impor...
Pattern 2: Custom Form Field
Validators in ModelForm(cont.)
#views.py	
from django.contrib import messages	
from django.vi...
Pattern 3: Overriding the clean
stage of Validation
Pattern 3: Overriding the clean
stage of Validation

• Multi-field validation	

• Validation involving existing data from t...
Pattern 3: Overriding the clean
stage of Validation(cont.)

• We are going to check the remaining amount
is enough or not....
Pattern 3: Overriding the clean
stage of Validation(cont.)

• And then check multiple fields..
class IceCreamOrderForm(form...
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 im...
Pattern 4: Hacking Form
Fields(cont.)

• Old style v.s. better style

from django import forms	
from models import IceCrea...
Pattern 4: Hacking Form
Fields(cont.)

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

!
...
Pattern 4: Hacking Form
Fields(cont.)

• Use it in view
from
from
from
from

django.views.generic import CreateView, Updat...
Pattern 5: Reusable Searching
Mixin View
Pattern 5: Reusable Searching
Mixin View

• Use a simple search view on multiple models
class TitleSearchMixin(object):	
d...
Thanks
Alfred
Upcoming SlideShare
Loading in …5
×

Two scoopsofdjango common patterns for forms

1,321 views

Published on

Published in: Technology, Business
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,321
On SlideShare
0
From Embeds
0
Number of Embeds
26
Actions
Shares
0
Downloads
14
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Two scoopsofdjango common patterns for forms

  1. 1. Two Scoops of Django Chapter 9 Common Patterns for Forms Alfred
  2. 2. Forms This chapter goes explicitly into the concepts of forms, models and CBVs. There are five common patterns.
  3. 3. Pattern 1: Simple ModelForm with default Validators
  4. 4. Pattern 1: Simple ModelForm with default Validators • Auto generated a model form based on the Flavor model.
  5. 5. Pattern 2: Custom Form Field Validators in ModelForm
  6. 6. Pattern 2: Custom Form Field Validators in ModelForm • Customize your validator.
  7. 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. 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. 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. 10. Pattern 3: Overriding the clean stage of Validation
  11. 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. 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. 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. 14. Pattern 4: Hacking Form Fields
  15. 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. 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. 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. 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. 19. Pattern 5: Reusable Searching Mixin View
  20. 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>
  21. 21. Thanks Alfred

×