Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django ORM join without foreign keys and without raw queries

Tags:

join

orm

django

A

class AKeywords(models.Model):
    id = models.AutoField(primary_key=True, db_column="kw_id")
    word = models.CharField(max_length=200)
    ...

    class Meta:
        managed = False
        db_table = '"A"."Keywords"'

B

class BKeywords(models.Model):
    id = models.AutoField(primary_key=True, db_column="kw_id")
    word = models.CharField(max_length=200)
    ...
    class Meta:
        managed = False
        db_table = '"B"."Keywords"'

I have another model where i would like to perform my join.

class XKeywords(models.Model):
    ...
    k_id = models.IntegerField(blank=True, null=True)
    ...

    class Meta:
        managed = False
        db_table = '"public"."XKeywords"'

I have two models that are very similar, one comes from a database schema and another from another database schema. A third model that will be to join with table A or B has i want.

How can i join model A or B without using foreignkeys and raw queries?

like image 927
ePascoal Avatar asked Sep 02 '16 11:09

ePascoal


2 Answers

The current way to do this is with a Subquery and an OuterRef:

Example taken from my code. Store and StoreInformation have a field called store_number.

from django.db.models import Subquery, OuterRef

Store.objects.annotate(timezone=Subquery(
      StoreInformation.objects.filter(store_number=OuterRef('store_number')).values('store_timezone')[:1]
))

This is joining to add a field called store_timezone.

like image 81
kagronick Avatar answered Oct 15 '22 11:10

kagronick


This will work:

XKeywords.objects.filter(pk_id=my_id).extra(select={'word':'SELECT word FROM "A"."Keywords" WHERE "public"."XKeywords".k_id = "A"."Keywords".kw_id'})

or

raw_sql = """SELECT * FROM (SELECT * FROM "public"."XKeywords" WHERE pk_id = my_id) as "XK" LEFT OUTER JOIN  "A"."Keywords" as "AK" ON "AK".kw_id = "XK".k_id ;"""
XKeywords.objects.raw(raw_sql)

This is an workaround i was expecting something more "clever". It would be nice to have something more directly like:

XKeywords.objects.filter(pk_id=my_id).join(k_id=A.kwd,from={"AKeywords":"A"})
like image 37
ePascoal Avatar answered Oct 15 '22 10:10

ePascoal