Django Joins Query - django

I have a Ride and Vehicle table where
class Ride(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User)
vehicle = models.ForeignKey(Vehicle, blank=True, null=True, unique=False)
state = models.CharField(max_length=255, blank=True, null=True)
I want to return a list of vehicles, where their LAST ride.state is NOT equal to COMPLETED
Is there a way to do this via the ORM?

from django.db.models import Max, F
Vehicle.objects.annotate(last_ride_id=Max("ride__id")).filter(ride_id=F("last_ride_id").exclude(ride__state="COMPLETE").distinct()
not tested but should work

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 ORM join statements

I'm learning django queryset API and it's so overwhelming. I'm used to sql statement and I just want a basic join statement where 2 tables join together
How can i get this result in shell?
SELECT e.emp_lastname,e.emp_firstname,o.job_description
FROM hs_hr_employee e
INNER JOIN ohrm_job_title o ON e.job_title_code = o.id
WHERE e.work_station='101';
hs_hr_employee
from django.db import models
class HsHrEmployee(models.Model):
emp_number = models.AutoField(primary_key=True)
employee_id = models.CharField(max_length=50, blank=True, null=True)
emp_lastname = models.CharField(max_length=100)
emp_firstname = models.CharField(max_length=100)
job_title_code = models.ForeignKey('OhrmJobTitle', models.DO_NOTHING,
db_column='job_title_code', blank=True, null=True)
work_station = models.ForeignKey('OhrmSubunit', models.DO_NOTHING,
db_column='work_station', blank=True, null=True)
hs_hr_job_title
class OhrmJobTitle(models.Model):
job_title = models.CharField(max_length=100)
job_description = models.CharField(max_length=400, blank=True,
null=True)
i added the models
You can filter with:
qs = HsHrEmployee.objects.filter(
work_station_id=101
).select_related('job_title_code')
For the HsHrEmployee model objects that arise from this queryset, you can then determine the job_title for example with:
for item in qs:
print(item.job_title_code.job_title)

Django: handle multi stock (related table) in Product Based List View

I need to manage Products shared by multiple Warehouses.
I tried to get through with annotate, prefetch_related, select_related but in my case, those solutions are upside-down for my need. I need first to get product and then, the related stock in each warehouse and display it in template and the foreignKey is in my Sststock, not in Product
I have :
Product models.py
class Product(models.Model):
famille = models.ForeignKey(Famille, on_delete=SET_NULL, null=True)
sku = models.CharField(max_length=100, unique=True)
nom = models.CharField(max_length=250)
fournisseur = models.ForeignKey(
Supplier, on_delete=models.SET_NULL, default=12, null=True)
qty = models.IntegerField()
mini = models.IntegerField()
maxi = models.IntegerField()
[...]
Warehouse models.py
class Warehouse(models.Model):
nom = models.CharField(max_length=100)
code = models.CharField(max_length=10, null=True)
adresse = models.CharField(max_length=255)
cp = models.IntegerField()
ville = models.CharField(max_length=50)
tel = models.CharField(max_length=10)
email = models.EmailField(default='sav#iturbo.fr', null=False, blank=False)
allow_store = models.BooleanField(default=False)
def __str__(self):
return self.nom.upper()
Sststock models.py
class SstStock(models.Model):
sst = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
mageid = models.ForeignKey(Product, on_delete=models.CASCADE, null=True)
qty = models.IntegerField()
last_update = models.DateTimeField(default=timezone.now)
For the time, I only have 3 warehouses but there could have more in the future.
First I had "hard-coded" my 3 warehouses in Product's model but this solution was not easily scalable.
What would be the best way to achieve my goal ?
I've seen solution with Mysql Stored Procedures in PhpMyAdmin for creating innerJoin tables but there is maybe possibilities within Django.

How to join Objects in Django with Foreign Keys 2 tables deep

I have 2 models each with foreign keys to 2 tables. I'm trying to join the 1st table to the 3rd.
Here are my models:
Model 1:
class AppBillingBil(models.Model):
id_bil = models.AutoField(primary_key=True)
idtrp_bil = models.ForeignKey(AppTradingPartnerTrp, models.DO_NOTHING, db_column='idtrp_bil', blank=True,
null=True)
idcst_bil = models.ForeignKey(AppCustomerCst, models.DO_NOTHING, db_column='idcst_bil')
idbtp_bil = models.ForeignKey(AppBillingTypeBtp, models.DO_NOTHING, db_column='idbtp_bil')
class Meta:
db_table = 'app_billing_bil'
ordering = ['id_bil']
Model 2:
class AppCustomerCst(models.Model):
id_cst = models.AutoField(primary_key=True)
is_active_cst = models.BooleanField()
name_cst = models.CharField(max_length=50, blank=True, null=True)
Model 2:
class AppTradingPartnerTrp(models.Model):
id_trp = models.AutoField(primary_key=True)
tpid_trp = models.CharField('TPID', max_length=50, blank=True, null=True)
name_trp = models.CharField('Name', max_length=50)
Final Model Needed:
class AppCustomerTpRel(models.Model):
id_rel = models.AutoField(primary_key=True)
idcst_rel = models.ForeignKey(AppCustomerCst, models.DO_NOTHING, db_column='idcst_rel')
idtrp_rel = models.ForeignKey(AppTradingPartnerTrp, models.DO_NOTHING, db_column='idtrp_rel')
cust_vendor_rel = models.CharField(max_length=50, blank=True, null=True)
I need to join on the following criteria:
idtrp_bil__id_trp = idtrp_rel
idcst_bil__id_cst = idcst_rel
And I need to be able to use the cust_vendor_rel field from AppCustomerTpRel in a filter query on AppBillingBil
After reading the docs here: https://docs.djangoproject.com/en/3.0/topics/db/queries/#spanning-multi-valued-relationships I tried this, and was successful:
idcst_bil__appcustomertprel__cust_vendor_rel
I realized I needed to include the target model name in the value grab.

Django QuerySet, Filtering Data Based on The Latest Entry of Each Data's Column/Field equals to a particular Value

#models.py
class Orders(models.Model):
orderid = models.IntegerField(db_column='orderID', primary_key=True)
createdate = models.DateField(db_column='createDate', blank=True, null=True)
pickupdate = models.DateField(db_column='pickupDate', blank=True, null=True)
returndate = models.DateField(db_column='returnDate', blank=True, null=True)
pickupstore = models.ForeignKey(Branch, models.DO_NOTHING, db_column='pickupStore', blank=True, null=True,related_name = 'pickupstore')
returnstore = models.ForeignKey(Branch, models.DO_NOTHING, db_column='returnStore', blank=True, null=True,related_name = 'returnstore')
rentedvehicle = models.ForeignKey('Vehicles', models.DO_NOTHING, db_column='rentedVehicle', blank=True, null=True)
customer = models.ForeignKey(Customer, models.DO_NOTHING, db_column='customer', blank=True, null=True)
class Vehicles(models.Model):
vehicleid = models.IntegerField(db_column='vehicleID', primary_key=True)
make = models.CharField(max_length=45, blank=True, null=True)
model = models.CharField(max_length=45, blank=True, null=True)
series = models.CharField(max_length=45, blank=True, null=True)
Orders model have foreign key rentedvehicle which refers to Vehicles models
I have filtered the data based on the pickupstore state, e.g. The list of vehicles that are picked up from store in a particular state
Vehicles.objects.filter(orders__pickupstore__state = request.POST['state'])
I want to be able to filter the filtered data above so that I can get a list of vehicles that are picked up from store in a particular state WITH its latest entry in Orders models has returnstore__state == a particular state
So basically, I want to achieve this:
Vehicles.objects.filter(orders__pickupstore__state = request.POST['state']).filter(the latest entry returnstore state =request.POST['state'])
Many possible solutions. Optimal depends on your Django version (1.11 or higher?). Here's one possible solution:
from django.db.models import Max, F
Vehicles.objects.filter(orders__pickupstore__state = request.POST['state']).annotate(max_date=Max('orders__returndate')).filter(orders__return_date=F('max_date')).filter(orders__state = request.POST['state'])
What's happening here is that we're identifying the most recent return date, then filtering the orders to only include the most recent, then filtering the Vehicles on the state of that latest order.