如何在django中进行内部加入?

时间:2018-01-06 15:17:55

标签: python mysql django orm inner-join

我想在html中显示出版物的城市名称,州和国家/地区。但他们在不同的表格中。

这是我的 models.py

class country (models.Model):
    country_name = models.CharField(max_length=200, null=True)
    country_subdomain = models.CharField(max_length=3, null=True)
    def __str__(self):
        return self.country_name

class countrystate (models.Model):
    state_name = models.CharField(max_length=200, null=True)
    country = models.ForeignKey(country, on_delete=models.CASCADE, null=True)
    importance = models.IntegerField(null=True)
    def __str__(self):
        return self.state_name

class city (models.Model):
    city_name = models.CharField(max_length=200, null=True)
    countrystate = models.ForeignKey(countrystate, on_delete=models.CASCADE, null=True)
    def __str__(self):
        return self.city_name

class publication(models.Model):
    user = ForeignKey(users, on_delete=models.CASCADE, null=False)
    title= models.CharField(max_length=300, null=True)
    country=models.ForeignKey(country, on_delete=models.CASCADE, null=True)
    countrystate=models.ForeignKey(countrystate, on_delete=models.CASCADE, null=True)
    city=models.ForeignKey(city, on_delete=models.CASCADE, null=True)

    def __str__(self):
        return self.title

这是我的views.py

def publications(request):
    mypublications = publication.objects.filter(user_id=request.session['account_id'])
    dic.update({"plist": mypublications })
    return render(request, 'blog/mypublications.html', dic)

在django视图中,下一个sql查询的等价物是什么?

SELECT p.user_id, p.title, c.cuntry_id, c.country_name, s.state_id, s.state_name, y.city_id, y.city_name FROM publication AS p
INNER JOIN country AS c ON c.id = p.country_id
INNER JOIN countrystate AS s ON s.id = p.countrystate_id
INNER JOIN city AS y ON y.id = p.city_id

5 个答案:

答案 0 :(得分:14)

你可能正在寻找select_related,这是实现这一目标的自然方式:

switch testB {
case Optional<Any>.none:
    print("value is none")
default:
    print("value is not none")
}

switch testC! {
case Optional<Any>.none:
    print("value is none")
default:
    print("value is not none")
}

您可以通过pubs = publication.objects.select_related('country', 'country_state', 'city') 检查生成的SQL,这应该会产生以下几行(示例来自postgres后端):

str(pubs.query)

然后将返回的游标值转换为相应的ORM模型实例,以便在循环遍历这些发布时,可以通过自己的对象访问相关表的值。但是,沿预先选择的前向关系的这些访问不会导致额外的db命中:

SELECT "publication"."id", "publication"."title", ..., "country"."country_name", ...  
FROM "publication" 
INNER JOIN "country" ON ( "publication"."country_id" = "country"."id" ) 
INNER JOIN "countrystate" ON ( "publication"."countrystate_id" = "countrystate"."id" ) 
INNER JOIN "city" ON ( "publication"."city_id" = "city"."id" ) 

答案 1 :(得分:1)

这应该对您有用:

publication = publication.objects.select_related('yourfield', 'yourfield', 'yourfield')

答案 2 :(得分:0)

让我从描述术语的含义开始并开始订购...

InnerJoin表示两个(或多个)表之间的“公共”部分。就像您的SQL查询所建议的那样,每个接一个地执行。

通过SQL查询,您将发布视为主要对象,所有查询都是发布中的外键,从而提供了整个数据集。

如果我的理解正确,那么您在Django等效项中寻找的是链式过滤器(不是Query),因为Q会分别给您每个Q的结果并将它们连接在一起,而您希望将一个结果应用于另一个。

(我不知道dic.update({“ plist”:mypublications})的作用,尚不清楚。 解: country = country.objects.all()#获取国家表中的所有国家。 country_state = countrystate.objects.all()#获取所有countrystate对象 city = city.objects.all()#获取所有城市物体

解决方案1:在python3中,您需要使用__in,在Python2中可以正常工作。并将使您的国家/地区拥有表国家/地区(不是None),表countrystate(不是None),表city(不是None),城市(如果没有)的任何内容。 注意:'None'(python)='Null'(SQL数据库) 从上面获取所有具有任何内容的出版物(实际上将为您带来任何好处。 publications_list = publication.objects.filter(country = country, countrystate = country_state, city = city)#获取“ id”(基于对象)中的任何一个是否匹配,从而使其本身成为内部联接。

答案 3 :(得分:0)

from django.db import models

class Course(models.Model):
    name=models.CharField(max_length=10)
    courseid=models.CharField(max_length=30,primary_key=True)
class Enrollment(models.Model):
    course=models.ForeignKey(Course,on_delete=models.CASCADE)
    enrollid=models.CharField(max_length=20)

#Queryset:
k=Enrollment.objects.filter(course__courseid=1).values('id','course__courseid','course__name','enrollid')

print(k.query)
SELECT "app1_enrollment"."id", "app1_enrollment"."course_id", "app1_course"."name", "app1_enrollment"."enrollid" FROM "app1_enrollment" INNER JOIN "app1_course" ON ("app1_enrollment"."course_id" = "app1_course"."courseid") WHERE "app1_enrollment"."course_id" = 1

答案 4 :(得分:-1)

在这种简单情况下,您不需要INNER JOIN或select_related,因为您可以直接在模板中遍历到citycountrystatecountry –根据我刚刚在项目中的经验。

由于您的QuerySet是通过上下文dic['plist']设置的,因此,在模板中,您可以:

{% for itero in plist %}

{{ itero.title }}
{{ itero.city.city_name }}
{{ itero.citystate.citystate_name }}
{{ itero.country.country_name }}

{% endfor %}