Skip to content

Instantly share code, notes, and snippets.

@seddonym
Last active March 10, 2017 17:48
Show Gist options
  • Save seddonym/83c3c5fb56bb1fbe41977b77741973b3 to your computer and use it in GitHub Desktop.
Save seddonym/83c3c5fb56bb1fbe41977b77741973b3 to your computer and use it in GitHub Desktop.
Form signals idea
from . import signals
# ...
class BaseForm:
# ...
def _clean_form(self):
try:
signals.pre_clean.dispatch(sender=self.__class__, form=self)
cleaned_data = self.clean()
signals.post_clean.dispatch(sender=self.__class__, form=self, cleaned_data)
except ValidationError as e:
self.add_error(None, e)
class BaseModelForm(BaseForm):
# ...
def save(self, commit=True):
"""
Save this form's self.instance object if commit=True. Otherwise, add
a save_m2m() method to the form which can be called after the instance
is saved manually at a later time. Return the model instance.
"""
if self.errors:
raise ValueError(
"The %s could not be %s because the data didn't validate." % (
self.instance._meta.object_name,
'created' if self.instance._state.adding else 'changed',
)
)
signals.pre_save.dispatch(sender=self.__class__, form=self, commit=commit)
if commit:
# If committing, save the instance and the m2m data immediately.
self.instance.save()
self._save_m2m()
else:
# If not committing, add a method to the form to allow deferred
# saving of m2m data.
self.save_m2m = self._save_m2m
signals.post_save.dispatch(sender=self.__class__, form=self)
return self.instance
from .models import Profile
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
exclude = ['user']
from django.db import models
class Profile(models.Model):
user = models.OneToOneField('auth.User')
age = models.PositiveSmallIntegerField()
nickname = models.CharField()
from django.forms import signals as form_signals
from django.dispatch import receiver
@receiver(form_signals.pre_init, sender=SignUpForm)
def foo(sender, args, kwargs, **extra_kwargs):
pass
@receiver(form_signals.post_init, sender=SignUpForm)
def add_profile_fields_to_sign_up_form(sender, form, **kwargs):
# Add profile form fields to SignUpForm
profile_form = ProfileForm(data=kwargs.get('data'))
for field_name, field in profile_form.fields.items():
form.fields[field_name] = field
@receiver(form_signals.pre_clean, sender=SignUpForm)
def baz(sender, form, **kwargs):
pass
@receiver(form_signals.post_clean, sender=SignUpForm)
def validate_profile_fields(sender, form, cleaned_data, **kwargs):
# Check that the nickname is not the same as the username
if cleaned_data.get('username') == cleaned_data.get('nickname'):
form.add_error('nickname', 'Your nickname cannot be the same as your username.')
@receiver(form_signals.pre_save, sender=SignUpForm)
def baz(sender, form, commit, **kwargs):
pass
from django import forms
from django.contrib.auth.models import User
class SignUpForm(forms.ModelForm):
class Meta:
model = User
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment