【问题标题】:Django Left join howDjango Left 加入如何
【发布时间】:2021-03-01 20:28:24
【问题描述】:

我对 Django 相当陌生,坚持在 Django 中创建左连接。我尝试了很多,但似乎都没有工作:

我要翻译成 Django 的查询是:

select ssc.id
      ,mgz.Title
      ,tli.id
      ,tli.Time
  
from Subscription ssc

join Person prs
  on ssc.PersonID = prs.id
 and prs.id = 3

join Magazine mgz
  on mgz.id = ssc.MagazineID
 and mgz.from <= date.today()
 and mgz.until > date.today()

left join TimeLogedIn tli
  on tli.SubscriptionID = ssc.id
 and tli.DateOnline = date.today()

我使用的模型如下所示:

class Magazine(models.Model):
      Title = models.CharField(max_length=100L)    
      from = models.Datefield()
      until = models.Datefield()
      Persons = models.ManyToManyField(Person, through='Subscription')

class Person(models.Model): 
      user = models.OneToOneField(User, on_delete=models.CASCADE)
      Magazines = models.ManyToManyField(Magazine, through='Subscription')

class Subscription(models.Model):
      MagazineID = models.ForeignKey(Magazine,on_delete=models.CASCADE)
      PersonID = models.ForeignKey(Person,on_delete=models.CASCADE)

class TimeLogedIn(models.Model):
      SubscriptionID = models.ForeignKey('Subscription', on_delete=models.CASCADE)
      DateOnline = models.DateField()
      Time = models.DecimalField(max_digits=5, decimal_places=2)

就像我说的,尝试了很多但没有成功,现在我不知道如何在 Django ORM 中做到这一点,这甚至可能吗?我已经创建了一个原始查询,这工作正常,但是如何在 Django ORM 中创建它?

【问题讨论】:

标签: python django django-orm


【解决方案1】:

您可以使用lookupsltegt 字段来过滤您的对象,然后使用values() 方法。

你也可以反方向查询,使用Q objects获取空值:

from django.db.models import Q

Subscription.objects.filter(
    PersonID_id=3,
    MagazineID__from__lte=date.today(), 
    MagazineID__until__gt=date.today()
 ).filter(
    Q(TimeLogedIn__DateOnline=date.today()) | Q(TimeLogedIn__DateOnline__isnull=True)
 ).values("id", "MagazineID__Title", "TimeLogedIn__id", "TimeLogedIn__Time")

或来自TimeLogedIn

TimeLogedIn.objects.filter(DateOnline=date.today()).filter(
    SubscriptionID__MagazineID__from__lte=date.today(), 
    SubscriptionID__MagazineID__util__gt=date.today()
).values(
    "SubscriptionID_id", "SubscriptionID__MagazineID__Title", "id", "Time"
)

Querysets 也有query 属性包含要执行的sql 查询,你可以看到它如下:

print(TimeLogedIn.objects.filter(...).values(...).query)

注意:在幕后,Django 将 "_id" 附加到字段名称以创建其数据库列名称。因此应该是 subscription,而不是SubscriptionID

您还可以使用prefetch_related()select_related() 来防止多个数据库命中:

SubscriptionID.objects.filter(...).prefetch_related("TimeLogedIn_set")
SubscriptionID.objects.filter(...).select_related("PersonID")

【讨论】:

  • 感谢您的回复!!我想知道,这是在创建左连接吗?我希望杂志的所有订阅今天都处于活动状态,如果今天有 TimeLogedIn 对象,TimeLogedIn.Time,否则我想要一个空值
  • @MacMax,我已经更新了我的答案。我添加了另一种方法。
猜你喜欢
  • 1970-01-01
  • 2011-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多