Unique Combination of ManyToMany
I'm trying to create a unique Availability status for Player on given Hour. Here goes the code:
class Player(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
class Hour(models.Model):
date = models.DateTimeField()
players = models.ManyToManyField(Player, blank=True,
through='Availability')
class Availability(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE)
hour = models.ForeignKey(Hour, on_delete=models.CASCADE)
available = models.BooleanField()
My problem is that it's currently possible to add same Availability few times - I want to programatically limit it to just one per combination.
Thanks in advance!
django django-models
add a comment |
I'm trying to create a unique Availability status for Player on given Hour. Here goes the code:
class Player(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
class Hour(models.Model):
date = models.DateTimeField()
players = models.ManyToManyField(Player, blank=True,
through='Availability')
class Availability(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE)
hour = models.ForeignKey(Hour, on_delete=models.CASCADE)
available = models.BooleanField()
My problem is that it's currently possible to add same Availability few times - I want to programatically limit it to just one per combination.
Thanks in advance!
django django-models
See docs for unique_together. This is enforced in the admin and at the database level. See this answer below.
– djvg
Jan 4 at 20:25
add a comment |
I'm trying to create a unique Availability status for Player on given Hour. Here goes the code:
class Player(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
class Hour(models.Model):
date = models.DateTimeField()
players = models.ManyToManyField(Player, blank=True,
through='Availability')
class Availability(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE)
hour = models.ForeignKey(Hour, on_delete=models.CASCADE)
available = models.BooleanField()
My problem is that it's currently possible to add same Availability few times - I want to programatically limit it to just one per combination.
Thanks in advance!
django django-models
I'm trying to create a unique Availability status for Player on given Hour. Here goes the code:
class Player(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
class Hour(models.Model):
date = models.DateTimeField()
players = models.ManyToManyField(Player, blank=True,
through='Availability')
class Availability(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE)
hour = models.ForeignKey(Hour, on_delete=models.CASCADE)
available = models.BooleanField()
My problem is that it's currently possible to add same Availability few times - I want to programatically limit it to just one per combination.
Thanks in advance!
django django-models
django django-models
asked Jun 25 '17 at 20:28
Franek MadejFranek Madej
7210
7210
See docs for unique_together. This is enforced in the admin and at the database level. See this answer below.
– djvg
Jan 4 at 20:25
add a comment |
See docs for unique_together. This is enforced in the admin and at the database level. See this answer below.
– djvg
Jan 4 at 20:25
See docs for unique_together. This is enforced in the admin and at the database level. See this answer below.
– djvg
Jan 4 at 20:25
See docs for unique_together. This is enforced in the admin and at the database level. See this answer below.
– djvg
Jan 4 at 20:25
add a comment |
3 Answers
3
active
oldest
votes
You can have the unique_together on the "throuh" table (in your case the Avaliability Table)
class Availability(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE)
hour = models.ForeignKey(Hour, on_delete=models.CASCADE)
available = models.BooleanField()
class Meta:
unique_together = (('player','hour'),)
And then use the get_or_create for adding/modifying:
obj,created = Availability.objects.get_or_create(hour=hour,player=player)
add a comment |
I've worked around it modifying save()
for Availability
:
def save(self, *args, **kwargs):
if self.pk is None:
combination = Availability.objects.filter(player=self.player,
hour=self.hour).first()
if combination:
self.pk = combination.pk
super(Availability, self).save(*args, **kwargs)
add a comment |
You can't have a unique
constraint in a ManyToManyField
, as reasoned in ticket 702. What you can do is validate the model when saving, as shown in an online snippet:
class MyModel(models.Model):
site = models.ManyToManyField(Site)
on_site = CurrentSiteManager()
foobar = ... # A unique field
def save(self, *args, **kwargs):
if self.id == None: # new item should be created.
# manually check a unique togeher, because django can't do this with a M2M field.
# Obsolete if unique_together work with ManyToMany: http://code.djangoproject.com/ticket/702
exist = MyModel.on_site.filter(foobar=self.foobar).count()
if exist != 0:
from django.db import IntegrityError
# We can use attributes from this model instance, because it needs to have a primary key
# value before a many-to-many relationship can be used.
site = Site.objects.get_current()
raise IntegrityError(
"MyModel item with same foobar field exist on site %r" % site
)
return super(MyModel, self).save(*args, **kwargs)
class Meta:
#unique_together = ("foobar", "site") # unique_together doesn't work with ManyToMany!
# See: http://code.djangoproject.com/ticket/702
Note that the logic can change depending on your goal. As Carl Meyer argues in the ticket linked above, different behavior can make sense in your model (e.g. a field being unique with every item of the ManyToManyField
or with the exact combination).
Sorry, but I believe this answer is incorrect: Ticket 702, as well as the docs for unique_together mention that "A ManyToManyField cannot be included in unique_together." I believe what the OP wants is the opposite, viz. to include foreign key fieldsplayer
andhour
from theAvailability
model in that model'sunique_together
. As described in the answer by Oded Har-Tal, this most certainly is possible.
– djvg
Jan 4 at 20:23
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f44750308%2funique-combination-of-manytomany%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can have the unique_together on the "throuh" table (in your case the Avaliability Table)
class Availability(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE)
hour = models.ForeignKey(Hour, on_delete=models.CASCADE)
available = models.BooleanField()
class Meta:
unique_together = (('player','hour'),)
And then use the get_or_create for adding/modifying:
obj,created = Availability.objects.get_or_create(hour=hour,player=player)
add a comment |
You can have the unique_together on the "throuh" table (in your case the Avaliability Table)
class Availability(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE)
hour = models.ForeignKey(Hour, on_delete=models.CASCADE)
available = models.BooleanField()
class Meta:
unique_together = (('player','hour'),)
And then use the get_or_create for adding/modifying:
obj,created = Availability.objects.get_or_create(hour=hour,player=player)
add a comment |
You can have the unique_together on the "throuh" table (in your case the Avaliability Table)
class Availability(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE)
hour = models.ForeignKey(Hour, on_delete=models.CASCADE)
available = models.BooleanField()
class Meta:
unique_together = (('player','hour'),)
And then use the get_or_create for adding/modifying:
obj,created = Availability.objects.get_or_create(hour=hour,player=player)
You can have the unique_together on the "throuh" table (in your case the Avaliability Table)
class Availability(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE)
hour = models.ForeignKey(Hour, on_delete=models.CASCADE)
available = models.BooleanField()
class Meta:
unique_together = (('player','hour'),)
And then use the get_or_create for adding/modifying:
obj,created = Availability.objects.get_or_create(hour=hour,player=player)
answered Nov 22 '18 at 7:04
Oded Har-TalOded Har-Tal
907
907
add a comment |
add a comment |
I've worked around it modifying save()
for Availability
:
def save(self, *args, **kwargs):
if self.pk is None:
combination = Availability.objects.filter(player=self.player,
hour=self.hour).first()
if combination:
self.pk = combination.pk
super(Availability, self).save(*args, **kwargs)
add a comment |
I've worked around it modifying save()
for Availability
:
def save(self, *args, **kwargs):
if self.pk is None:
combination = Availability.objects.filter(player=self.player,
hour=self.hour).first()
if combination:
self.pk = combination.pk
super(Availability, self).save(*args, **kwargs)
add a comment |
I've worked around it modifying save()
for Availability
:
def save(self, *args, **kwargs):
if self.pk is None:
combination = Availability.objects.filter(player=self.player,
hour=self.hour).first()
if combination:
self.pk = combination.pk
super(Availability, self).save(*args, **kwargs)
I've worked around it modifying save()
for Availability
:
def save(self, *args, **kwargs):
if self.pk is None:
combination = Availability.objects.filter(player=self.player,
hour=self.hour).first()
if combination:
self.pk = combination.pk
super(Availability, self).save(*args, **kwargs)
answered Jun 25 '17 at 21:52
Franek MadejFranek Madej
7210
7210
add a comment |
add a comment |
You can't have a unique
constraint in a ManyToManyField
, as reasoned in ticket 702. What you can do is validate the model when saving, as shown in an online snippet:
class MyModel(models.Model):
site = models.ManyToManyField(Site)
on_site = CurrentSiteManager()
foobar = ... # A unique field
def save(self, *args, **kwargs):
if self.id == None: # new item should be created.
# manually check a unique togeher, because django can't do this with a M2M field.
# Obsolete if unique_together work with ManyToMany: http://code.djangoproject.com/ticket/702
exist = MyModel.on_site.filter(foobar=self.foobar).count()
if exist != 0:
from django.db import IntegrityError
# We can use attributes from this model instance, because it needs to have a primary key
# value before a many-to-many relationship can be used.
site = Site.objects.get_current()
raise IntegrityError(
"MyModel item with same foobar field exist on site %r" % site
)
return super(MyModel, self).save(*args, **kwargs)
class Meta:
#unique_together = ("foobar", "site") # unique_together doesn't work with ManyToMany!
# See: http://code.djangoproject.com/ticket/702
Note that the logic can change depending on your goal. As Carl Meyer argues in the ticket linked above, different behavior can make sense in your model (e.g. a field being unique with every item of the ManyToManyField
or with the exact combination).
Sorry, but I believe this answer is incorrect: Ticket 702, as well as the docs for unique_together mention that "A ManyToManyField cannot be included in unique_together." I believe what the OP wants is the opposite, viz. to include foreign key fieldsplayer
andhour
from theAvailability
model in that model'sunique_together
. As described in the answer by Oded Har-Tal, this most certainly is possible.
– djvg
Jan 4 at 20:23
add a comment |
You can't have a unique
constraint in a ManyToManyField
, as reasoned in ticket 702. What you can do is validate the model when saving, as shown in an online snippet:
class MyModel(models.Model):
site = models.ManyToManyField(Site)
on_site = CurrentSiteManager()
foobar = ... # A unique field
def save(self, *args, **kwargs):
if self.id == None: # new item should be created.
# manually check a unique togeher, because django can't do this with a M2M field.
# Obsolete if unique_together work with ManyToMany: http://code.djangoproject.com/ticket/702
exist = MyModel.on_site.filter(foobar=self.foobar).count()
if exist != 0:
from django.db import IntegrityError
# We can use attributes from this model instance, because it needs to have a primary key
# value before a many-to-many relationship can be used.
site = Site.objects.get_current()
raise IntegrityError(
"MyModel item with same foobar field exist on site %r" % site
)
return super(MyModel, self).save(*args, **kwargs)
class Meta:
#unique_together = ("foobar", "site") # unique_together doesn't work with ManyToMany!
# See: http://code.djangoproject.com/ticket/702
Note that the logic can change depending on your goal. As Carl Meyer argues in the ticket linked above, different behavior can make sense in your model (e.g. a field being unique with every item of the ManyToManyField
or with the exact combination).
Sorry, but I believe this answer is incorrect: Ticket 702, as well as the docs for unique_together mention that "A ManyToManyField cannot be included in unique_together." I believe what the OP wants is the opposite, viz. to include foreign key fieldsplayer
andhour
from theAvailability
model in that model'sunique_together
. As described in the answer by Oded Har-Tal, this most certainly is possible.
– djvg
Jan 4 at 20:23
add a comment |
You can't have a unique
constraint in a ManyToManyField
, as reasoned in ticket 702. What you can do is validate the model when saving, as shown in an online snippet:
class MyModel(models.Model):
site = models.ManyToManyField(Site)
on_site = CurrentSiteManager()
foobar = ... # A unique field
def save(self, *args, **kwargs):
if self.id == None: # new item should be created.
# manually check a unique togeher, because django can't do this with a M2M field.
# Obsolete if unique_together work with ManyToMany: http://code.djangoproject.com/ticket/702
exist = MyModel.on_site.filter(foobar=self.foobar).count()
if exist != 0:
from django.db import IntegrityError
# We can use attributes from this model instance, because it needs to have a primary key
# value before a many-to-many relationship can be used.
site = Site.objects.get_current()
raise IntegrityError(
"MyModel item with same foobar field exist on site %r" % site
)
return super(MyModel, self).save(*args, **kwargs)
class Meta:
#unique_together = ("foobar", "site") # unique_together doesn't work with ManyToMany!
# See: http://code.djangoproject.com/ticket/702
Note that the logic can change depending on your goal. As Carl Meyer argues in the ticket linked above, different behavior can make sense in your model (e.g. a field being unique with every item of the ManyToManyField
or with the exact combination).
You can't have a unique
constraint in a ManyToManyField
, as reasoned in ticket 702. What you can do is validate the model when saving, as shown in an online snippet:
class MyModel(models.Model):
site = models.ManyToManyField(Site)
on_site = CurrentSiteManager()
foobar = ... # A unique field
def save(self, *args, **kwargs):
if self.id == None: # new item should be created.
# manually check a unique togeher, because django can't do this with a M2M field.
# Obsolete if unique_together work with ManyToMany: http://code.djangoproject.com/ticket/702
exist = MyModel.on_site.filter(foobar=self.foobar).count()
if exist != 0:
from django.db import IntegrityError
# We can use attributes from this model instance, because it needs to have a primary key
# value before a many-to-many relationship can be used.
site = Site.objects.get_current()
raise IntegrityError(
"MyModel item with same foobar field exist on site %r" % site
)
return super(MyModel, self).save(*args, **kwargs)
class Meta:
#unique_together = ("foobar", "site") # unique_together doesn't work with ManyToMany!
# See: http://code.djangoproject.com/ticket/702
Note that the logic can change depending on your goal. As Carl Meyer argues in the ticket linked above, different behavior can make sense in your model (e.g. a field being unique with every item of the ManyToManyField
or with the exact combination).
answered Apr 11 '18 at 11:27
Paulo AlmeidaPaulo Almeida
5,3531727
5,3531727
Sorry, but I believe this answer is incorrect: Ticket 702, as well as the docs for unique_together mention that "A ManyToManyField cannot be included in unique_together." I believe what the OP wants is the opposite, viz. to include foreign key fieldsplayer
andhour
from theAvailability
model in that model'sunique_together
. As described in the answer by Oded Har-Tal, this most certainly is possible.
– djvg
Jan 4 at 20:23
add a comment |
Sorry, but I believe this answer is incorrect: Ticket 702, as well as the docs for unique_together mention that "A ManyToManyField cannot be included in unique_together." I believe what the OP wants is the opposite, viz. to include foreign key fieldsplayer
andhour
from theAvailability
model in that model'sunique_together
. As described in the answer by Oded Har-Tal, this most certainly is possible.
– djvg
Jan 4 at 20:23
Sorry, but I believe this answer is incorrect: Ticket 702, as well as the docs for unique_together mention that "A ManyToManyField cannot be included in unique_together." I believe what the OP wants is the opposite, viz. to include foreign key fields
player
and hour
from the Availability
model in that model's unique_together
. As described in the answer by Oded Har-Tal, this most certainly is possible.– djvg
Jan 4 at 20:23
Sorry, but I believe this answer is incorrect: Ticket 702, as well as the docs for unique_together mention that "A ManyToManyField cannot be included in unique_together." I believe what the OP wants is the opposite, viz. to include foreign key fields
player
and hour
from the Availability
model in that model's unique_together
. As described in the answer by Oded Har-Tal, this most certainly is possible.– djvg
Jan 4 at 20:23
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f44750308%2funique-combination-of-manytomany%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
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
Required, but never shown
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
Required, but never shown
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
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
See docs for unique_together. This is enforced in the admin and at the database level. See this answer below.
– djvg
Jan 4 at 20:25