NeoVe
NeoVe

Reputation: 3897

Save object name into ForeignKey field on child object - Django

I have these models:

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)

Then, this method:

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')

So far, this method works to save the parent and save particular fields on child creation.

My problem comes when I want to, for example, instead of saving a parent's CharField into a child CharField, I want to save the actual parent instance into a child's ForeignKey field, like this:

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')

The parent object is saved into db with a method like this:

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

So, after the second create_child_objects it throws me this:

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

So, how can I save the parent object descriptor into a ForeignKey field to the parent object?

EDIT

What is saved on this myfk field is the id of MyModel1, so, it would be sufficient to save this, but when I try like this field1 = MyModel1.id

It says:

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

Upvotes: 0

Views: 46

Answers (1)

IVNSTN
IVNSTN

Reputation: 9299

field1 = instance.__str__

change to

field1 = instance.__str__()

or

field1 = str(instance)

__str__ is a method so your assignment makes field1 pointing to this method, not method's result.

UPD

All the MyModel[2-4].objects.get_or_create(field1=field2) lines are wrong:

  • those model don't have field1 field, so correct filter would be field[2-4]=field1
  • anyway, I assume it will never match anything because __str__ method is a combination of those IDs and this string must be parsed first; only extracted values would match

And I don't understand how your __str__ method works since this model does not have field2, field3 and field4.

I suggest you to rethink the approach. Have a look at generic relations.

Upvotes: 1

Related Questions