Сохранить имя объекта в поле ForeignKey дочернего объекта — Django

#django #python-3.x

#django #python-3.x

Вопрос:

У меня есть эти модели:

 class MyModel1(models.Model):
    field1 = models.CharField(max_length=128, blank=True, null=True)
    fieldrelated1 = models.OneToOneField('MyModel2', max_length=128, blank=True, null=True, related_name='mymodel2')
    fieldrelated2 = models.OneToOneField('MyModel3', max_length=128, blank=True, null=True, related_name='mymodel3')
    fieldrelated3 = models.OneToOneField('MyModel4', max_length=128, blank=True, null=True, related_name='mymodel4')

class MyModel2(models.Model):
    field2 = models.CharField(max_length=128, blank=True, null=True)
    myfk = models.ForeignKey(MyModel1, max_length=128, blank=True, null=True)

class MyModel3(models.Model):
    field3 = models.CharField(max_length=128, blank=True, null=True)
    test = models.CharField(max_length=128, blank=True, null=True)

class MyModel4(models.Model):
    field4 = models.CharField(max_length=128, blank=True, null=True)
    test = models.CharField(max_length=128, blank=True, null=True)
  

Затем этот метод:

 def create_child_objects(instance, created, rad, **kwargs):
    if not created or rad:
        return
        field1 = instance.field1

    if not instance.fieldrelated1_id:
        fieldrelated1, _ = MyModel2.objects.get_or_create(field1=field2)
    instance.fieldrelated1 = fieldrelated1

    if not instance.fieldrelated2_id:
        fieldrelated2, _ = MyModel3.objects.get_or_create(field1=field3)
    instance.fieldrelated2 = fieldrelated2

    if not instance.fieldrelated3_id:
        fieldrelated3, _ = MyModel4.objects.get_or_create(field1=field4)
    instance.fieldrelated3 = fieldrelated3

    instance.save()

models.signals.post_save.connect(create_child_records, sender=MyModel1, dispatch_uid='create_child_objects')
  

Пока этот метод работает для сохранения родительского объекта и сохранения определенных полей при создании дочернего объекта.

Моя проблема возникает, когда я хочу, например, вместо сохранения родительского CharField в дочернем CharField , я хочу сохранить фактический родительский экземпляр в дочернем ForeignKey поле, вот так:

 def create_child_objects(instance, created, rad, **kwargs):
    if not created or rad:
        return
    field1 = instance.__str__

    if not instance.fieldrelated1_id:
        fieldrelated1, _ = MyModel2.objects.get_or_create(field1=myfk)
    instance.fieldrelated1 = fieldrelated1

    if not instance.fieldrelated2_id:
        fieldrelated2, _ = MyModel3.objects.get_or_create(field1=field3)
    instance.fieldrelated2 = fieldrelated2

    if not instance.fieldrelated3_id:
        fieldrelated3, _ = MyModel4.objects.get_or_create(field1=field4)
    instance.fieldrelated3 = fieldrelated3

    instance.save()

models.signals.post_save.connect(create_child_objects, sender=MyModel1, dispatch_uid='create_child_records')
  

Родительский объект сохраняется в БД с помощью метода, подобного этому:

     def __str__(self):
        return ('{}: {}: {}'.format(self.field1, self.field2, self.field3))
  

Итак, после второго create_child_objects он выдает мне это:

 TypeError at /admin/mymodel/instance/add/
int() argument must be a string, a bytes-like object or a number, not 'method'
  

Итак, как я могу сохранить дескриптор родительского объекта в ForeignKey поле родительского объекта?

Редактировать

В этом myfk поле сохраняется идентификатор MyModel1 , поэтому было бы достаточно сохранить это, но когда я пытаюсь вот так field1 = MyModel1.id

В нем говорится:

 ValueError at /admin/mymodel/instance/add/
Cannot assign "98": "MyModel2.field1.id" must be a "MyModel1" instance.
  

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

1. Я думаю, что это должно быть __str__()

2. Вы всегда «сохраняете фактический родительский экземпляр в поле ForeignKey дочернего объекта», по крайней мере, в коде Django. На уровне базы данных сохраняется первичный ключ родительского объекта. Строковое представление родительского объекта не имеет к этому никакого отношения.

Ответ №1:

 field1 = instance.__str__
  

изменить на

 field1 = instance.__str__()
  

или

 field1 = str(instance)
  

__str__ это метод, поэтому ваше назначение делает field1 указание на этот метод, а не на результат метода.

UPD

Все MyModel[2-4].objects.get_or_create(field1=field2) строки неверны:

  • в этих моделях нет field1 поля, поэтому правильный фильтр будет field[2-4]=field1
  • в любом случае, я предполагаю, что оно никогда ничему не будет соответствовать, потому что __str__ метод представляет собой комбинацию этих идентификаторов, и эта строка должна быть проанализирована первой; совпадают только извлеченные значения

И я не понимаю, как работает ваш __str__ метод, поскольку в этой модели нет field2 , field3 и field4 .

Я предлагаю вам пересмотреть подход. Взгляните на общие отношения.

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

1. Привет, хорошее объяснение, большое вам спасибо, но извините, там написано недопустимый литерал для int () с основанием 10, когда я сохраняю родительский объект с помощью метода str , он содержит комбинацию чисел и строк, (field1, field2, field3) может ли это быть проблемой?

2. Привет, Иван, большое тебе спасибо, я выполнил несколько запросов к базе данных, что необходимо сохранить, так это фактический ‘id’ в поле ‘myfk’, оно должно его отобразить, я отредактировал свой вопрос, если хочешь, спасибо.

3. Ваш запутанный (?) код и сообщения об ошибках не совпадают.

4. Я имею в виду, если я добавлю идентификатор ‘instance’, который будет идентификатором MyModel1, он должен быть сохранен как таковой, я не понимаю, почему эта ошибка, кажется, что я должен явно объявить экземпляр MyModel1