Keeping database foreign keys consistent

Multi tool use
up vote
3
down vote
favorite
I am trying to write a django app with a PostgreSQL database. My problem can be reduced to the following minimal example:
Organization
- has 0 ... N workers
Worker
- belongs to an organization
Task
- belongs to an organization
- is assigned to no-one, or assigned to one worker within the same organization
I am unsure of how to design the database in a way that prevents inconsistent state - since both Worker and Task need to have a foreign key pointing to the Organization they belong to, it is possible to end up with an inconsistent state where a worker from organization A is assigned a task from organization B.
The only solution I could think of was verifying the constraint in the save method:
class Organization(models.Model):
name = models.CharField(max_length=255)
class Worker(models.Model):
name = models.CharField(max_length=255)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
class Task(models.Model):
name = models.CharField(max_length=255)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
assigned_to = models.ForeignKey(Worker, null=True, on_delete=models.SET_NULL)
def save(self, *args, **kwargs):
if self.assigned_to and self.assigned_to.organization != self.organization:
raise ValidationError('Task and Worker belong in different Organizations.')
return super(Task, self).save(*args, **kwargs
Is it possible to create a better solution which still prevents inconsistent state? My own solution doesn't seem like a good one from a database design point of view.
python django database schema normalization
New contributor
けんじ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
add a comment |
up vote
3
down vote
favorite
I am trying to write a django app with a PostgreSQL database. My problem can be reduced to the following minimal example:
Organization
- has 0 ... N workers
Worker
- belongs to an organization
Task
- belongs to an organization
- is assigned to no-one, or assigned to one worker within the same organization
I am unsure of how to design the database in a way that prevents inconsistent state - since both Worker and Task need to have a foreign key pointing to the Organization they belong to, it is possible to end up with an inconsistent state where a worker from organization A is assigned a task from organization B.
The only solution I could think of was verifying the constraint in the save method:
class Organization(models.Model):
name = models.CharField(max_length=255)
class Worker(models.Model):
name = models.CharField(max_length=255)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
class Task(models.Model):
name = models.CharField(max_length=255)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
assigned_to = models.ForeignKey(Worker, null=True, on_delete=models.SET_NULL)
def save(self, *args, **kwargs):
if self.assigned_to and self.assigned_to.organization != self.organization:
raise ValidationError('Task and Worker belong in different Organizations.')
return super(Task, self).save(*args, **kwargs
Is it possible to create a better solution which still prevents inconsistent state? My own solution doesn't seem like a good one from a database design point of view.
python django database schema normalization
New contributor
けんじ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
It would be great if the downvoter taught me what I did wrong, instead of just voting me down...
– けんじ
yesterday
One factor to consider is what happens if a worker changes organizations. Is that allowed? Do their tasks switch organizations too, or do they become unassigned? And so on. That might inform your design.
– Kevin Christopher Henry
yesterday
1
You want a task FK (worker, org) to worker. A FK says subrows must appear elsewhere a PKs. We need to identify all the restrictions that our database tables have & declare what we can as constraints & enforce others via triggers. This is a faq, that you might find if you googled many clear concise specific phrasings of your question/problem/goal. with & without your particular strings/names. PS Re downvoter presumably they think it is either unclear and/or not useful (maybe because it's a faq or there's no Minimal, Complete, and Verifiable example)--see the downvote arrow mouseover text.
– philipxy
yesterday
You'd need to implement acheck
. I got it from this answer: stackoverflow.com/a/39884447/1637351
– schillingt
23 hours ago
To add to @philipxy answer, I have found this post which also suggests a composite foreign key. To that end I have found this django module: django-composite-foreignkey
– CoffeeBasedLifeform
6 hours ago
add a comment |
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I am trying to write a django app with a PostgreSQL database. My problem can be reduced to the following minimal example:
Organization
- has 0 ... N workers
Worker
- belongs to an organization
Task
- belongs to an organization
- is assigned to no-one, or assigned to one worker within the same organization
I am unsure of how to design the database in a way that prevents inconsistent state - since both Worker and Task need to have a foreign key pointing to the Organization they belong to, it is possible to end up with an inconsistent state where a worker from organization A is assigned a task from organization B.
The only solution I could think of was verifying the constraint in the save method:
class Organization(models.Model):
name = models.CharField(max_length=255)
class Worker(models.Model):
name = models.CharField(max_length=255)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
class Task(models.Model):
name = models.CharField(max_length=255)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
assigned_to = models.ForeignKey(Worker, null=True, on_delete=models.SET_NULL)
def save(self, *args, **kwargs):
if self.assigned_to and self.assigned_to.organization != self.organization:
raise ValidationError('Task and Worker belong in different Organizations.')
return super(Task, self).save(*args, **kwargs
Is it possible to create a better solution which still prevents inconsistent state? My own solution doesn't seem like a good one from a database design point of view.
python django database schema normalization
New contributor
けんじ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
I am trying to write a django app with a PostgreSQL database. My problem can be reduced to the following minimal example:
Organization
- has 0 ... N workers
Worker
- belongs to an organization
Task
- belongs to an organization
- is assigned to no-one, or assigned to one worker within the same organization
I am unsure of how to design the database in a way that prevents inconsistent state - since both Worker and Task need to have a foreign key pointing to the Organization they belong to, it is possible to end up with an inconsistent state where a worker from organization A is assigned a task from organization B.
The only solution I could think of was verifying the constraint in the save method:
class Organization(models.Model):
name = models.CharField(max_length=255)
class Worker(models.Model):
name = models.CharField(max_length=255)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
class Task(models.Model):
name = models.CharField(max_length=255)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
assigned_to = models.ForeignKey(Worker, null=True, on_delete=models.SET_NULL)
def save(self, *args, **kwargs):
if self.assigned_to and self.assigned_to.organization != self.organization:
raise ValidationError('Task and Worker belong in different Organizations.')
return super(Task, self).save(*args, **kwargs
Is it possible to create a better solution which still prevents inconsistent state? My own solution doesn't seem like a good one from a database design point of view.
python django database schema normalization
python django database schema normalization
New contributor
けんじ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
けんじ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
けんじ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
asked yesterday
けんじ
191
191
New contributor
けんじ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
けんじ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
けんじ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
It would be great if the downvoter taught me what I did wrong, instead of just voting me down...
– けんじ
yesterday
One factor to consider is what happens if a worker changes organizations. Is that allowed? Do their tasks switch organizations too, or do they become unassigned? And so on. That might inform your design.
– Kevin Christopher Henry
yesterday
1
You want a task FK (worker, org) to worker. A FK says subrows must appear elsewhere a PKs. We need to identify all the restrictions that our database tables have & declare what we can as constraints & enforce others via triggers. This is a faq, that you might find if you googled many clear concise specific phrasings of your question/problem/goal. with & without your particular strings/names. PS Re downvoter presumably they think it is either unclear and/or not useful (maybe because it's a faq or there's no Minimal, Complete, and Verifiable example)--see the downvote arrow mouseover text.
– philipxy
yesterday
You'd need to implement acheck
. I got it from this answer: stackoverflow.com/a/39884447/1637351
– schillingt
23 hours ago
To add to @philipxy answer, I have found this post which also suggests a composite foreign key. To that end I have found this django module: django-composite-foreignkey
– CoffeeBasedLifeform
6 hours ago
add a comment |
It would be great if the downvoter taught me what I did wrong, instead of just voting me down...
– けんじ
yesterday
One factor to consider is what happens if a worker changes organizations. Is that allowed? Do their tasks switch organizations too, or do they become unassigned? And so on. That might inform your design.
– Kevin Christopher Henry
yesterday
1
You want a task FK (worker, org) to worker. A FK says subrows must appear elsewhere a PKs. We need to identify all the restrictions that our database tables have & declare what we can as constraints & enforce others via triggers. This is a faq, that you might find if you googled many clear concise specific phrasings of your question/problem/goal. with & without your particular strings/names. PS Re downvoter presumably they think it is either unclear and/or not useful (maybe because it's a faq or there's no Minimal, Complete, and Verifiable example)--see the downvote arrow mouseover text.
– philipxy
yesterday
You'd need to implement acheck
. I got it from this answer: stackoverflow.com/a/39884447/1637351
– schillingt
23 hours ago
To add to @philipxy answer, I have found this post which also suggests a composite foreign key. To that end I have found this django module: django-composite-foreignkey
– CoffeeBasedLifeform
6 hours ago
It would be great if the downvoter taught me what I did wrong, instead of just voting me down...
– けんじ
yesterday
It would be great if the downvoter taught me what I did wrong, instead of just voting me down...
– けんじ
yesterday
One factor to consider is what happens if a worker changes organizations. Is that allowed? Do their tasks switch organizations too, or do they become unassigned? And so on. That might inform your design.
– Kevin Christopher Henry
yesterday
One factor to consider is what happens if a worker changes organizations. Is that allowed? Do their tasks switch organizations too, or do they become unassigned? And so on. That might inform your design.
– Kevin Christopher Henry
yesterday
1
1
You want a task FK (worker, org) to worker. A FK says subrows must appear elsewhere a PKs. We need to identify all the restrictions that our database tables have & declare what we can as constraints & enforce others via triggers. This is a faq, that you might find if you googled many clear concise specific phrasings of your question/problem/goal. with & without your particular strings/names. PS Re downvoter presumably they think it is either unclear and/or not useful (maybe because it's a faq or there's no Minimal, Complete, and Verifiable example)--see the downvote arrow mouseover text.
– philipxy
yesterday
You want a task FK (worker, org) to worker. A FK says subrows must appear elsewhere a PKs. We need to identify all the restrictions that our database tables have & declare what we can as constraints & enforce others via triggers. This is a faq, that you might find if you googled many clear concise specific phrasings of your question/problem/goal. with & without your particular strings/names. PS Re downvoter presumably they think it is either unclear and/or not useful (maybe because it's a faq or there's no Minimal, Complete, and Verifiable example)--see the downvote arrow mouseover text.
– philipxy
yesterday
You'd need to implement a
check
. I got it from this answer: stackoverflow.com/a/39884447/1637351– schillingt
23 hours ago
You'd need to implement a
check
. I got it from this answer: stackoverflow.com/a/39884447/1637351– schillingt
23 hours ago
To add to @philipxy answer, I have found this post which also suggests a composite foreign key. To that end I have found this django module: django-composite-foreignkey
– CoffeeBasedLifeform
6 hours ago
To add to @philipxy answer, I have found this post which also suggests a composite foreign key. To that end I have found this django module: django-composite-foreignkey
– CoffeeBasedLifeform
6 hours ago
add a comment |
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
けんじ is a new contributor. Be nice, and check out our Code of Conduct.
けんじ is a new contributor. Be nice, and check out our Code of Conduct.
けんじ is a new contributor. Be nice, and check out our Code of Conduct.
けんじ is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53179127%2fkeeping-database-foreign-keys-consistent%23new-answer', 'question_page');
}
);
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
yjh,j6Ei84mCF5RXWFbxgblFruGj8xApQaMQ waTQ,6LunYq1 cevuDEJbMrM8zHjT09hIw7GTjLivISqse 9VoJfxY,uhccJo
It would be great if the downvoter taught me what I did wrong, instead of just voting me down...
– けんじ
yesterday
One factor to consider is what happens if a worker changes organizations. Is that allowed? Do their tasks switch organizations too, or do they become unassigned? And so on. That might inform your design.
– Kevin Christopher Henry
yesterday
1
You want a task FK (worker, org) to worker. A FK says subrows must appear elsewhere a PKs. We need to identify all the restrictions that our database tables have & declare what we can as constraints & enforce others via triggers. This is a faq, that you might find if you googled many clear concise specific phrasings of your question/problem/goal. with & without your particular strings/names. PS Re downvoter presumably they think it is either unclear and/or not useful (maybe because it's a faq or there's no Minimal, Complete, and Verifiable example)--see the downvote arrow mouseover text.
– philipxy
yesterday
You'd need to implement a
check
. I got it from this answer: stackoverflow.com/a/39884447/1637351– schillingt
23 hours ago
To add to @philipxy answer, I have found this post which also suggests a composite foreign key. To that end I have found this django module: django-composite-foreignkey
– CoffeeBasedLifeform
6 hours ago