how to let django achieve inner join - python

there are two tables:
class TBLUserProfile(models.Model):
userid = models.IntegerField(primary_key=True)
relmusicuid = models.IntegerField()
fansnum = models.IntegerField()
class TSinger(models.Model):
fsinger_id = models.IntegerField()
ftbl_user_profile = models.ForeignKey(TBLUserProfile, db_column='Fsinger_id')
I want to get Tsinger info and then order by TBLUserProfile.fansnum, I know how to write sql query: select * from t_singer INNER JOIN tbl_user_profile ON (tbl_user_profile.relmusicuid=t_singer.Fsinger_id) order by tbl_user_profile.fansnum, but I don't want to use model raw function. relmusicuid is not primary key otherwise I can use ForeignKey to let it work. How can I use django model to achieve this?

You can do like this :
Tsinger.objects.all().order_by('ftbl_user_profile__fansnum')
For information about Django JOIN :
https://docs.djangoproject.com/en/1.8/topics/db/examples/many_to_one/

Related

Django ORM multiple tables query

I trying to make some queries in Django ORM (migration from SQL). My models looks like this
class Iv2(models.Model):
s_id = models.AutoField(primary_key=True)
l_eid = models.CharField(max_length=265)
t_id = models.CharField(max_length=265,unique=True)
class Sv2(models.Model):
id = models.AutoField(primary_key=True)
s_id = models.OneToOneField(Iv2, on_delete=models.PROTECT)
gdd = models.DateTimeField(default=datetime.now)
class Ev2(models.Model):
id = models.OneToOneField(Iv2, to_field='l_eid', on_delete=models.PROTECT)
s_id = models.ForeignKey(Iv2, on_delete=models.PROTECT)
car = models.CharField(max_length=265)
I want to write a query, given t_id(some real search value). I want to get the corresponding Sv2.gdd and Ev2.car
I'm thinking to get s_id and l_eid with the t_id. And when I get s_id. I can query Sv2 and with l_eid I can query Ev2.
Is it possible to achieve everything with one ORM query ? can prefetch/select_related work here?
"Given t_id of Iv2 get Sv2.gdd and Ev2.car"
First get the Sv2 instance by filtering its 1:1 relation by the
real search value t_id:
sv2 = Sv2.objects.filter(s_id__t_id=t_id).first()
sv2.gdd
Now you have 2 options to get Ev2.car
Add related name in Ev2 (more on related_name here )
Assuming your related_name is ev2 you can do:
sv2.ev2.car
Use the default django related_name modelname__set
sv2.ev2_set

How to use temp table count values into into the where query in Django Raw Sql?

