Django multiple table join on using ORM - django

I am trying to join multiple table using django ORM .i have tried several different way but no luck.
from django.db import models
from compositefk.fields import CompositeForeignKey, CompositeOneToOneField
class Company(models.Model):
code = models.DecimalField(db_column='Code', max_digits=38, decimal_places=0)
srccode = models.SmallIntegerField(db_column='SrcCode')
est = models.DateTimeField(db_column='Est')
rownum = models.BigIntegerField(db_column='RowNum')
class Meta:
manage = False
unique_together = (('code', 'srccode'),)
db_table = 'Company'
class Floor(models.Model):
code = models.DecimalField(db_column='Code', max_digits=38, decimal_places=0)
srccode = models.SmallIntegerField(db_column='SrcCode')
depcode = models.DecimalField(db_column='DepCode', max_digits=38, decimal_places=0)
depsrccode = models.SmallIntegerField(db_column='Depsrccode')
floorname = models.CharField(db_column='FloorName')
rownum = models.BigIntegerField(db_column='RowNum')
company = CompositeForeignKey(Company,on_delete=models.CASCADE,to_fields={'code':'code','srccode': 'srccode'})
department= CompositeOneToOneField(Department,on_delete=models.CASCADE,to_fields={'depcode':'depcode','depsrccode': 'depsrccode'})
class Meta:
manage = False
unique_together = (('depcode', 'depsrccode','floorname'),)
db_table = 'floor'
class SubCompany(models.Model):
code = models.DecimalField(db_column='Code', max_digits=38, decimal_places=0)
srccode = models.SmallIntegerField(db_column='SrcCode')
subname = models.CharField(db_column='SubName')
rownum = models.BigIntegerField(db_column='RowNum')
location = models.CharField(db_column='Location')
department = models.CharField(db_column='Department')
company = CompositeForeignKey(Company,on_delete=models.CASCADE,to_fields={'code':'code','srccode': 'srccode'})
class Meta:
manage = False
unique_together = (('code', 'srccode','subname','rownum'),)
db_table = 'SubCompany'
basically i am trying to get data as per below row sql
SELECT Location, Department, Subname, t.* from [Floor] t join [SubCompany] s on t.code = s.code and t.srccode = s.srccode;"
what is the equilant Django Orm of above SQL query.?
is there any alternative solution apart from raw sql in django.?
Thanks

Related

Field 'id' expected a number but got 'ANPKUR0724' while Importing Data in Django

I have two models, related through a Foreign Key, when im uploading the Model having Foreign key , the id value which is auto created is taking value of the Field which is the foreign key. What could be the possible reason?.
class Station(models.Model):
BS_ID = models.TextField(max_length=20,unique=True)
BS_Name = models.CharField(max_length=20)
City = models.CharField(max_length=20,null=True)
State = models.CharField(max_length=20,null=True)
City_Tier = models.CharField(max_length=10,null=True)
Lat = models.DecimalField(max_digits=10,decimal_places=5,null=True,blank=True)
Long = models.DecimalField(max_digits=10,decimal_places=5,null=True,blank=True)
class CustomerLVPN(models.Model):
Customer_Name = models.CharField(max_length=200)
Order_Type = models.CharField(max_length=200,null=True)
Feasibility_ID = models.IntegerField(null=True)
Circuit_ID = models.CharField(max_length=250,null=True,blank=True)
Req_BW = models.DecimalField(max_digits=6,decimal_places=3,null=True,blank=True)
City = models.CharField(max_length=200,null=True)
State = models.CharField(max_length=200,null=True)
Region =models.CharField(max_length=200,null=True)
L2_Lat = models.DecimalField(max_digits=6,decimal_places=3,null=True,blank=True)
L2_Long = models.DecimalField(max_digits=6,decimal_places=3,null=True,blank=True)
BS_ID = models.ForeignKey(Station,to_field='BS_ID',related_name='ConfirmedCustomer',on_delete=models.SET_NULL,null=True)
So when im Uploading data for CustomerLVPN model im getting the following error -
"BS_ID
Field 'id' expected a number but got 'ANPKUR0724'."
Below is the Resource Code:
class StationResource(resources.ModelResource):
class Meta:
model=Station
exclude = ['id']
use_bulk=True
batch_size = 500
class StationAdmin(ImportExportModelAdmin):
resource_class=StationResource
class LVPNResource(resources.ModelResource):
class Meta:
model = CustomerLVPN
use_bulk = True
batch_size = 500
class LVPNAdmin(ImportExportModelAdmin):
resource_class = LVPNResource
For your LVPNResource you need to associated a ForeignKeyWidget with your bs_id field:
bs_id = fields.Field(
column_name='BS_ID',
attribute='BS_ID',
widget=ForeignKeyWidget(Station, 'BS_ID'))

