26👍
I had a similar misunderstanding of the ORM when I first started with Django.
- No, don’t put
self.full_clean()
inside ofsave
. Either
A) use a ModelForm
(which will cause all the same validation to occur – note: ModelForm.is_valid()
won’t call Model.full_clean
explicitly, but will perform the exact same checks as Model.full_clean
). Example:
class PersonForm(forms.ModelForm):
class Meta:
model = Person
def add_person(request):
if request.method == 'POST':
form = PersonForm(request.POST, request.FILES)
if form.is_valid(): # Performs your validation, including ``validate_gender``
person = form.save()
return redirect('some-other-view')
else:
form = PersonForm()
# ... return response with ``form`` in the context for rendering in a template
Also note, forms aren’t for use only in views that render them in templates – they’re great for any sort of use, including an API, etc. After running form.is_valid()
and getting errors, you’ll have form.errors
which is a dictionary containing all the errors in the form, including a key called '__all__'
which will contain non-field errors.
B) Simply use model_instance.full_clean()
in your view (or other logical application layer), instead of using a form, but forms are a nice abstraction for this.
- I don’t really have a solution to, but I’ve never run into such a problem, even in large projects (the current project I work with my company on has 146 tables) and I don’t suspect it’ll be a concern in your case either.
0👍
As of django 4.1, self.full_clean
by default also runs self.validate_constraints
(docs).
After makemigrations, there will be a migrations.AddConstraint
statement included in the migration.
In your case:
from django.db import models
class Person(models.Model):
class Gender(models.TextChoices):
M = "M", "Male"
F = "F", "Female"
name = models.CharField(max_length=128)
age = models.IntegerField()
gender = models.CharField(maxlength=1, choices=Gender.choices)
class Meta:
constraints = [
models.CheckConstraint(
check=models.Q(gender__in=Gender.values), name="valid_gender"
),
models.CheckConstraint(
check=models.Q(age__gte=18), name="adults_only"
),
]
After running migrations, if you now try to self.save()
, will raise an IntegrityError
!
- [Django]-How do I restrict foreign keys choices to related objects only in django
- [Django]-Django App Improperly Configured – The app module has multiple filesystem locations
- [Django]-Django.core.exceptions.ImproperlyConfigured: Requested setting USE_I18N, but settings are not configured