Query Django ORM with foreign key fields - django

I am having issues with using Django ORM queries in order to retrieve specific information. I have three models all linked by foreign keys, these are Hosts, Groups and Organisations. So each host belong to a group and these groups belong to an organisation. I need to get the query set of all hosts that belong to a specific organisation named 'Y' for example. Below are my model.py, can anybody help me to formulate a query set that will achieve this? or point me in the correct direction to figure this out?
Hosts
class Host(models.Model):
host_name = models.CharField(max_length=120, blank=False, unique=True)
url = models.CharField(max_length=120, blank=False, unique=True)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
slug = models.SlugField(blank=True, null=True)
def __str__(self):
return self.host_name
Groups
class Group(models.Model):
org_name = models.ForeignKey(Organization, on_delete=models.CASCADE)
group_name = models.CharField(max_length=120, blank=False, unique=True)
def __str__(self):
return self.group_name
Organizations
class Organization(models.Model):
org_name = models.CharField(max_length=120, blank=False, unique=True)
org_code = models.CharField(max_length=120, blank=False, unique=True, default=GenerateOrganozationCode)
def __str__(self):
return self.org_name

host_queryset = Host.objects.filter(group__org_name__org_name='Y')
For more detailed information and examples, please do refer to the official django doc

Related

How to make a query across multiple models in Django

