0

I have django app that is tracking contracts, locations, and products for various clients. Contracts, Locations each reference the client with a ForeignKey.

class Location(models.Model):
    client = models.ForeignKey(Client, on_delete=models.CASCADE)
    ...

class Contract(models.Model):
    client = models.ForeignKey(Client, on_delete=models.CASCADE)
    ...

I also have a product that will be deployed in a location, on a contract, for a client. I need to include client in product because the reference is used to secure the record to that client.

class Product(models.Model):
    client = models.ForeignKey(Client, on_delete=models.CASCADE)
    contract = models.ForeignKey(Contract, on_delete=models.CASCADE)
    location = models.ForeignKey(Location, on_delete=models.CASCADE)
    ....

What is the best way to make sure a product is never created that contains a different client reference across all 3 models? I was thinking I could use a pre_save signal but I would rather use a database constraint but I don't see a database constraint to force this.

HobbyHack
  • 33
  • 4
  • this looks like bad modeling, why all of these models have client if client must be same – iklinac Sep 03 '20 at 21:31
  • @iklinac we need to be able to enter a location that is tied to a client. we also need to enter a contract that is tied to a client. these objects are not related. i could remove the client reference from product but I would still have the same problem. how would you suggest I model this? – HobbyHack Sep 03 '20 at 22:01
  • aha, it looks like multitenant arhitecture on same database then, do clients write their own locations etc as you can always limit set to current client by overriding default manager – iklinac Sep 03 '20 at 22:20
  • @iklinac this is multi-tenant. clients can write their own data... we have agents that can write to a subset of client records and we have agents that can write to all the client records. – HobbyHack Sep 03 '20 at 22:47

1 Answers1

0

Did you look into the unique_together. I think this will do what you want to do.

Also keep the following in mind.

UniqueConstraint provides more functionality than unique_together. unique_together may be deprecated in the future.

Sadan A.
  • 1,017
  • 1
  • 10
  • 28
  • unique_together makes sure different fields are unique in a table to avoid duplicate conflicting records. I would like to make sure they are all referencing the same record. – HobbyHack Sep 03 '20 at 20:57
  • So basically, what you want is that Contract and Location are also linked to the same client in the Product. If I understand correctly. – Sadan A. Sep 03 '20 at 21:05
  • I am afraid you cannot do that at the database level. Instead either update your model save method and add the functionality programatically. As you mentioned `pre_save` is a good option. But if you don't wanna go towards the db signals then this answer might help https://stackoverflow.com/a/14471010/5084737 – Sadan A. Sep 03 '20 at 21:11
  • thanks. this is basically what I am doing currently. I am throwing an integrity error in an overridden save method. However, I noticed that with the constraints django actually returns the user to the input page with a note so it is easy to update. When I manually throw the integrity error (or validationerror) it just stops and displays an error page. maybe I should just be trying to figure out how to make the error return the user to the input page. – HobbyHack Sep 03 '20 at 21:48