django left outer join with condition - python

how to put condition in left outer join query in django.I have given sample query in below.
I need equivalent django query for below sql query.
Table 1
class LeadGroups(Audit):
user = models.ForeignKey(User)
group_name = models.CharField(max_length=250)
Table 2
class lead(Audit):
group = models.ForeignKey(LeadGroups, null='true', blank='true')
First_Name = models.CharField(max_length=255, null='true', blank='true')
Last_Name = models.CharField(max_length=255, null='true', blank='true')
Required query
SELECT "lead_leadgroups"."id", "lead_leadgroups"."created_by_id", "lead_leadgroups"."modified_by_id", "lead_leadgroups"."created_at", "lead_leadgroups"."modified_at", "lead_leadgroups"."customer_id", "lead_leadgroups"."user_id", "lead_leadgroups"."group_name", COUNT("lead_lead"."id") AS "totlacontact" FROM "lead_leadgroups"
LEFT OUTER JOIN "lead_lead" ON ( "lead_leadgroups"."id" = "lead_lead"."group_id" and **"lead_lead"."data_value" = True**)
WHERE ("lead_leadgroups"."customer_id" = 309 ) GROUP BY "lead_leadgroups"."id", "lead_leadgroups"."created_by_id", "lead_leadgroups"."modified_by_id", "lead_leadgroups"."created_at", "lead_leadgroups"."modified_at", "lead_leadgroups"."customer_id", "lead_leadgroups"."user_id", "lead_leadgroups"."group_name"
ORDER BY "lead_leadgroups"."id" ASC LIMIT 100

Related

How to inner join 4 tables in Django?

We want to retrieve all table records at a time how to implement like SQL queries in django orm.
Example SQL query:
select *
from Company_info
inner join Bank_info on Bank_info.manufacturer = Company_info.manufacturer
inner join Company_info on Company_info.manufacturer = Company_info.manufacturer
inner join Transport_info on Transport_info.manufacturer = Company_info.manufacturer
Code:
class Manufacturer(models.Model):
name = models.CharField(max_length=42)
class Bank_info(models.Model):
account = models.CharField(max_length=42)
manufacturer = models.ForeignKey(Manufacturer, on_delete= models.CASCADE)
class Company_info(models.Model):
name= models.CharField(max_length=42)
manufacturer = models.ForeignKey(Manufacturer, on_delete= models.CASCADE)
class Transport_info(models.Model):
name= models.CharField(max_length=42)
manufacturer = models.ForeignKey(Manufacturer, on_delete= models.CASCADE)
You can use prefetch_related for this, as mentioned in comments:
Manufacturer.objects.all().prefetch_related('related_name2', 'related_name3', 'related_name4')
This, in fact, will not perform an SQL INNER JOIN, but will join prefetched objects on Python level - this will decrease hits to DB when using related object fields.

django 1.11.x -> 2.x migration. I got the incorrect 'group by' fields

