Django ListView Through Model Relationships - django

I have been reading through here and I can't seem to find the answer of the question I am looking for. Maybe I'm not asking the correct question.
I have three models.
Recruiter
Office
Recruit
Recruiters are assigned to multiple offices and each office has multiple employees. What I need to be able to do is create a listview that lists all of the employees that are associated with a recruiter. So something like this:
Recruiter 1 has Office 1 and 2 assigned to them. Office 1 has Employee 1,2,3. Office 2 has employee 3,4,5
The Listview should display all employees under Recruiter 1.
My Models are:
class Recruit(models.Model):
id = models.CharField(max_length=25,primary_key=True, unique=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
mobile_phone = models.CharField(max_length=20,null=True)
preferred_phone = models.CharField(max_length=20,null=True)
email= models.CharField(max_length=100,null=True)
officeid = models.ForeignKey(Office,on_delete=models.DO_NOTHING,related_name="recruit")
class Office(models.Model):
office_name = models.CharField(max_length=100)
officeid = models.CharField(max_length=20,primary_key=True,unique=True)
class Recruiter(models.Model):
user = models.OneToOneField(User, related_name='recruiter',on_delete=models.CASCADE)
organization = models.ForeignKey(UserProfile,on_delete=models.CASCADE)
Do I need a AssingedOffices table to join this all together?
class AssignedOffice(models.Model):
user = models.ForeignKey(UserProfile,on_delete=models.CASCADE)
esa_office = models.ForeignKey(Office,on_delete=models.CASCADE)
Just not sure how to connect them & display in the listview.
Edit Added start of view.
class MyESA(LoginRequiredMixin,ListView):
template_name = "recruits/recruits_list.html"
user= User.objects.select_related('recruiter')
paginate_by = 20
model=Recruit
context_object_name = 'recruits'
def get_queryset(self):
queryset = Recruit.objects.filter(probablity=1)
return queryset

If you want to achieve a Many-to-one relationship like this
Recruiters are assigned to multiple offices
then you should have a ForeignKey in the Office model not the other way around. I presume that each Office has one Recruiter. Otherwise you should have a Many-to-Many relationship that is constructed with a ManyToManyField
I presume that by
each office has multiple employees
You meant that each Office object has multiple Recruit objects
If you want to list all of the Recruit objects in a ListView for model Recruiter then I think the easiest way would be to add a ForeignKey field in the Recruit model and refer to it via related object reference

Related

Django admin: filter_horizontal with custom search/filter results

I have a simple model with ManyToManyField.
class Meeting(models.Model):
place = models.CharField()
date = models.DateField()
persons = models.ManyToManyField(Person)
Person model contains basic information about person.
class Person(models.Model):
login = models.CharField(unique=True)
first_name = models.CharField()
last_name = models.CharField()
def __str__(self):
return self.login
In my MeetingAdmin(ModelAdmin) class I have filter_horizontal('persons',) that is used for adding multiple people when creating new Meeting object. This works perfectly fine. In the left menu it's showing the list of all persons(filtering by login).
As you may know, filter_horizontal contains search box on the top of the left menu.
Examples
I would also like to be able to filter persons here by their first name and last name. For example, if there is a person with fields (login='mylogin', first_name='John', last_name='Smith') and I type 'Jo' or 'Smi' in search box, this person is displayed as a search result, etc. 'mylogin' since login field is representation of Person model.

Have each user have a model attached to them, and that model has a many to one relationship with items

I am trying to create a Django application where each User has one model attached to them ( a list of Plants ) and that model is composed of individual plants. I already know I can have the plants connected to the plant list through a many-to-one relationship using foreign key as shown down below:
class PlantList(models.Model):
plant_list_id = models.AutoField(primary_key=True)
class Plant(models.Model):
plantlist = models.ForeignKey(PlantList, on_delete = models.CASCADE)
name = models.CharField(max_length = 20)
wateringInterval = models.PositiveSmallIntegerField()
However, I want each user to have a plant list attached to them that can be displayed uniquely for each user, according to the plants that they add to their list. How would I make it so that each user has a plant list?
I was trying to have it inside the register form but couldn't figure out how to do it and I wanted each plantlist to have a unique ID so that I can add plants to it easier.
class AddNewPlant(forms.Form):
name = forms.CharField(label='Name',max_length = 20)
wateringInterval = forms.IntegerField(label='Watering Interval')
The thing is, you don't need the model PlantList.
What you should do instead is: set a ForeignKey to the User Model inside the Plant Model, and in that foreign_key set a related_name='plants'.
To access the User Model use:
from django.contrib.auth import get_user_model
code example:
class Plant(models.Model):
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='plants')
name = models.CharField(max_length = 20)
wateringInterval = models.PositiveSmallIntegerField()
Then you can access all user's plants using:
first_user = get_user_model().objects.first().plants
Try this:
class User(models.Model):
plant_list = models.ForeignKey(PlantList, on_delete=models.CASCADE)
this is for connecting plant_list with the user. Also, you need to change the relationship between plant and plant_list, so that users can have the same plants as well like below:
class Plant(models.Model):
plantlist = models.ManyToManyField(PlantList)
that way different users can have the same plants on their plant_list and every user has only one plant_list.

