[Fixed]-ForeignKey to a model that is defined after/below the current model


Use the fully-qualified model string

When this happens, I usually resort to what’s called the fully-qualified model string, fancy term for what’s essential a string representing the model and the containing app in the format of 'app_label.ModelName'

E.g. if your model is Order, then the model string name would be the string 'Order'

So you can already do:

order = models.ForeignKey('Order', on_delete=models.CASCADE)

With the above, Django will look for the model 'Order' in the same app. It’s okay if you have not defined it yet, as long as it is defined.

If that model happens to come from a different app, it would be:

order = models.ForeignKey('appname.Order', on_delete=models.CASCADE)

Reverse query clashes

Because Order points to OrderItems and OrderItems point to Order you get a clash with related queries that Django generate for you. You can disable those with related_name='+':

order = models.ForeignKey('Order', on_delete=models.CASCADE, related_name='+')

Better modeling

Since a OrderedItem already “belongs” to an Order, there’s no point in having a ForeignKey from Order to OrderedItem, you can just remove it instead of dealing with the above clash.

So what you’d have would look like this



    + FK(Item)
    + FK(Order)

A design which wouldn’t involve referencing a model that hasn’t been defined yet 🙂



The reason it can’t find the class order is because it hasn’t been defined yet, you either need to specify it as a string as shown by Shang Wang, or change the order of them in your models.py

class Order(models.Model):
    orderedItem = models.ForeignKey(OrderedItem, on_delete=models.CASCADE)
    #truckId Foreign key till truck
    created = models.DateTimeField(auto_now=False, auto_now_add=True)
    updated = models.DateTimeField(auto_now=True, auto_now_add=False)
    emergency = models.BooleanField(default=False)
    status = models.IntegerField()
    def __str__(self):
        return self.id    

class OrderedItem(models.Model):
    items = models.ForeignKey(Items, on_delete=models.CASCADE)
    order = models.ForeignKey(Order, on_delete=models.CASCADE)
    amount = models.IntegerField()
    def __str__(self):
        return self.items

Changing the order has its advantages over specifying as a string since it will allow IDE’s to find usages of the class should it ever need refactoring.

Since you have foreign keys to both classes, the above won’t work and only applies to one-to-one or one-to-many relationships. Instead, it would be better to define a ManyToManyField instead of the two foreign keys



You have defined class Items before use it and you have not any error.
you must define class Order before class OrderedItem.


Leave a comment