Django создает уникальные объекты внешнего ключа

#python #django

#python #django

Вопрос:

У меня есть FK в моей модели Django, которая должна быть уникальной для каждой существующей модели, существовавшей до миграции:

 class PNotification(models.Model):
    notification_id = models.AutoField(primary_key=True, unique=True)
    # more fields to come

def get_notifications():
    noti = PNotification.objects.create()
    logger.info('Created notifiactions')
    logger.info(noti.notification_id)
    return noti.notification_id

class Product(models.Model):
        notification_object = models.ForeignKey(PNotification, on_delete=models.CASCADE, default=get_notifications)
  

При миграции я получаю три PNotification объекта, сохраненных в базе данных, однако каждый существующий Product связан с notification_id=1, поэтому каждый существующий Product связывается с одним и тем же PNotification объектом. Я думал, что вызов метода default будет выполняться для каждого существующего Product ?
Как я могу предоставить каждому существующему Product уникальному PNotification объекту?

Комментарии:

1. Ну ForeignKey , вы помещаете отношение в Product модель, что означает, что у каждого Product может быть только один PNotification , но у одного PNotification может быть много Product s — может быть, вы хотите поменять это отношение?

2. Вы могли бы добавить unique=True к notification_object .

3. @ger.s.brett использование unique=True приведет к ошибкам целостности, потому что тогда каждый продукт также получит одинаковую PNotification.

4. @Daniel Это будет один, но я работаю с FK здесь для тестирования. Каждый продукт будет иметь ровно один PNotification и один PNotification принадлежит одному продукту

Ответ №1:

Я также подозревал, что новая PNotification будет создана с вашей настройкой. Похоже, что метод вызывается при объявлении класса, а не при создании экземпляра.

Может быть, переопределенный метод сохранения является лучшим подходом здесь? Обратите внимание, вам нужно будет немного изменить логику для OneToOneField s:

 class Product(models.Model):

    ...

    def save(self, *args, **kwargs):

        if not self.notification_object.all():

            notification = PNotification.objects.create()

            self.notification_object.add(notification)
                
        super(Product, self).save(*args, **kwargs)
  

Комментарии:

1. Только один вопрос: это не поможет с миграцией, не так ли? Для вновь созданных продуктов мой код работает, речь идет только о миграции

2. Это хороший момент, но вы можете легко добавить: for p in Product.objects.all(): p.save() где-нибудь в вашем коде временно, чтобы запустить метод сохранения для существующих объектов во время миграции / подключения к определенному представлению и т.д. Обычно это то, что я делаю при внесении изменений в существующие экземпляры.

3. Да, я думаю, что это намного проще, чем писать сценарий миграции или SQL