Django add aggregate operation to a query result

I'm trying to do an aggregate operation between two tables using Django, my models are:
class Cusinetype(models.Model):
hometype_en = models.TextField()
active = models.BooleanField()
hometype_es = models.TextField(blank=True, null=True)
class Meta:
managed = False
db_table = 'cusinetype'
class Foodpreferences(models.Model):
id_client = models.ForeignKey(Client, models.DO_NOTHING, db_column='id_client')
id_cusinetype = models.ForeignKey(Cusinetype, models.DO_NOTHING, db_column='id_cusinetype')
created_at = models.DateTimeField()
class Meta:
managed = False
db_table = 'foodpreferences'
The query that I'm trying to build is:
SELECT
ct.id,
ct.hometype_en,
ct.hometype_es
,
((SELECT COUNT(*)
FROM foodpreferences fp
WHERE fp.id_cusinetype = ct.id AND fp.id_client = 3 ) > 0 ) selected
FROM
Cusinetype ct
I'm trying to generate a model, to store the information of those tables in a single one query, but anything works.
Someone has an idea about how to do it?
serializers.py
class PreferencesSerializer(serializers.ModelSerializer):
selected = serializers.IntegerField()
class Meta:
model = Cusinetype
fields = ('id', 'trucktype_en', 'trucktype_es', 'selected')
views.py
qs = Cusinetype.objects.filter().filter(active = True)
qs = qs.annotate(
selected=Sum(Case(
When(foodpreferences__id_client=3, then=1),
output_field=IntegerField()
))
)
serializers = PreferencesSerializer(qs, many = True)
return Response({ "result": serializers.data })

Fetch data from multiple tables in django views