Django ManyToManyField reverse Relationship

I would like to do a reverse relationship on my table Tickets.
Here is my model :
class Tickets(models.Model):
ticket_title = models.CharField(max_length=100)
ticket_content = models.TextField()
class User_Detail(models.Model):
user = models.OneToOneField(User)
tickets = models.ManyToManyField(Tickets, blank=True, null=True)
I create my ticket like that :
ticket = Tickets.objects.create(ticket_title="test", ticket_content="test content")
request.user.user_detail.tickets.add(ticket)
and the thing I'm having an issue to do is to get the username of the guy who post the ticket, (without request.user)
so I tried like that :
ticket = Tickets.objects.get(pk=1)
ticket.user_detail_set.user.username
but I get
AttributeError: 'ManyRelatedManager' object has no attribute 'user'
Thanks you for watching, I hope you'll understand.
Since you set up a many-to-many relationship, a Ticket may have many User_Detail objects. Therefore, Ticket.user_detail_set is a manager, not a single object. You could get the first user associated with a Ticket like this:
ticket.user_detail_set.first().user.username
But it sounds like you actually want a one-to-many relationship between Ticket and User_Detail, meaning you actually want Ticket to have a foreign key relationship. Your models should probably look like this:
class User_Detail(models.Model):
user = models.OneToOneField(User)
class Ticket(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=100)
contents = models.TextField()
Then you can do:
ticket = Ticket.objects.get(pk=1)
user = ticket.user
You might even be able to drop the User_Detail model entirely, unless you use it elsewhere in your application and/or it has more fields than what is shown here.

django many to many admin shows all and not associated items

I have an object structure that looks like so:
Customer -- one to many -- Locations
Locations -- many to many -- Departments
Departments -- one to many -- Objects
here is my models.py (my admin.py is standard):
class Customer(models.Model):
customerName = models.CharField(max_length=64)
class Department(models.Model):
departmentName = models.CharField(max_length=64)
class Location(models.Model):
customer = models.ForeignKey(Customer)
departments = models.ManyToManyField(Department)
class Object(models.Model):
location = models.ForeignKey(Location)
department = models.ForeignKey(Department)
The problem is that when I want to set the department for objects I get every department in the django admin drop down. I even get the departments that are associate with locations of different customers.
Also, when I am setting the department of an object, I get the same list of all available departments, even those associated with different customers.
How can I have the drop down only show me the departments that a customer supports?
A quick one line solution to filter down a many to many relationship is put this line in your admin object:
filter_horizontal = ('departments',)
You can provide your own form with filtered queryset
class DepartmentAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(DepartmentAdminForm, self).__init__(*args, **kwargs)
self.fields['customers'].queryset = Customer.objects.filter(...)
class Meta:
model = Department
class DepartmentAdmin(admin.ModelAdmin):
form = DepartmentAdminForm
I believe the answer is to use the formfield_for_manytomany
https://docs.djangoproject.com/en/1.4/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_for_foreignkey

django manytomany through

If I have two Models that have a manytomany relationship with a through model, how do I get data from that 'through' table.
class Bike(models.Model):
nickname = models.CharField(max_length=40)
users = models.ManyToManyField(User, through='bike.BikeUser')
The BikeUser class
class BikeUser(models.Model):
bike = models.ForeignKey(Bike)
user = models.ForeignKey(User)
comment = models.CharField(max_length=140)
And I would add a user to that bike (presuming I have a myBike and a myUser already)
BikeUser.objects.create(bike = myBike, user = myUser, comment = 'Got this one at a fancy store')
I can get all the users on 'myBike' with myBike.users.all() but how do I get the 'comment' property?
I would like to do something like
for myBikeUser in myBike.users.all():
print myBikeUser.comment
The through table is linked by standard ForeignKeys, so you do a normal ForeignKey lookup. Don't forget that there's a comment for each bikeuser, ie one for each bike/user pairing.
for myBikeUser in myBike.bikeuser_set.all():
print myBikeUser.comment, myBikeUser.user.first_name