| Jul 17, 2014 | Django python
As a heavy user of Django, here I’d like to share some experiences based on my own Django working practice.
Identify which level of model, view, or form implementing related features is rather important to achieve code reuse, avoid requirement missed, especially during team work, and even strength project long term maintenance.
For example, Our requirement is expecting to reject one employee taking both owner and assistant at the same group.
Assume the project model as following,
class Employee(models.Model):
"""Record employees' information."""
employee_number = models.IntegerField()
name = models.CharField(max_length=255)
class Group(models.Model):
"""Record groups' information."""
name = models.CharField(max_length=255)
description = models.CharField(max_length=255)
owner = models.ForeignKey(
"Employee", related_name="direct_owned_groups")
assistant = models.ForeignKey(
"Employee", related_name="direct_manage_groups")
Implement the restriction at view/form level, or in file views/group.py&forms/group.py, assume form description as following,
class GroupEditForm(forms.ModelForm):
class Meta:
model = Group
fields = ['name', 'description', 'owner', 'assistant']
widgets = {
'name': forms.TextInput(),
'description': forms.TextInput(),
'owner': forms.Select(),
'assistant': forms.Select(),
}
def clean(self):
cleaned_data = super(GroupEditForm, self).clean()
owner = cleaned_data.get('owner')
assistant = cleaned_data.get('assistant')
if all([owner, assistant, owner is assistant]):
self._errors['assistant'] = self.error_class(
["Can't set %s as the same group's owner&assistant" % owner.name])
return cleaned_data
with the maybe view,
class GroupEditView(UpdateView):
"""Edit group's info."""
model = Group
pk_url_kwarg = 'group_id'
template_name = 'group/edit.html'
form_class = GroupEditForm
Updated
Implement the restriction at model level, or before the action of model object save, we can code a listener connected with signal pre_save. Assume we write it in listener.py as following,
def decide_before_group_save(sender, instance, **kwargs):
if instance.owner is instance.assistant:
raise ValidationError("Can't set %s as the same group's owner&assistant" % owner.name)
at the same time, connect the above listener with pre_save(),
pre_save.connect(decide_before_group_save, Sender=Group)
Here I ignored the interactive with front end.
Implement the restriction at model clean function,
class Group(models.Model):
......
def clean(self):
from django.core.exceptions import ValidationError
if self.owner is self.assistant:
raise ValidationError("Can't set %s as the same group's owner&assistant" % self.owner.name)
Obviously, the last is closer with DB than the formers. The advantage of the later implementation is: