Django - Убедитесь, что два поля в таблице одного типа модели не имеют одинакового значения для сущности
Итак, у меня есть класс пользователя, и пользователь может следить за другим пользователем, но я не хочу, чтобы пользователь мог следить за собой. Есть ли способ добавить это ограничение в Django?
class FollowUser(AbstractSimpleModel):
follower_id = models.ForeignKey(User, on_delete=models.CASCADE, related_name='follower_id')
followee_id = models.OneToOneField(User, on_delete=models.CASCADE, related_name='followee_id')
Поскольку вам нужно проверить значение поля на основе значений других полей, а именно FollowUser.follower_id
и FollowUser.followee_id
, вы можете следовать этому процессу, как Django обрабатывает проверку полей следующим образом:
Implement Model.clean() where you would run the validation
Override Model.save() to call the complete validation process via
Model.full_clean()
. This explicit step is needed because as documented:Note that full_clean() will not be called automatically when you call your model’s save() method. You’ll need to call it manually when you want to run one-step model validation for your own manually created models. For example:
from django.core.exceptions import ValidationError
from django.db import models
class UserDummy(models.Model):
pass
class FollowUser(models.Model):
follower_id = models.ForeignKey(UserDummy, on_delete=models.CASCADE, related_name='follower_id')
followee_id = models.OneToOneField(UserDummy, on_delete=models.CASCADE, related_name='followee_id')
def clean(self):
if self.follower_id == self.followee_id:
raise ValidationError("Users can't follow themselves")
def save(self, *args, **kwargs):
self.full_clean()
super().save(*args, **kwargs)
Выборочный запуск
Установите данные:
>>> from my_app.models import *
>>> UserDummy.objects.values()
<QuerySet [{'id': 1}, {'id': 2}, {'id': 3}]>
>>> user1 = UserDummy.objects.get(id=1)
>>> user2 = UserDummy.objects.get(id=2)
>>> user3 = UserDummy.objects.get(id=3)
Неудачная валидация:
>>> # Using Model.save()
>>> FollowUser(follower_id=user1, followee_id=user1).save()
Traceback (most recent call last):
raise ValidationError(errors)
django.core.exceptions.ValidationError: {'__all__': ["Users can't follow themselves"]}
>>>
>>> # Using Model.objects.create()
>>> FollowUser.objects.create(follower_id=user1, followee_id=user1)
Traceback (most recent call last):
raise ValidationError(errors)
django.core.exceptions.ValidationError: {'__all__': ["Users can't follow themselves"]}
Успешная валидация:
>>> # Using Model.save()
>>> FollowUser(follower_id=user1, followee_id=user2).save()
>>>
>>> # Using Model.objects.create()
>>> FollowUser.objects.create(follower_id=user2, followee_id=user3)
<FollowUser: FollowUser object (2)>
>>>
>>> FollowUser.objects.values()
<QuerySet [{'id': 1, 'follower_id_id': 1, 'followee_id_id': 2}, {'id': 2, 'follower_id_id': 2, 'followee_id_id': 3}]>
Примечание: Имейте в виду, что если вы используете Model.objects.bulk_create(), вам потребуются дальнейшие изменения, поскольку он не вызывает функциональность Model.save()
, как описано в документации:
bulk_create()
.Метод сохранения модели save() не будет вызван, и сигналы pre_save и post_save не будут отправлены.