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)

что все равно обеспечит уникальность.

Вернуться на верх