首页 > 解决方案 > 当我在 Django 中使用 INNER JOIN 时,原始查询结果成倍增加

问题描述

我不明白为什么我的原始查询将结果乘以用户数量。我正在使用 INNER JOIN 并且我绑定了两个对象,所以我真的无法得到它。(我在 Django 查询语言方面没有经验,所以我使用的是原始查询)。

视图.py

def index(request):
    projekt = Projekt.objects.raw('SELECT  projekt_id, stressz_projekt.projekt, last_name, first_name, stressz_profile.id, stressz_profile.user_id, auth_user.id FROM stressz_profile INNER JOIN stressz_projekt ON stressz_projekt.id = stressz_profile.projekt_id INNER JOIN auth_user ON auth_user.id = stressz_profile.user_id')

    template = loader.get_template('stressz/index.html')

    context = {
        'projekt': projekt,
    }
    return HttpResponse(template.render(context, request))

如果我使用 Django ORM,我会得到相同的结果

profile = Profile.objects.get(user=request.user)
projekt = Profile.objects.filter(projekt=profile.projekt)

模型.py

class Viselkedestipus(models.Model):

    def __str__(self):
        return str(self.user_name)

        user_name = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
        date = models.DateField(auto_now_add=True, auto_now=False, blank=True)


class Profile(models.Model):

    def __str__(self):
        return str(self.user)

    user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
    date = models.DateField(auto_now_add=True, auto_now=False, blank=True)
    projekt = models.ForeignKey(Projekt, on_delete=models.CASCADE, default=1)


class Projekt(models.Model):

    def __str__(self):
        return str(self.projekt)

    projekt = models.TextField(max_length=150)
    company_name = models.ForeignKey('Company', on_delete=models.CASCADE, default=1)
    date = models.DateField(auto_now_add=True, auto_now=False, blank=True)

标签: pythonsqldjango

解决方案


这是一个简单的示例,说明如何使用可以适应您的情况的 ORM:

假设我们有两个模型,一个Country和一个City类似的:

class Country(models.Model):

    """ country model """

    name = models.CharField(...)


class City(models.Model):

    """ city model with a foreign key to a country """

    country = models.ForeignKey('Country', ..., related_name='cities')
    name = models.CharField(...)
    population = models.PositiveIntegerField(...)

我们可以按如下方式使用 Django ORM:

# filter for a country with a given name:
country = Country.objects.filter(name='Italy')
country.name # Italy

# filter for a city with a given name:
city = City.objects.filter(name='Rome')
city.name # Rome

# get the country the city belongs to:
country = city.country
country.name # Italy

# get the queryset of all cities with a population greater than 1 million in a specific country:
country = Country.objects.filter(name='Italy')
large_cities = country.cities.filter(population__gt=1000000)
for city in large_cities:
    print(city.name)   
# loop will print: Rome, Milan

此外,看起来您只是将一个Projeckt实例传递给您的模板。所以你真的不需要 ORM,相反你可以做类似的事情:

我还将简要补充一下,您似乎已经颠倒了 profile-projekt 关系——因为它代表一个 profile 只能有一个 projekt,但一个 projekt 可以有多个 profile——不确定这是否是有意的。

视图.py

def index(request):

    # get projekt by id:
    projekt = Projekt.objects.get(id=<the-id>)

    template = loader.get_template('stressz/index.html')

    context = {
        'projekt': projekt,
    }
    return HttpResponse(template.render(context, request))

然后在您的模板中: stressz/index.html

<!-- use context data in template -->
<div> Name: {{projekt.projekt}} </div>

<!-- loop over all profiles in the project -->
{% for profile in projekt.profile_set %}
  <div> User First Name: {{ profile.user.first_name }} </div>
  <div> User Last Name: {{ profile.user.last_name}} </div>
{% endfor %}

推荐阅读