I need to use raw sql in my django project. I'm using count command and then I associated it with as command like "the_count" but i got an error. The error like this, the_count does not exist.
And my my code here,
# First Model
class AModel(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_lenth=100)
# Second Model
class BModel(models.Model):
a_model = models.ForeignKey(AModel, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
query = 'SELECT "app_AModel"."id",
(SELECT COUNT(*) FROM "app_BModel" INNER JOIN ON ("app_BModel"."user_id" = "app_AModel"."user_id") WHERE ("app_BModel"."a_model_id" = "app_AModel"."id")) AS "the_count"
FROM "app_AModel"
WHERE ("the_count" = 0)'
BModel.objects.raw(query)
Thank you for yours helps...
From postgreSQL documentation
An output column's name can be used to refer to the column's value in
ORDER BY and GROUP BY clauses, but not in the WHERE or HAVING clauses;
there you must write out the expression instead.
Also you probably want to use GROUP BY and HAVING on my_app table instead so something in a line of following:
SELECT a_model_id, COUNT(*) from app_BModel GROUP BY a_model_id HAVING count(*) > 0

how to make left join in django?

this is my first model
class DipPegawai(models.Model):
PegID = models.AutoField(primary_key=True)
PegNamaLengkap = models.CharField(max_length=100, blank=True, null=True)
PegUnitKerja = models.IntegerField(null=True,blank=True)
and this is my second model
class DipHonorKegiatanPeg(models.Model):
KegID = models.AutoField(primary_key=True)
PegID = models.ForeignKey(DipPegawai, blank=True,null=True)
KegNama = models.Charfield(max_length=100,null=True,blank=True)
i want to make left join with this model, something like this in mysql query
SELECT PegNamaLengkap, KegNama_id
FROM karyawan_dippegawai AS k LEFT JOIN honorkegiatanpeg_diphonorkegiatanpeg AS h ON k.PegID = h.PegID_id
WHERE PegUnitKerja = 3
GROUP BY k.PegID
how to make left join with django orm same like mysql query above?
Should be something like:
DipPegawai.objects.filter(PegUnitKerja=3).values_list.('pegnamalengkap', 'diphonorkegiatanpeg_kegnama')
Tell me if that worked for you.
You can print your raw query using print(your_var_here.query). Remember put your query into a var
DipHonorKegiatanPeg.objects.filter(PegID__PegUnitKerja=3).values('PegID__PegNamaLengkap', 'KegNama_id')

Django ORM join subtable in query

I want use Django ORM. I build SQL query:
select itinerary.id, count(users.home_location_id) from itinerary_itinerary as itinerary left join (select to_applicationuser_id as id, users.home_location_id from custom_auth_applicationuser_friends as friends join custom_auth_applicationuser as users on friends.to_applicationuser_id = users.id where from_applicationuser_id = 28)
as users on itinerary.location_id = users.home_location_id
WHERE user_id = 28
GROUP BY itinerary.id, users.home_location_id
Could anybody tell me how make left join with table from subquery?
28 is current user_id.
I use something like:
Itinerary.object.filter(user_id=28).extra(
tables=['(select to_applicationuser_id as id, users.home_location_id from custom_auth_applicationuser_friends as friends join custom_auth_applicationuser as users on friends.to_applicationuser_id = users.id where from_applicationuser_id = 28) as users'],
where=['itinerary.location_id = users.home_location_id']
)
But I got error
ProgrammingError relation "(select to_applicationuser_id as id,
users.home_location_id fro" does not exist
UPD
Models (it is just simple scheme):
class ApplicationUser(models.Model):
name = models.CharField(max_length=255)
home_location = models.ForeignKey(Location)
friends = models.ManyToManyFieled('self')
class Location(models.Model):
loc_name = models.CharFiled(max_length=255)
class Itinerary(models.Model):
user = models.ForeignKey(ApplicationUser)
location = models.ForeignKey(Location)
When you add tables with extra, they get added to the from list, which does not accept an sql statement.
I don't think you need to use extra at all here, you can get a similar query with the ORM without the need to join on a select statement. The following code, using filtering and annotations, will give the same results as much as I was able to understand your query:
ApplicationUser.objects.filter(
Q(itinerary__location_id = F('friends__home_location_id')) |
Q(friends__home_location__isnull=True),
id=28,
).values_list(
'itinerary__id', 'friends__home_location_id'
).annotate(location_count = Count('friends__home_location_id')
).values_list('itinerary__id', 'location_count')

How can I do INNER JOIN in Django in legacy database?

Sorry for probably simple question but I'm a newby in Django and really confused.
I have an ugly legacy tables that I can not change.
It has 2 tables:
class Salespersons(models.Model):
id = models.IntegerField(unique=True, primary_key=True)
xsin = models.IntegerField()
name = models.CharField(max_length=200)
surname = models.CharField(max_length=200)
class Store(models.Model):
id = models.IntegerField(unique=True, primary_key=True)
xsin = models.IntegerField()
brand = models.CharField(max_length=200)
So I suppose I can not add Foreign keys in class definitions because they change the tables.
I need to execute such sql request:
SELECT * FROM Salespersons, Store INNER JOIN Store ON (Salespersons.xsin = Store.xsin);
How can I achieve it using Django ORM?
Or I'm allowed to get Salespersons and Store separately i.e.
stores = Store.objects.filter(xsin = 1000)
salespersons = Salespersons.objects.filter(xsin = 1000)
Given your example query, are your tables actually named Salespersons/Store?
Anyway, something like this should work:
results = Salespersons.objects.extra(tables=["Store"],
where=["""Salespersons.xsin = Store.xsin"""])
However, given the names of the tables/models it doesn't seem to me that an inner join would be logically correct. Unless you always have just 1 salesperson per store with same xsin.
If you can make one of the xsin fields unique, you can use a ForeignKey with to_field to generate the inner join like this:
class Salespersons(models.Model):
xsin = models.IntegerField(unique=True)
class Store(models.Model):
xsin = models.ForeignKey(Salespersons, db_column='xsin', to_field='xsin')
>>> Store.objects.selected_related('xsin')
I don't see why you can't use the models.ForeignKey fields even if the database lacks the constraints -- if you don't explicitly execute the SQL to change the database then the tables won't change. If you use a ForeignKey then you can use Salespersons.objects.select_related('xsin') to request that the related objects are fetched at the same time.

Categories