In Django views, I want to fetch all details(Workeraccount.location,Workeravail.date, Workerprofile.*) for any particular wid=1.
SQL Query:
select * from Workeraccount,Workeravail,Workerprofile where Workerprofile.wid=1 and Workerprofile.wid=Workeravail.wid and Workeraccount.wid=Workerprofile.wid;
The corresponding models are as follows:
class Workeraccount(models.Model):
wid = models.ForeignKey('Workerprofile', db_column='wid', unique=True)
location = models.ForeignKey(Location, db_column='location')
class Meta:
managed = False
db_table = 'workerAccount'
class Workeravail(models.Model):
wid = models.ForeignKey('Workerprofile', db_column='wid')
date = models.DateField()
class Meta:
managed = False
db_table = 'workerAvail'
class Workerprofile(models.Model):
wid = models.SmallIntegerField(primary_key=True)
fname = models.CharField(max_length=30)
mname = models.CharField(max_length=30, blank=True, null=True)
lname = models.CharField(max_length=30)
gender = models.CharField(max_length=1)
age = models.IntegerField()
class Meta:
managed = False
db_table = 'workerProfile'`
You can do this:
workprofile = Workerprofile.objects.filter(id=1).first()
all_worker_avails = workprofile.workeravail_set.all()
all_workeraccounts = workprofile.workeraccount_set.all()
As Workeraccount and Workeravail are related through Workerprofile, you can get one queryset easily - you will need two separate ones.
You can also do the following:
all_worker_avails = Workeravail.objects.filter(wid=workprofile)
...
Here is how you can do it with only one database call:
workprofile = Workerprofile.objects.get(pk=1)
.select_related('workeravail_set', 'workerprofile_set')
This will fetch all the data for you at once, which can then be used with:
workprofile.workerprofile_set.location #Gets the Workeraccount.location
workprofile.workeravail_set.date #Gets the Workeravail.date
workprofile.fname #Example of Workerprofile.*
As an aside, if you want a shorter way to reference the foreign objects than the "*_set" method, you can set a related_name like
class Workeraccount(models.Model):
wid = models.ForeignKey('Workerprofile', db_column='wid', unique=True, related_name='waccount')
...
And then replace workeraccount_set with waccount

Relation in Django REST Framework?

I am using serializers.GeoFeatureModelSerializer to serialize Model. I have a queryset
that is creating Left Outer Join. I want to serialize related Model fields
Here is my Model
class LookupTiming(models.Model):
day = models.CharField(max_length=7)
time_1 = models.TimeField()
time_2 = models.TimeField()
class Meta:
db_table = u'lookup_timing'
class Streets(models.Model):
name = models.CharField(max_length=50)
geometry = models.GeometryField(null=True, blank=True)
objects = models.GeoManager()
class Meta:
db_table = u'streets'
def __unicode__(self):
return '%s' % self.name
class StreetTimings(models.Model):
street= models.ForeignKey(Streets)
lookuptiming = models.ForeignKey(LookupTiming)
class Meta:
db_table = u'street_timings'
queryset =
Streets.objects.filter(streettimings_lookuptiming_isnull=True)
Serializer Class
class StreetSerializer(gis_serializer.GeoFeatureModelSerializer):
class Meta:
model = Streets
geo_field = "geometry"
id_field = False
fields = ('id', 'streettimings__lookuptiming__day', other fields)
Updated
I want to show following fields on response
Streets (id)
LookupTiming (day)
I want output like this query simple is that
SELECT "streets"."id", "lookuptiming"."day" FROM "streets"
LEFT OUTER JOIN "streettimings" ON ( "streets"."id" = "streettimings"."street_id" )
LEFT OUTER JOIN "lookuptiming" ON ( "streettimings"."lookuptiming_id" = "lookuptiming"."id" )
How can i do this?
Thank you

add condition to join in django orm

How to get data equivalent to sql query using django orm:
SELECT *
FROM "financeDocuments_documenttemplateline"
LEFT JOIN "financeDocuments_documentinstanceline" ON "financeDocuments_documentinstanceline".template_line_id = "financeDocuments_documenttemplateline".id AND "financeDocuments_documentinstanceline".document_instance_id = 1
WHERE "financeDocuments_documenttemplateline".document_type_id = 1
I use:
document_lines = DocumentTemplateLine.objects.filter(document_type__id = document_instance.document_type.id).select_related('documentinstanceline').values('documentinstanceline__value')
But it generates:
SELECT "financeDocuments_documentinstanceline"."value" FROM "financeDocuments_documenttemplateline" LEFT OUTER JOIN "financeDocuments_documentinstanceline" ON ("financeDocuments_documenttemplateline"."id" = "financeDocuments_documentinstanceline"."template_line_id") WHERE "financeDocuments_documenttemplateline"."document_type_id" = 1
Models are like this one:
class DocumentInstance(models.Model):
company = models.ForeignKey(Company)
period = models.ForeignKey(Period, verbose_name=u'период')
document_type = models.ForeignKey(DocumentType, verbose_name=u'вид документа' )
created = models.DateTimeField('created', auto_now_add=True)
author = models.ForeignKey(User)
class Meta:
unique_together= (('company', 'period', 'document_type'),)
class DocumentInstanceLine(models.Model):
document_instance = models.ForeignKey(DocumentInstance, related_name='lines')
template_line = models.ForeignKey(DocumentTemplateLine)
value = models.FloatField(default=0.00)
comment = models.TextField(blank=True)
class Meta:
unique_together= (('document_instance', 'template_line'),)
How to change code for django orm to add second condition like in my first sql query?