0

I have a FK in my Django model, that needs to be unique for every existing model existing before migration:

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)

When migrating, I get three PNotification objects saved into the database, however each existing Product is linked with notification_id=1, so each existing Product gets linked with the same PNotification object. I thought the method call in default would be executed for each existing Product? How can I give each existing Product a unique PNotification object?

4
  • Well you put the ForeignKey relaton on the Product model meaning each Product can have only one PNotification but one PNotification can have many Products - maybe you want to swap that relation? Commented Nov 9, 2020 at 15:38
  • You could add unique=True to the notification_object. Commented Nov 9, 2020 at 16:05
  • @ger.s.brett using unique=True will throw IntegrityErrors because then also each Product gets the same PNotification. Commented Nov 9, 2020 at 16:22
  • @Daniel It will be a OneToOne, but I am working with FK here for testing. Each Product will have exactly one PNotification and one PNotification belongs to one product Commented Nov 9, 2020 at 16:22

1 Answer 1

1

I also suspected that a new PNotification would be created wth your setup. It appears as if the method is being called on the class decleration and not instance creation.

Maybe an overridden save method is a better approach here? Note, you'll need to change the logic slightly for OneToOneFields:

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)
Sign up to request clarification or add additional context in comments.

3 Comments

Just one question: this will not help with migration, will it? For newly created products my code works, it is just about migrating
That's a good point - but you can easily add: for p in Product.objects.all(): p.save() somewhere in your code temporarily to trigger the save method for existing objects during a migration / connected to a specific view, etc. That is generally what I do when making changes to existing instances.
Yea, I think that is way easier than writing a migration or SQL script

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.