Your SlideShare is downloading. ×
0
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Forms, Getting Your Money's Worth
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Forms, Getting Your Money's Worth

15,185

Published on

These are the slides from my talk on advanced forms topics given at EuroDjangocon 2009.

These are the slides from my talk on advanced forms topics given at EuroDjangocon 2009.

Published in: Technology, Business
2 Comments
35 Likes
Statistics
Notes
  • A good guide to getting your money's worth in the form technical side. http://network21australia.blogspot.com/
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Explained well on django forms.

    Mark Chang, www.free-ringtones.co.in/ www.free-ringtones-for-sprint.com/
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
15,185
On Slideshare
0
From Embeds
0
Number of Embeds
16
Actions
Shares
0
Downloads
286
Comments
2
Likes
35
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Forms, Getting Your Money's Worth Alex Gaynor
  • 2. What Are Forms For? •They are a way to get data from the user
  • 3. django.forms •Encapsulate forms into objects •Know how to validate our data •In the case of ModelForms, they know how to save data •Formsets: Multiple of the same type of Form •Understand part of the idea of the HTTP request/response cycle
  • 4. The 20 second recap from django import forms from myapp.models import MyModel class MyForm(forms.Form): my_field = forms.CharField() other_field = forms.BooleanField(widget=forms.Select) class MyModelForm(forms.ModelForm): class Meta: model = MyModel
  • 5. Going beyond the basics •What you just saw is how 90% of people use django.forms •That's using classes to define static forms that don't change •But that's not how most applications are •What are some common tasks that aren't static, or otherwise handled by this setup?
  • 6. Problems to Solve •Multiple forms of different types •Altering a form's options dynamically •Building entire forms dynamically
  • 7. Multiple Forms •Formsets let us handle multiple forms of one type, for example letting a user enter multiple books •We can manually pass around multiple forms user_form = UserForm() profile_form = UserProfileForm() return render_to_response({ 'user_form': user_form, 'profile_form': profile_form, })
  • 8. Doing a bit Better •That's really ugly, doesn't scale well •What would be easier? •One class to hold all of our forms •It should act like it's just a normal form object where possible •How do we build this? •Normal python tools of the trade, dynamically creating classes
  • 9. def multipleform_factory(form_classes, form_order=None): if form_order: form_classes = SortedDict([ (prefix, form_classes[prefix]) for prefix in form_order]) else: form_classes = SortedDict(form_classes) return type('MultipleForm', (MultipleFormBase,), {'form_classes': form_classes})
  • 10. How type() works type(object) -> returns the class of the object, type(1) == int type([]) == list type(name, bases, attrs) -> returns a new class named {{ name }}, inherits from {{ bases}}, and has attributes of {{ attrs}} class MyForm(forms.Form): my_field = forms.CharField() type('MyForm', (forms.Form,), {'my_field': forms.CharField()}
  • 11. class MutlipleFormBase(object): def __init__(self, data, files): self.forms = [form_class(data, files, prefix=prefix) for form_class, prefix in self.form_classes.iteritems()] def as_table(self): return 'n'.join([form.as_table() for form in self.forms]) def save(self, commit=True): return tuple([form.save(commit) for form in self.forms]) def is_valid(self): return all(form.is_valid() for form in
  • 12. How it works •Simple factory function creates a new class that subclasses MultipleFormBase, gives it an extra attribute, a dict of form classes •MultipleFormBase just emulates the API of Form and ModelForm, aggregating the methods as appropriate
  • 13. class UserForm(forms.ModelForm): class Meta: model = User class ProfileForm(forms.ModelForm): class Meta: model = UserProfile UserProfileForm = multipleform_factory({ 'user': UserForm, 'profile': ProfileForm, }, ['user', 'profile'])
  • 14. The Result •Now we can use UserProfileForm the same way we would a regular form. •We need to expand MultipleFormBase to implement the rest of the Form API, but these additional methods are trivial.
  • 15. A More Dynamic Form •Not all users should see the same form •Simple example: a user should only be able to select an option from a dropdown if it belongs to them •Tools of the trade: Subclassing methods
  • 16. class ObjectForm(forms.ModelForm): def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super(ObjectForm, self).__init__(*args, **kwargs) self.fields['related'].queryset = self.fields['related'].queryset. filter(owner=user) class Meta: model = Object
  • 17. Dead Simple •Now when we instantiate our form we just need to prive a user kwarg. •Form and ModelForm are just python. We overide methods to add our own behavior, then call super(). •We can apply this same technique anywhere in Python, to any method.
  • 18. Building it Dynamically •What if we don't just want to alter our form per request, what if we want to build the whole thing dynamically? •Common example: a survey application where we keep the survey questions in the database. •Let's build it.
  • 19. The Pieces •What do we need to build this survey application? •A Model for a Survey and another for Fields on each Form(we're keeping it simple). •A function to take a Survey object and turn it into a Form subclass.
  • 20. class Survey(models.Model): name = models.CharField(max_length=100) FIELD_TYPE_CHOICES = ( (0, 'charfield'), (1, 'textfield'), (2, 'boolean'), ) class Question(models.Model): survey = models.ForeignKey(Survey, related_name='questions') label = models.CharField(max_length=255) field_type = models.IntegerField(choices= FIELD_TYPE_CHOICES)
  • 21. FIELD_TYPES = { 0: forms.CharField, 1: curry(forms.CharField, widget=forms.Textarea) 2: forms.BooleanField } def form_form_survey(survey): fields = {} for question in survey.questions.all(): fields[question.label] = FIELD_TYPES[question.field_type]( label = question.label ) return type('%sForm' % survey.name, (forms.Form,), fields)
  • 22. What do We Have •2 very simple models for storing our surveys and the questions for these surveys •a way to create actual forms.Form classes for a survey •now we can use these forms in our views the same as normal
  • 23. What Don't We have •Handling for more complex field types(such as choices) •A way to create Surveys(other than the admin, which would actually work really well for this) •A way to save the results of a survey •Consider these an excersise for the reader
  • 24. Recap •Use standard Python to extend what we have •Don't be afraid to build your own things on top of what we already have •It's just Python
  • 25. Questions? P.S.: If you're someone who needs multiple datbase support in Django come talk to me

×