I'm using Django and I want to know how to get objects through 3 models
These are my models
class Participant(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
is_leader = models.BooleanField(default=False)
team = models.ForeignKey(Team, on_delete=models.CASCADE, null=True, related_name="participants")
application_date = models.DateField(auto_now_add=True, null=True)
resolution_date = models.DateField(null=True, blank=True)
accepted = models.BooleanField(default=False)
class Team(models.Model):
name = models.TextField(default="")
is_public = models.BooleanField(default=False)
institution = models.ForeignKey(Institution, on_delete=models.CASCADE, null=True, related_name='teams')
campaign = models.ForeignKey(Campaign, on_delete=models.CASCADE, null=True, related_name='teams')
class Campaign(models.Model):
name = models.TextField(default="")
description = models.TextField(default="")
initial_date = models.DateTimeField(auto_now_add=False, null=True, blank=True)
end_date = models.DateTimeField(auto_now_add=False, null=True, blank=True)
qr_step_enabled = models.BooleanField(default=True)
image_resolution = models.IntegerField(default=800)
sponsor = models.ForeignKey(Sponsor, on_delete=models.CASCADE, null=True, related_name='campaigns')
I have the user through a request, and I want to get all campaigns of that user.
I tried doing it with for loops but I want to do it with queries
this is what I had:
user = request.user
participants = user.participant_set.all()
for participant in participants:
participant.team.campaign.name
is there a way to make a query through these models and for all participants?
A user can have many participants, and each participant has a Team, each team has a campaign
The best way is to merge the two modela Team and Campaign in one model.
Something as simple as this should work:
Campaign.objects.filter(team__participant__user=request.user)
The Django ORM is smart enough to follow foreign key relationships in both directions.
Thanks to Daniel W. Steinbrook to guide me to the answer, I had to do this to get the query:
Campaign.objects.filter(teams__participants__user__exact=request.user)

Django: Query to check whether the request.user is group's admin

class Group(models.Model):
group_name = models.CharField(max_length=256)
group_desc = models.CharField(max_length=2000, blank=True)
created_by = models.ForeignKey(User, on_delete=models.PROTECT, blank=True, null=True, related_name='created_groups')
group_pic = models.ImageField(blank=True)
users = models.ManyToManyField(User, through='GroupMember')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class GroupMember(models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
is_group_admin = models.BooleanField(default=False)
I have these two models and I want to query whether the request.user is part of a particular group and is group_admin or not:
I have successfully queried the first part but not able to do the latter part. For the first part, I have written the following query:
GroupMember.objects.filter(id=pk, group__users__in=[request.user])
Any kind of help will be appreciated.
Try:
GroupMember.objects.filter(user=request.user, group=<group_to_check>, is_group_admin=True).exists()
Please try
GroupMember.objects.filter(user=request.user, group__group_name=<group_name_to_be_checked>, is_group_admin=True).exists()

How can I get the ID from one model and pass it to another one? Django

I have a two models like so :
class Entity(models.Model):
contact = models.ForeignKey(User, default=None, on_delete=models.CASCADE)
company_name = models.CharField(max_length=40, blank=False, null=True)
vat_registration = models.CharField(max_length=12, blank=False, null=True)
street_number = models.CharField(max_length=10, blank=False, null=True)
street_name = models.CharField(max_length=100, blank=False, null=True)
post_code = models.CharField(max_length=10, blank=False, null=True)
city = models.CharField(max_length=40, blank=False, null=True)
country = models.CharField(max_length=60, blank=False, null=True)
email = models.EmailField(max_length=240, blank=False, null=True)
class Invoices(models.Model):
invoice_number = models.CharField(max_length=12, blank=False, null=True)
invoice_date = models.DateField()
invoice_code = models.CharField(max_length=10, blank=False, null=True)
client_ref = models.CharField(max_length=10, blank=False, null=True)
supplier = models.ForeignKey(Suppliers, default=None, on_delete=models.CASCADE)
net_amount = models.FloatField()
vat_paid = models.FloatField()
vat_reclaimed = models.FloatField()
invoice_type = models.CharField(max_length=10, blank=False, null=True)
entity_name = models.ForeignKey(Entity, blank=True, null=True, default=None, on_delete=models.CASCADE)
I have a page where I input some data from invoices and I would like to link the invoice which is entered to the company to which it belongs to.
Below is my (not working views.py):
def claim_details(request): #save the invoice onto DB
form = forms.SaveInvoice(request.POST)
if request.method == 'POST':
if form.is_valid():
instance = form.save(commit=False)
inv = Entity.objects.values_list('id', flat=True)
instance.entity_name = inv[0]
print(instance)
instance.save()
return redirect('accounts:claim')
else:
form = forms.SaveInvoice()
args = {'form': form}
return render(request, 'dashboard/claim_details.html', args)
I am trying to include the id from the Entity to the Invoice which is saved.
Any idea ?
I need to add that I see the field entity_name in the admin dashboard but the value is NULL. I would like it to be equal to the entity to which I enter the invoices for.
I am pulling my hair and don't really understand what should be put in the if statement. The inv variable returns a queryset with the id of the Entity but I really don't know how to have it to save when submitting the form ... your help will be very much appreciated.
You are doing right, but not quite right. You already have the field as a foreign key, hence you need not worry about getting id. Just get the whole Entity object you want to link to and pass it in entity_name, Django will automatically assign the id to that field. In case you want to view the id, use object.pk. Pk as in primary key. Hope this helps.
Since entity_name is a foreign key you don't need to bother yourself with assigning record ID directly - as was mentioned, Django will do this for you. Simply use this:
inv = Entity.objects.first()
instance.entity_name = inv
instance.save()
Also, note two things:
as for now, you're fetching any first record from Entity table and basically all invoices will be bound to same Entite. Perhaps you wanted to filter this by user: Entity.objects.filter(contact=request.user).first
entity_name have set on_delete argument to CASCADE. This means that when related Entity is deleted, you'll lose invoce as well. Possibly you want to keep invoices as a historical data no matter if related Entity is deleted.

How get information from three different tables at once?

I have following models:
class Device(models.Model):
name = models.CharField(max_length=100, blank=False)
description = models.TextField(max_length=500, blank=True)
ip_address = models.GenericIPAddressField(blank=True, null=True)
contact_person = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
team = models.ForeignKey(Team, on_delete=models.SET_NULL, null=True)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.name
class TimeSlot(models.Model):
name = models.CharField(max_length=20)
start_slot = models.CharField(max_length=10)
end_slot = models.CharField(max_length=10)
def __str__(self):
return self.name
class Reservation(models.Model):
device = models.ForeignKey(Device, on_delete=models.CASCADE)
time_slot = models.ForeignKey(TimeSlot, on_delete=models.CASCADE)
date_of_reservation = models.DateField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return "{} - {} for device: {} by {}.".format(self.time_slot, self.date_of_reservation, self.device, self.user)
class ForbiddenSlot(models.Model):
device = models.ForeignKey(Device, on_delete=models.CASCADE)
time_slot = models.ForeignKey(TimeSlot, on_delete=models.CASCADE)
def __str__(self):
return str(self.time_slot)
This is simple reservation system. I have problem to understand how create query for three different tables.
I want get all TimeSlots which are not set in ForbiddenSlot and Reservation for given Device name.
I'm not entirely sure if this will work, but I think it will and is definitely worth a shot.
TimeSlot.objects.filter(
forbiddenslot__isnull=True,
reservation__device__name='Device Name',
)
It's not necessarily the easiest thing for me to wrap my head around, but not only does TimeSlot have access to .forbiddenslot_set, it also can filter by forbiddenslot. The same goes for reservation.
I guess changing the structure of your models will be much better, like deleting the model ForbiddenSlot and replacing it with a flag on the reservation model, then you can select all TimeSlots from the reservation model where the forbidden flag is False, like:
reservations = Reservation.objects.only('time_slot').filter(device__name=name_of_the_device,forbidden=False) where forbidden is a boolean field.
Using select_related() will pre-populate the appropriate attributes:
Model.objects.select_related()

How do I get related Model field in Django using the Django Admin

I think that my problem here is Django specific and not necessarily a reflection on
my understanding of relational databases (hopefully).
I have a Django app that stores information on Contacts.
With that one table things seemed to work fine. When I wanted to categorize
the type of relationship - is this a professional relationship, family, friends, etc.
That's when things didn't show up like I wanted. I finally got the migration to work
with the new table.
I'm using python 3 with the latest version of django. I have a mysql
database. I want a one to many relationship, where one contact can
be characterized by many categories. When I work with the django admin
and try to enter a contact, I'm not seeing a field for entering relationship categories.
So, here is my models.py for the contacts app.
from django.db import models
class Resource(models.Model):
first_name = models.CharField(max_length=40)
last_name = models.CharField(max_length=40)
organization = models.CharField(max_length=60, null=True, blank=True)
street_line1 = models.CharField("Street Line 1", max_length=50, null=True, blank=True)
street_line2 = models.CharField("Street Line 2", max_length=50, null=True, blank=True)
city = models.CharField(max_length=40, null=True, blank=True)
state = models.CharField(max_length=40, null=True, blank=True)
zipcode = models.CharField(max_length=20, blank=True, null=True)
phone1 = models.CharField(max_length=20, null=True, blank=True)
phone2 = models.CharField(max_length=20, null=True, blank=True)
email = models.EmailField(max_length=60, null=True, blank=True)
website = models.URLField(max_length=90, null=True, blank=True)
def __str__(self):
return "%s %s \t%s" % (self.first_name, self.last_name, self.organization)
class Meta:
ordering = ('last_name',)
class Relationship(models.Model):
category = models.CharField(max_length=120)
resource = models.ForeignKey(Resource, related_name='category')
def __str__(self):
return self.category
class Meta:
ordering = ('category',)
Thanks in advance for any help,
Bruce