Ошибка повторяющегося ключа после исключения IsNotExist в Django - PullRequest
1 голос
/ 18 января 2020

Мне нужно вставить новые Candle объекты, у которых есть опция поля datetime unique=True. Чтобы избежать ошибки проверки при создании объекта, я сначала проверяю, могу ли я получить его с помощью objects.get(), а когда возникает исключение DoesNotExist, я создаю его. Моя проблема заключается в том, что после того, как возникло исключение, создание не удалось из-за дублирования ключа.

    try:
        Candle.objects.get(market = instance, dt = dt)

    except Candle.DoesNotExist:
        Candle.objects.create(
            market = instance,
            dt = dt,
            op = op,
            hi = hi,
            lo = lo
            cl = cl
        )

Как вы можете видеть, я пытаюсь получить свечу для определенного c рынка, который является экземпляром Я работаю на. И это похоже на работу, потому что это исключение.

Однако, когда он создает объект, возникает другое исключение для ошибки нарушения:

duplicate key value violates unique constraint "marketsdata_candle_timestamp_key"
DETAIL:  Key (dt)=(2019-11-28 00:00:00+00) already exists.

Мой анализ состоит в том, что свеча с тем же полем dt существует на другом рынке, но она не должен выдавать ошибку нарушения, потому что я указываю market = instance для создания свечи в случае рынка, над которым я работаю. И он прекрасно работает с get.

. И еще мне показалось странным, что у Candle нет поля timestamp, поскольку оно было переименовано в dt. Вот как выглядят мои модели:

models.py

class Candle(models.Model):
    market = models.ForeignKey(Market,
                               on_delete=models.CASCADE,
                               related_name='market',
                               null= True
                               )
    dt = models.DateTimeField(unique=True)
    op = models.DecimalField(max_digits=20, decimal_places=2)
    hi = models.DecimalField(max_digits=20, decimal_places=2)
    lo = models.DecimalField(max_digits=20, decimal_places=2)
    cl = models.DecimalField(max_digits=20, decimal_places=2)


    def __str__(self):
        return str(self.dt.strftime("%Y-%m-%d %H:%M:%S"))

class Market(models.Model):
    exchange = models.ForeignKey(Exchange,
                                 on_delete=models.CASCADE,
                                 related_name='exchange'
                                 )

    pair = models.CharField(max_length=12, null=True)
    def __str__(self):
        return str(self.pair)

Может кто-нибудь сказать, почему метод create не работает, пока get работает? а также откуда берется поле timestamp?

Ответы [ 2 ]

1 голос
/ 18 января 2020

Атрибут uqinue поля модели влияет на всю таблицу. Таким образом, если у вас есть одна запись с указанным значением c dt в вашей таблице, вы не сможете добавить еще одну запись даже с значением dictinct market. Вместо unique в указанном c поле попробуйте использовать параметр unique_together:

class Candle(models.Model):
    market = models.ForeignKey(Market,
                               on_delete=models.CASCADE,
                               related_name='market',
                               null= True
                               )
    dt = models.DateTimeField()

    class Meta:
        unique_together = ['market', 'dt']

Что касается marketsdata_candle_timestamp_key именования, то это имя ограничения БД, которое было создано при вы создаете timestamp. Позже вы переименуете это поле, но имя ограничения не было изменено, и оно все еще содержит имя предыдущего поля.

BTW django имеет ярлык get_or_create, который вы можете использовать в этом случае.

0 голосов
/ 18 января 2020

Когда вы запрашиваете с помощью get (), вы используете два ограничения ie market и dt. Но когда дело доходит до создания записи, только поле dt проверяется на уникальность. Так что вам нужно go с 'unique_together'. В вашей модели вы должны упомянуть это в Meta.

class Meta:
    unique_together = [['field1', 'field2']]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...