Django: Access model through another model - django

class Project(models.Model):
title = models.CharField()
class Job(models.Model):
name = models.CharField()
user = models.ForeignKey(User)
project = models.ForeignKey(Project)
I have many jobs for each project. How do i get a list of all users of all jobs of a project?
I came up with this:
users = set()
for job in project.job_set.all():
users.add(job.user)
Is there an easier way without explicitely looping through every job?

Use Django's join syntax and start from your User model instead:
users = User.objects.filter(job_set__project=project).distinct()

Alternatively, you could use a ManyToMany relation from Project to User through the Job model which is in effect a join model:
class Project(models.Model):
users = models.ManyToManyField(User, through='Job')
...
And then simply do:
project.users.all()

Related

Multiple many-to-many relations through the same model in Django problem

i have a problem i don't know how to make multiple many-to-many relations through the same model.
This is my DB relations :
Db architecture
and this is my code, i want to know if what I did is right or not ?
class Projects(models.Model):
Project_name = models.CharField(max_length=50)
Poject_key = models.CharField(max_length=50)
CITools = models.ForeignKey(CITools,null=True,on_delete=models.CASCADE)
UsersO = models.ManyToManyField(User,through='OwnerShips') # for user Ownerships
UserF = models.ManyToManyField(User,through='Favorites') # for user Favorites
This is my OwnerSHips class :
class OwnerShips(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
project = models.ForeignKey(Projects,on_delete=models.CASCADE)
And this is my Favorites Class:
class Favorites(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
project = models.ForeignKey(Projects,on_delete=models.CASCADE)
I don't think you can use foreign keys (ownerships and favorites) in Project before those classes are created.
Actually i found the solution, i used the attribute related_name, so Django to create this two tables automatically

How access the all the child of a object related to a model in django?

I'm not sure if my question makes sense, but here is what I'm trying to do:
I have Two Models:
class Task(models.Model):
title = models.CharField()
tasklist = models.ForeignKey('TaskList')
class TaskList(models.Model):
title = models.CharField()
users = models.ManyToManyField(User, related_name="lists")
How can I get all the tasks for a single User in one line?
Or is the code below the only solution?
user_tasks = []
user_tasklists = request.user.tasklists.all()
for list in user_tasklists:
for task in list.task_set.all():
user_tasks.append(task)
Assuming you have a user:
user = User.objects.get(pk=some_pk)
# Or if you need get the user from request:
# user = request.user
user_tasks = user.tasklist_set.all()
Now user_tasks is a queryset, so you can filter, or apply any queryset function.
To get Tasks (as shown in your last edit), you need query Task model:
Task.objects.filter(tasklist__users=user)
You can find the related objects documentation here

Django many-to-many lookup from different models

I have some models that represents some companies and their structure. Also all models can generate some Notifications (Notes). User can see own Notes, and, of course, can't see others.
class Note(models.Model):
text = models.CharField(...)
class Company(models.Model):
user = models.ForeignKey(User)
note = models.ManyToManyField(Note, blank='True', null='True')
class Department(models.Model):
company = models.ForeignKey(Company)
note = models.ManyToManyField(Note, blank='True', null='True')
class Worker(models.Model):
department = models.ForeignKey(Department)
note = models.ManyToManyField(Note, blank='True', null='True')
class Document(models.Model)
company = models.ForeignKey(Company)
note = models.ManyToManyField(Note, blank='True', null='True')
The question is how I can collect all Notes for particular user to show them?
I can do:
Note.objects.filter(worker__company__user=2)
But its only for Notes that was generated by Workers. What about another? I can try hardcoded all existing models, but if do so dozen of kittens will die!
I also tried to use backward lookups but got "do not support nested lookups". May be I did something wrong.
EDIT:
As I mentioned above I know how to do this by enumerating all models (Company, Worker, etc. ). But if I will create a new model (in another App for example) that also can generate Notes, I have to change code in the View in another App, and that's not good.
You can get the Notes of a user by using the following query:
For example let us think that a user's id is 1 and we want to keep it in variable x so that we can use it in query. So the code will be like this:
>>x = 1
>>Note.objects.filter(Q(**{'%s_id' % 'worker__department__company__user' : x})|Q(**{'%s_id' % 'document__company__user' : x})|Q(**{'%s_id' % 'company__user' : x})|Q(**{'%s_id' % 'department__company__user' : x})).distinct()
Here I am running OR operation using Q and distinct() at the end of the query to remove duplicates.
EDIT:
As I mentioned above I know how to do this by enumerating all models
(Company, Worker, etc. ). But if I will create a new model (in another
App for example) that also can generate Notes, I have to change code
in the View in another App, and that's not good.
In my opinion, if you write another model, how are you suppose to get the notes from that model without adding new query? Here each class (ie. Department, Worker) are separately connected to Company and each of the classes has its own m2m relation with Note and there is no straight connection to User with Note's of other classes(except Company). Another way could be using through but for that you have change the existing model definitions.
Another Solution:
As you have mentioned in comments, you are willing to change the model structure if it makes your query easier, then you can try the following solution:
class BaseModel(models.Model):
user = models.Foreignkey(User)
note = models.ManyToManyField(Note)
reports_to = models.ForeignKey('self', null=True, default=None)
class Company(BaseModel):
class Meta:
proxy = True
class Document(BaseModel):
class Meta:
proxy = True
#And so on.....
Advantages: No need to create separate table for document/company etc.
object creation:
>>c= Company.objects.create(user_id=1)
>>c.note.add(Note.objects.create(text='Hello'))
>>d = Document.objects.create(user_id=1, related_to=c)
>>d.note.add(Note.objects.create(text='Hello World'))

Django :Suggestion for django model

I am using django models to create my database .
here is my User Class
class User(models.Model):
user_name = models.CharField(max_length=100,null = False)
first_name = models.CharField(max_length=100)
middle_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
tags = here what to do ?
now i am planning to add tags for User so that user can select the tags (it can be more then one also )
Here is my Tags Class
Class Tags(models.Model)
tag = models.CharField()
my question is which relation should i use for the reference Tags from User table (Foreign key or Manytomany )
Note: In future i will search the users based on tags so please suggest me the better way to do this
Use a ManytoMany relationship: different users may use the same tags and a single User will have several tags:
tags= models.ManyToManyField(Tags, verbose_name="list of tags")
Anyway, you don't have to implement a Model for the User, there is a User model that comes with django. See the docs:
Django docs
Django book

Django Forms With foreign key

I have 2 models in django, and im also using ModelForm, my question is the second model have a froreignkey of the 1, and i want to have one page when generating the form. It's possible, how to link the two forms in one page.
Class Event(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField()
class Date(models.Model):
id = models.AutoField(primary_key=True)
start = models.DateTimeField()
end = models.DateTimeField()
event = models.ForeignKey("Event")
I also have
class EventForm(ModelForm)
Class Date(ModelForm)
What i want is to create the event in one page in my templates.
Thanks.
If you want to have this on the Django Admin, then you need to use inline models.
If you plan to create your own form (using ModelForms), then you need to use inline formets.