I am studying the Django REST framework and building an API, but I have a simple question: Where should I add my validation fields? What’s the best place to do that—models or serializers? I know that a serializer has a function to convert Python objects to JSON or XML, and you can add validations before saving the object. On the other hand, I know validations in models affect the entire API. Take the example below: Should I put these validation fields in a serializer or keep them in the models?
class Table(Bean):
number = models.IntegerField(unique=True)
capacity = models.IntegerField()
available = models.BooleanField(default=True)
class Reservation(Bean):
STATUS_CHOICES = [
("confirmed", "Confirmed"),
("cancelled", "Cancelled"),
("finished", "Finished")
]
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
table = models.ForeignKey(Table, on_delete=models.CASCADE, default=None)
reservation_date = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=50, choices=STATUS_CHOICES, default="confirmed")
def save(
self,
*args,
force_insert=False,
force_update=False,
using=None,
update_fields=None,
):
if self.status == "confirmed" and self.table.available:
self.table.available = False
elif self.status == "cancelled" or self.status == "finished":
self.table.available = False
else:
raise ValidationError(f"Table {self.table.number} with id {self.table.id} is already reserved")
self.table.save()
super().save()
def delete(self, using=None, keep_parents=False):
if not self.table.available:
self.table.available = True
self.table.save()
super().delete()
Actuallly these is my Serializers:
class TableSerializer(serializers.ModelSerializer):
class Meta:
model = Table
fields = "__all__"
class ReservationSerializer(serializers.ModelSerializer):
class Meta:
model = Reservation
fields = "__all__"
I am studying the Django REST framework and building an API, but I have a simple question: Where should I add my validation fields? What’s the best place to do that—models or serializers? I know that a serializer has a function to convert Python objects to JSON or XML, and you can add validations before saving the object. On the other hand, I know validations in models affect the entire API. Take the example below: Should I put these validation fields in a serializer or keep them in the models?
class Table(Bean):
number = models.IntegerField(unique=True)
capacity = models.IntegerField()
available = models.BooleanField(default=True)
class Reservation(Bean):
STATUS_CHOICES = [
("confirmed", "Confirmed"),
("cancelled", "Cancelled"),
("finished", "Finished")
]
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
table = models.ForeignKey(Table, on_delete=models.CASCADE, default=None)
reservation_date = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=50, choices=STATUS_CHOICES, default="confirmed")
def save(
self,
*args,
force_insert=False,
force_update=False,
using=None,
update_fields=None,
):
if self.status == "confirmed" and self.table.available:
self.table.available = False
elif self.status == "cancelled" or self.status == "finished":
self.table.available = False
else:
raise ValidationError(f"Table {self.table.number} with id {self.table.id} is already reserved")
self.table.save()
super().save()
def delete(self, using=None, keep_parents=False):
if not self.table.available:
self.table.available = True
self.table.save()
super().delete()
Actuallly these is my Serializers:
class TableSerializer(serializers.ModelSerializer):
class Meta:
model = Table
fields = "__all__"
class ReservationSerializer(serializers.ModelSerializer):
class Meta:
model = Reservation
fields = "__all__"
Where should I add my validation fields? What’s the best place to do that—models or serializers?
If the validation should always hold, you put it in the models. That way, ModelForm
s, ModelSerializer
s, the ModelAdmin
, etc. will all validate the data accordingly.
But not all validation always holds. For example if you make a reservation, one could specify that a person can only make a reservation to a subset of the tables (non-primary tables for example), and only staff can upgrade the person to a premium table.
So some validation is view-dependent, and then you define that validation in the corresponding serializer(s), ModelForm
(s), etc.