I have a complex relation scenario as shown below. I'd like limit_choices_to Questions that are related to JobChecklistAnswer.job_checklist.checklist on JobChecklistAnswer.question.
How can I filter those Questions as Q object (or callable as the docs say)?
class Checklist(models.Model):
name = models.CharField(_("name"), max_length=150)
description = models.CharField(_("description"), max_length=150)
class Question(models.Model):
checklist = models.ForeignKey(Checklist, on_delete=models.CASCADE)
question = models.CharField(_("question"), max_length=200)
class Job(models.Model):
...
...
class JobChecklist(models.Model):
job = models.ForeignKey(Job, on_delete=models.CASCADE)
checklist = models.ForeignKey(Checklist, on_delete=models.CASCADE)
class JobChecklistAnswer(models.Model):
job_checklist = models.ForeignKey(JobChecklist, on_delete=models.CASCADE)
# FIXME: Add limit_choices_to query question
question = models.OneToOneField(ChecklistItem, on_delete=models.CASCADE)
answer = models.TextField(_("answer"))
In contrast to the OneToOneField "reverse" relation, a ForeignKey "reverse" relation returns a QuerySet.
You are not returning a queryset here in the OneToOneField, You are only reversing a relation between them
So the first step is to change OneToOneField into a ForeignKey
then you can use limit_choices_to attribute on ForeignKey
Related
one of the questions that came to my mind is that in a many-to-one relationship in Django, where should the foreign key be located? I mean, it should be in many or in part one?
For example, we have two classes, post and comment: in this case, where should the ForeignKey be located in the comment or post class?
post model :
class post(models.model):
created_at = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ManyToManyField("PostCategory", blank=True)
caption = models.CharField(max_length=2000)
comment model :
class Comment(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
verbose_name=_('user'), on_delete=models.CASCADE)
text = models.TextField()
Now here is the comment field where the foreign key should be defined?
Foreign key must be used on the "Many" side of the Many-to-one relationships.
In your question, you have Post and Comment models. Since each post can have many comments, you should put a foreign key into your Comment model.
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
I am making an app that is pretty much similar to google classroom in django.
I have a Course model and an assignment model, and I want to connect an assignment to the specified course.
These are my models
class Assignment(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
date_created = models.DateTimeField(default=timezone.now)
class Course(models.Model):
title = models.CharField(max_length=100)
subject = models.CharField(max_length=100)
image = models.ImageField(default='no_course_image.jpg', upload_to='course_images')
owner = models.ForeignKey(User, on_delete=models.CASCADE)
students_invited = models.ManyToManyField(User, null=True, blank=True)
assignments = models.ManyToManyField(Assignment, null=True, blank=True)
date_published = models.DateTimeField(default=timezone.now)
class Meta:
verbose_name_plural = 'Course'
ordering = ['-date_published']
def __str__(self):
return '{} - {}'.format(self.title, self.owner)
But i am getting an error when I specify the course field in the assignment model with the ForeignKey!
Could you please help me with how to connect the assignment to the Course model?
Thank you
ForeignKey is used to setup a many to one relationship. As you are trying to setup a ManyToManyField it won't work in this situation as you can see in the Django documentation
ForeignKey¶
class ForeignKey(to, on_delete, **options)¶
A many-to-one relationship. Requires two positional arguments:
the class to which the model is related and the on_delete option.
In fact you don't even need to set the relation in the Assignment Model as Django will take care of creating a third table linking the two together by their primary keys. You can see this in the documentation
from django.db import models
class Publication(models.Model):
title = models.CharField(max_length=30)
class Meta:
ordering = ['title']
def __str__(self):
return self.title
class Article(models.Model):
headline = models.CharField(max_length=100)
publications = models.ManyToManyField(Publication)
class Meta:
ordering = ['headline']
def __str__(self):
return self.headline
So every time you add the assignment to the course like so
>>> c1 = Course(title='Python Course')
>>> c1.save()
>>> a1 = Assignment(name='Python Assignment')
>>> a1.save()
>>> c1.assignments.add(a1)
And the relation will automatically be created and c1.assignments.all() will return all the assignments linked to the course
If you need to go the other way around then you would use a1.course_set.add(c1). When using the model that doesn't have the ManyToManyField object tied to it you need to use the *_set notation where * will be replaced by the model name in lower case. Can read more about Related Objects references in the docs here
When you try to create the Model Assignment with reference to the model Course, the Course Model has not yet created and vice versa and you will get an error either of the model is not defined
You can use the quotes for it
class Assignment(models.Model):
course = models.ForeignKey('Course', on_delete=models.CASCADE)
name = models.CharField(max_length=100)
date_created = models.DateTimeField(default=timezone.now)
You can use a custom through model enter link description here
I guess the Course model has to be written before the Assignment model.
How should I give ForeignKey to model?
Now models.py has User&Item table like
from django.db import models
# Create your models here.
class User(models.Model):
user_id = models.CharField(max_length=200)
name_id = models.CharField(max_length=200)
regist_date = models.DateTimeField(auto_now=True)
class Item(models.Model):
user_id = models.CharField(max_length=200)
name = models.CharField(max_length=200)
item_name = models.CharField(max_length=200)
price = models.CharField(max_length=200)
I wanna treat user_id&name_id as Foreing key.User table is parent table,and Item is child one.I think user_id&name_id in Item should have ForeignKey like
class Item(models.Model):
user_id = models.ForeignKey()
name = models.ForeignKey()
However,how should I connect these 2 model is User is parent&Item is child ?How should I write it?
For sure, you have to read that.
Looks like One User -> Many Items.
Its ForeignKey and we have to set it in User model.
class Item(models.Model):
...
class User(models.Model):
...
item = models.ForeignKey(Item)
You can use something like
class Item(models.Model):
user = models.ForeignKey(User, related_name='items')
Accessing user_id from item will be
item.user.user_id
Accessing all items from a user will be
user.items.all()
It's a good idea to read the documentation on the ForeignKey field.
As for your question, you can connect the Item model to the User model like this:
class Item(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
Again, it's a good idea to read the documentation and figure out what exactly you need, such as what to do when a User object is deleted (the on_delete part in my code).
I have the following model (below).
I would like a query that returns every record of parent Question(models.Model), where ALL the values for the is_relevant field within the child Choice(models.Model) are "True".
Having a difficult time creating the QuerySet. Any Assistance would be very helpful.
model.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
is_relevant = models.BooleanField()
You can use the reverse relationship of the Question model like so:
Question.objects.filter(choice__is_relevant=True)
The choice in choice__is_relevant is the lowercase name of the model Choice.
Reference: Relationship lookups
I have an abstract base class that declares two foreign key fields to the user model:
class BaseModel(models.Model):
updated = models.DateTimeField(null=True)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, related_name="updated_by")
created = models.DateTimeField(null=True)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, related_name="created_by")
class Meta:
abstract=True
I have multiple classes that inherit from this class. When I run makemigrations, I get the following error for each possible class-pair and for both created_by and updated_by:
myapp.ClassA.updated_by: (fields.E305) Reverse query name for 'ClassB.updated_by' clashes with reverse query name for 'ClassB.updated_by'.
HINT: Add or change a related_name argument to the definition for 'ClassA.updated_by' or 'ClassB.updated_by'.
Even though I already have a related_name set. It works fine with just one of the two foreign key fields declared.
Is it possible to have two foreign key fields to the same model in an abstract class, and if so, how do I set it up?
This is the expected behavior as mentioned in the documentation.
To work around this problem, when you are using related_name in an abstract base class (only), part of the name should contain '%(app_label)s' and '%(class)s'.
class BaseModel(models.Model):
updated = models.DateTimeField(null=True)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, related_name="updated%(app_label)s_%(class)s_related")
created = models.DateTimeField(null=True)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, related_name="created%(app_label)s_%(class)s_related")
class Meta:
abstract=True
Since you use the related_name more than once, in model classes you inherit, then related name for the user model is not clear and clashes.
You will have to set a different related_name for each model.