I'm trying to have a model with 2 ManyToMany fields without allowing a backwards relation.
So here is the model:
class Camp(models.Model):
#...
free_options = models.ManyToManyField('Option', related_name='+')
paid_options = models.ManyToManyField('Option', related_name='+')
After trying to do
python manage.py syncdb
I'm getting the following error:
Error: One or more models did not validate: camps.camp: Accessor for
m2m field 'free_options' clashes with related m2m field 'Option.+'.
Add a related_name argument to the definition for 'free_options'.
camps.camp: Reverse query name for m2m field 'free_options' clashes
with related m2m field 'Option.+'. Add a related_name argument to the
definition for 'free_o ptions'.
Is it not possible to have 2 fields without backwards relation on the same model? how can i fix this?
Thanks!
I would ask why you're bothered by having the backwards relation, just don't use it if you don't want it. But to answer the question, no there isn't a way to remove it entirely.
According to the Django documentation for the related_name argument of the ManyToManyField:
If you have more than one ManyToManyField pointing to the same model
and want to suppress the backwards relations, set each related_name to
a unique value ending with '+'
Emphasis mine.
So if you want to do that, you should be able to simply:
class Camp(models.Model):
#...
free_options = models.ManyToManyField('Option', related_name='free_options+')
paid_options = models.ManyToManyField('Option', related_name='paid_options+')
# ^^^^^^^^^^^^
to suppress the backwards relation on multiple ManyToManyField's in the same model.
Hope this helps!
Related
I'm making an application and I should make a Model which have 2 keys that saves models of the same type.
It's not easy to express in English so I will upload the image of the situation.
In Food Pair Model ( or we can call it table I think )
I want to refer Food Model But I wasn't able to use ForeignKey or ManyToManyField.
ERRORS:
food_test.FoodQuestion.left_food: (fields.E304) Reverse accessor for 'FoodQuestion.left_food' clashes with reverse accessor for 'FoodQuestion.right_food'.
HINT: Add or change a related_name argument to the definition for 'FoodQuestion.left_food' or 'FoodQuestion.right_food'.
food_test.FoodQuestion.right_food: (fields.E304) Reverse accessor for 'FoodQuestion.right_food' clashes with reverse accessor for 'FoodQuestion.left_food'.
HINT: Add or change a related_name argument to the definition for 'FoodQuestion.right_food' or 'FoodQuestion.left_food'.
I don't know what database relation to use in this case and how to make it.
What can I use for this case?
When you create a ForeignKey from one model to another Django will dynamically create a property on the model being referenced that will return a QuerySet with all objects that have the foreign key to that object
For example
class Foo(models.Model):
pass
class Bar(models.Model):
foo = models.ForeignKey(Foo, on_delete=models.CASCADE)
foo = Foo.objects.create()
bar = Bar.objects.create(foo=foo)
foo.bar_set.all() # This will return a queryset containing foo
By default this property will be <model_name_lowercase>_set. In your case because you have 2 foreign keys from one model to the same model Django is trying to create the same property on the Food model for each foreign key.
To get around this issue you can specify the name of this property using related_name, if you set this to '+' no reverse relation will be made at all or give them unique names
class FoodQuestion(models.Model):
left_food = models.ForeignKey(Food, on_delete=models.CASCADE, related_name='+')
left_food = models.ForeignKey(Food, on_delete=models.CASCADE, related_name='+')
You must define a unique related_name for each ForeignKey field in your FoodPair model.
class FoodPair(models.Model):
first_food = models.ForeignKey(Food, related_name="first_food")
second_food = models.ForeignKey(Food, related_name="second_food")
what_i_buy = models.ForeignKey(Food, related_name="what_i_buy")
If related_name is not defined Django automatically sets it and when there is multiple ForeignKey fields pointing to the same model the names clash.
I am building the example django polls application. I want to exclude all polls, which have no choices. For that I have to access the related choices objects:
return Question.objects.filter(
pub_date__lte=timezone.now()
).exclude(
choice_set__count=0
).order_by('-pub_date')[:5]
But this query results in a field error:
Cannot resolve keyword 'choice_set' into field. Choices are: choice, id, pub_date, question_text
How can I query related models from the query?
To filter against a related model, you just use the lower-case model name - you can see that choice is one of the available fields.
However, this still won't work; there is no __count attribute to filter against. You can add one by using annotations, but there is a simpler way: compare against None:
.exclude(choice=None)
In the Choice model set the related_name to the Question foreign key.
Example:
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='choices')
# other code..
And then your query should be something like that:
return (Question.objects
.filter(pub_date__lte=timezone.now(),
choices__isnull=False)
.order_by('-pub_date')[:5])
Note: There is no `__count' lookup. If you want to rely on counts then check the docs on this.
docs: https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.ForeignKey.related_name
The _set only applies when you are using that to retrieve the related model outside of the queryset, instead, as the error suggests, you can just use choice
.exclude(choice__isnull=True)
I have two Django models which inherit from a base class:
- Request
- Inquiry
- Analysis
Request has two foreign keys to the built-in User model.
create_user = models.ForeignKey(User, related_name='requests_created')
assign_user = models.ForeignKey(User, related_name='requests_assigned')
For some reason I'm getting the error
Reverse accessor for 'Analysis.assign_user' clashes with reverse accessor for 'Inquiry.assign_user'.
Everything I've read says that setting the related_name should prevent the clash, but I'm still getting the same error. Can anyone think of why this would be happening? Thanks!
The related_name would ensure that the fields were not conflicting with each other, but you have two models, each of which has both of those fields. You need to put the name of the concrete model in each one, which you can do with some special string substitution:
create_user = models.ForeignKey(User, related_name='%(class)s_requests_created')
This is code in models.py
class Package(models.Model):
name=models.CharField(max_length=300)
version=models.CharField(max_length=300,blank=True)
home_page=models.URLField(blank=True)
summary=models.TextField()
description=models.TextField(blank=True)
keywords=models.TextField(blank=True)
categories=models.ManyToManyField(Category,related_name='packages')
class Category(models.Model):
topic=models.ForeignKey(Package, related_name="categories")
When i try to syncdb it says "NameError Category is not defined" i tried placing class category first and package next this time it says "NameError name Package is not defined".
Please help me out of this problem.
EDIT:
Thanks for the help guys, from a very little knowledge of what i know in databases the tutorial here seems wrong http://toys.jacobian.org/presentations/2007/pycon/tutorials/beginning/
He has defined the field categories in Packages to be many-to-many and the field in Category topic to be a foreign key to Package ,but a foreign key is a many-to-one relationship, therefore the implementation is flawed.
I think django is trying to tell it in its way as "Accessor for field 'topic' clashes with m2m field 'Package.categories'." Reverse query name for field 'topic' clashes with m2m field ' "
Is that correct?
"If you need to create a relationship on a model that has not yet been defined, you can use the name of the model, rather than the model object itself..."
class Package(models.Model):
...
categories=models.ManyToManyField('Category', related_name='packages')
Add quotes while you define category ManyToManyField.
Change to:
categories=models.ManyToManyField('Category',related_name='packages')
Reason: Category is not defined while you add that field, so need to add quotes around it so that django will resolve it later.
I recently got a ForeignKey clash in my Django model. I have the need to have two foreign keys (owner, assigned_to) ultimately pointing to the same model (a user).
From what I understand I need a related_name argument to solve that problem. So I did that:
assigned_to = models.ForeignKey(TaskUser, blank=True, null=True, related_name='user_assignment')
and
owner = models.ForeignKey(TaskUser, related_name="user_ownership"
But I'm still getting an error:
tasks.task: Accessor for field 'owner' clashes with related field 'TaskUser.user
_ownership'. Add a related_name argument to the definition for 'owner'.
tasks.task: Reverse query name for field 'owner' clashes with related field 'TaskUser.user_ownership'. Add a related_name argument to the definition for 'owner'.
Why am I still getting this error?
There is one catch, owner is in a super class (BaseWidget) and assigned_to is in a sub class (Task). Are there issues with using related_name in an inheritance relationship? Do I need to just override the inheritance of owner and redefine related_name in the sub class instead? I'd appreciate any help!
If you have ForeignKey relationships in an abstract base class every class inheriting from it will have this relationship. As a result of this you must not 'hardcode' its related_name, because all sub classes will try to create the same accessor on the realted class (TaskUser in this case).
You should better do something like:
owner = models.ForeignKey(TaskUser, related_name="%(app_label)s_%(class)s_ownership")
See the django docs on this.
If you are using related_name in abstract base class you need to use a '%(app_label)s' and '%(class)s' in it.
Its mentioned in django doc
Be careful with related_name