django get_or_create выдает ошибку целостности

avatar
flice com
8 августа 2021 в 20:26
39
2
0

Я прочитал эту тему: get_or_create выдает ошибку целостности

Но все еще не совсем понятно, когда get_or_create возвращает False или IntegrityError.

У меня есть следующий код:

django_username = 'me'
user = get_user_model().objects.filter(username=django_username).first()

action_history, action_added = ActionModel.objects.get_or_create(
                date=date_obj,  # date object 
                account_name=unique_name,  # e.g. account1234
                target=follower_obj, # another model in django
                user=user,  # connected django user
                defaults={'identifier': history['user_id']}
            )

Хотя модель выглядит так:

class ActionModel(models.Model):
    """
    A model to store action history.

    """

    identifier = models.BigIntegerField(
        _("identifier"), null=True, blank=True) # target id
    account_name = models.CharField(_("AccountName"), max_length=150, null=True, blank=True)  # account name of the client
    date = models.DateField(_("Date"), auto_now=False, auto_now_add=False)  # action date
    target = models.ForeignKey(Follower, verbose_name=_("Target"), on_delete=models.CASCADE)  # username of the done-on action
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        null=True,
        editable=False,
        db_index=True,
    )  # django user that performed the action

    class Meta:
        verbose_name = _("Action")
        verbose_name_plural = _("Actions")
        unique_together = [
            ['account_name','date','target'],
        ]

Иногда он возвращает IntegrityError, а иногда (когда существует уникальное ограничение, он возвращает False при создании).

Источник
Mark R.
8 августа 2021 в 20:55
1

В документах говорится: > Если необходимо создать объект, а ключ уже существует в базе данных, будет выдано сообщение об ошибке IntegrityError.

flice com
8 августа 2021 в 21:19
0

@МаркР. Почему он не перехватывается в get перед созданием? Я отправляю ему все уникальные значения!

Ответы (2)

avatar
Shamsiddin Parpiev
8 августа 2021 в 21:32
1

У вас есть ограничение unique_together. Давайте представим, что у вас есть объект в БД со следующими данными account_name='bob', date='2020-12-12', target='b', user='12'

В вашем методе get_or_create вы делаете это

ActionModel.objects.get_or_create(
            date='2020-12-12', 
            account_name='bob',  
            target='b', 
            user="13"
        )

вы указываете именно эти три параметра с этими данными, но пользователь на этот раз 13, поэтому django не может найти объект и пытается создать его, но с этими параметрами вы не можете создать объект, потому что есть уникальное ограничение

flice com
8 августа 2021 в 21:35
0

Могу ли я добавить пользователя в уникальное ограничение? повлияет ли это на существующую БД? unique_together = [['account_name','date','target', 'user']

Shamsiddin Parpiev
8 августа 2021 в 21:37
0

да, вы также можете добавить пользователя в ограничения, если это соответствует логике вашего приложения, но будьте осторожны, могут возникнуть проблемы, если у вас есть 2 или более объектов с уникальной проблемой

Shamsiddin Parpiev
8 августа 2021 в 21:38
1

если это произойдет, вы можете очистить базу данных с фильтрацией и удалением объектов, которые нарушают ограничения, и попытаться снова выполнить миграцию.

avatar
flice com
8 августа 2021 в 21:33
0

ОК. Разобрался, отправил:

account_name = 'adi'
date = '07-02-21'
target = 'nana1'
user = 'me'

Хотя он не существовал с конкретным пользователем = 'me', но с пользователем = None:

account_name = 'adi'
date = '07-02-21'
target = 'nana1'
user = None

Поэтому получение не удалось, и созданная попытка продублировать unique_together = ['account_name','date','target'].