I just upgraded the Django version. The model or code has not been modified in my app.
But... I get different results QuerySet.
Fields specified in 'Group by' are different when printing a 'query'.
Model:
class Content(models.Model):
id_field = models.AutoField(db_column='id_', primary_key=True)
...
collections = models.ManyToManyField('Collection',
through='CollectionMap',
through_fields=('contentid', 'collectionid'))
class CollectionMap(models.Model):
field_index = models.AutoField(db_column='_index', primary_key=True)
collectionid = models.ForeignKey(Collection, on_delete=models.CASCADE, db_column='collectionid')
contentid = models.ForeignKey(Content, on_delete=models.CASCADE, db_column='contentid')
field_time = models.DateTimeField(db_column='_time')
class Collection(models.Model):
field_index = models.AutoField(db_column='_index', primary_key=True)
name = models.CharField(unique=True, max_length=50)
collectionorder = models.IntegerField(db_column='collectionOrder', blank=True, null=True)
active = models.IntegerField(blank=True, null=True)
field_time = models.DateTimeField(db_column='_time')
Code:
Content.objects\
.annotate(count=Count('id_field')\
.values('id_field', 'collections__name')
Query:
1.11.X
SELECT
Content.id_, Collection. name
FROM Content
LEFT OUTER JOIN Collection_Map ON (Content.id_ = Collection_Map.contentid)
LEFT OUTER JOIN Collection ON (Collection_Map.collectionid = Collection._index)
GROUP BY Content.id_
ORDER BY Content.itemOrder DESC
LIMIT 50;
2.X
SELECT
Content.id_, Collection. name
FROM Content
LEFT OUTER JOIN Collection_Map ON (Content.id_ = Collection_Map.contentid)
LEFT OUTER JOIN Collection ON (Collection_Map.collectionid = Collection._index)
GROUP BY Content.id_, Collection. name
ORDER BY Content.itemOrder DESC
LIMIT 50;
Group By fields:
Version 1.11.X : GROUP BY Content.id
Version 2.X : GROUP BY Content.id, Collection.Name
I want this... '... GROUP BY Content.id ...'
What should I do??

Django left join models

I want to left join the below tables and add a filter condition on approved_coupon field.
My models
class Voucher(models.Model):
voucher_id = models.UUIDField(default=uuid.uuid4, editable=False)
voucher_code = models.CharField()
class ApprovedCouponLine(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
approved_coupon = models.ForeignKey(ApprovedCoupon, on_delete=models.CASCADE, related_name='approved_coupon_lines')
coupon_code = models.ForeignKey(Voucher, on_delete=models.CASCADE, related_name='approved_coupon_lines_coupons')
I tried this, but it shows the inner join.
queryset = Voucher.objects.filter(approved_coupon_lines_coupons__approved_coupon_id='CD5FC4FE').values_list('code', flat=True)
Current Query:
SELECT "voucher_voucher"."code", "voucher_approvedcouponline"."id"
FROM "voucher_voucher"
INNER JOIN "voucher_approvedcouponline" ON ("voucher_voucher"."id" = "voucher_approvedcouponline"."coupon_code_id")
WHERE "voucher_approvedcouponline"."approved_coupon_id" = 'CD5FC4FE'
Expected Query:
SELECT "voucher_voucher"."code", "voucher_approvedcouponline"."id"
FROM "voucher_voucher"
LEFT JOIN "voucher_approvedcouponline" ON ("voucher_voucher"."id" = "voucher_approvedcouponline"."coupon_code_id" AND
"voucher_approvedcouponline"."approved_coupon_id" = 'CD5FC4FE'
)
What I missed in the above example?

How to convert SQL query to Django query

Django model
class Imones(models.Model): # Clients
id = models.AutoField(primary_key=True)
pavadinimas = models.CharField(unique=True, max_length=45) # name
class Priekabos(models.Model): # Products
id = models.AutoField(primary_key=True)
sutarties_nr = models.CharField(unique=True, max_length=45) # contract_number
vin = models.CharField(unique=True, max_length=45, verbose_name='VIN') # vehicle_identification_number
imones = models.ForeignKey(Imones, models.DO_NOTHING, verbose_name='Įmonė') # client_id
class Saskaitos(models.Model): # Invoices
id = models.AutoField(primary_key=True)
apmoketa = models.BooleanField(default=0) # Paid in full
imones = models.ForeignKey(Imones, models.DO_NOTHING) # client_id
MySQL query:
SELECT distinct sutarties_nr, vin, apmoketa
FROM priekabos pr
LEFT OUTER JOIN saskaitos sa
ON pr.imones_id = sa.imones_id
WHERE apmoketa=0 or apmoketa is null
Could someone explain how to translate MySQL query to Django query? I've tried:
obj = Saskaitos.objects.filter(apmoketa=0)
queryset = Priekabos.objects.filter(imones__in=obj.values('imones')).values()
But it doesn't return all values as expected. One more question - how to make Imones.pavadinimas appear in queryset results instead of plain id? Now it looks like that

Erroneous group_by query generated in python django

I am using Django==1.8.7 and I have the following models
# a model in users.py
class User(models.Model):
id = models.AutoField(primary_key=True)
username = models.CharField(max_length=100, blank=True)
displayname = models.CharField(max_length=100, blank=True)
# other fields deleted
# a model in healthrepo.py
class Report(models.Model):
id = models.AutoField(primary_key=True)
uploaded_by = models.ForeignKey(User, related_name='uploads',
db_index=True)
owner = models.ForeignKey(User, related_name='reports', db_index=True)
# other fields like dateofreport, deleted
I use the following Django queryset:
Report.objects.filter(owner__id=1).values('uploaded_by__username',
'uploaded_by__displayname').annotate(
total=Count('uploaded_by__username')
)
I see that this generates the following query:
SELECT T3."username", T3."displayname", COUNT(T3."username") AS "total" FROM "healthrepo_report"
INNER JOIN "users_user" T3 ON ( "healthrepo_report"."uploaded_by_id" = T3."id" )
WHERE "healthrepo_report”.”owner_id" = 1
GROUP BY T3."username", T3."displayname", "healthrepo_report"."dateofreport", "healthrepo_report”.”owner_id", "healthrepo_report"."uploaded_by_id"
ORDER BY "healthrepo_report"."dateofreport" DESC, "healthrepo_report"."user_id" ASC, "healthrepo_report"."uploaded_by_id" ASC
However, what I really wanted was just grouping based on "healthrepo_report”.”owner_id" and not multiple fields. i.e. What I wanted was:
SELECT T3."username", T3."displayname", COUNT(T3."username") AS "total" FROM "healthrepo_report"
INNER JOIN "users_user" T3 ON ( "healthrepo_report"."uploaded_by_id" = T3."id" )
WHERE "healthrepo_report”.”owner_id" = 1
GROUP BY T3."username", T3."displayname" ORDER BY "healthrepo_report"."dateofreport" DESC, "healthrepo_report"."user_id" ASC, "healthrepo_report"."uploaded_by_id" ASC
I am wondering why this is happening and how do I get grouping based on single column.
I just saw this post:
Django annotate and values(): extra field in 'group by' causes unexpected results
Changing the query by adding empty order_by() fixes it
Report.objects.filter(owner__id=1).values('uploaded_by__username',
'uploaded_by__displayname').annotate(
total=Count('uploaded_by__username')
).order_by()

Categories

Resources