Unique_together не предотвращает дублирование записей
У меня есть две такие модели :
class Preference(models.Model):
lat = models.DecimalField(max_digits=25,decimal_places=15)
lng = models.DecimalField(max_digits=25,decimal_places=15)
name = models.CharField(max_length=150,null=True)
address = models.TextField(max_length=350,null=True)
type = models.CharField(max_length=150,blank=True,null=True)
class PrefenceOfUser(models.Model):
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
place_detail = models.ForeignKey(Preference, on_delete=models.CASCADE)
def __str__(self):
return self.user.username
class Meta:
unique_together = ('user', 'place_detail',)
вот json, который я отправляю в apiview :
{
"lat": "29.621142463088336",
"lng": "52.520185499694527",
"name":"cafesama1",
"address":"streetn1",
"type":"cafe"
}
в файле views.py :
class PreferedLocationsOfUsers(APIView):
def post(self, request, format=None):
serializer = PreferLocationSerializer(data=request.data)
if serializer.is_valid():
location= Preference(**serializer.data)
location.save()
user_perefeces = PrefenceOfUser(user=request.user,place_detail=location)
user_perefeces.save()
return Response({'location saved'},status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
я хочу предотвратить сохранение пользователем дублированных записей в базе данных, но когда объект местоположения сохраняется в PrefenceOfUser unique_together, это не предотвращает дублирование.
У вас действительно проблема с миграцией, как указано в комментариях. Избавьтесь от дубликатов, запустите миграцию заново, пока не получите никаких ошибок, и все будет в порядке.
Однако я бы рассмотрел это как проблему проектирования модели. Вам не нужно прибегать к ручным ограничениям для этого.
class Preference(models.Model):
lat = models.DecimalField(max_digits=25,decimal_places=15)
lng = models.DecimalField(max_digits=25,decimal_places=15)
name = models.CharField(max_length=150,null=True)
address = models.TextField(max_length=350,null=True)
type = models.CharField(max_length=150,blank=True,null=True)
users = models.ManyToManyField(get_user_model(), blank=True)
Приведенный выше код будет иметь точно такие же последствия, как и ваш, он более чистый и более Djangoesque.
Вы все еще можете получить доступ к тому, что вы называете PrefenceOfUser
через Preference.users.through
. Если вы планируете добавить больше атрибутов к выбору (т.е. когда пользователь добавил свои предпочтения), вы можете просто сделать:
class PrefenceOfUser(models.Model):
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
place_detail = models.ForeignKey(Preference, on_delete=models.CASCADE)
extra_field = models.WhateverField()
def __str__(self):
return self.user.username
и измените Preference.users
на
models.ManyToManyField(get_user_model(), through=PrefenceOfUser)
что все равно обеспечит уникальность.