我有3个模型Product, Photo, and ProductLikeDilike
。我正在所有3个模型上执行左外部联接。首先,我将Product
与Photo
连接在一起,然后将结果表(temp
)与ProductLikeDilike
连接在一起。下面是原始sql。
注意:olx
是Django应用的名称。
data = Product.objects.raw('select * from (select
olx_product.id,olx_product.name,olx_photo.file,olx_photo.cover_photo_flag
from olx_product left outer join olx_photo on
(olx_product.id=olx_photo.reference_id_id) where
olx_photo.cover_photo_flag="yes" or olx_photo.cover_photo_flag is null) as
temp left outer join olx_productlikedislike on
(temp.id=olx_productlikedislike.product_id_id and
olx_productlikedislike.product_liked_by_id_id=2)')
for x in data:
print(x.name)
我想了解的是,当我使用上述3种模型中的任何一种来运行原始sql时,为什么得到相同的结果,即
当我这样做
data = Product.objects.raw('select *.....')
for x in data:
print(x.name)
或
data = Photo.objects.raw('select *......')
for x in data:
print(x.name)
或
data = ProductLikeDislike.raw('select *.....')
for x in data:
print(x.name)
我得到相同的结果。为什么? 请帮助我理解这一点。
下面是models.py文件
from django.db import models
from django.urls import reverse
from django.dispatch import receiver
from django.contrib.auth.models import User
class Product(models.Model):
category = models.ForeignKey(Category ,on_delete=models.CASCADE)
name = models.CharField(max_length = 200, db_index = True)
slug = models.SlugField(max_length = 200, db_index = True)
description = models.TextField(blank = True)
price = models.DecimalField(max_digits = 10, decimal_places = 2 )#Not used FloatField to avoid rounding issues
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
contact= models.BigIntegerField(default=None,blank=True, null=True)
created_by = models.CharField(max_length = 200, default=None,blank=True, null=True)
uploaded_by_id = models.IntegerField(default=0)
status = models.IntegerField(default=0) # 0-->Active,1-->Inactive
mark_as_sold = models.IntegerField(default=0) # 0-->not sold,1-->sold
def get_absolute_url(self):
return reverse('olx:edit_product', kwargs={'pk': self.pk})
class Meta:
ordering = ('-created',)
index_together = (('id','slug'),)# we want to query product by id and slug using together index to improve performance
def __str__(self):
return self.name
class Photo(models.Model):
reference_id = models.ForeignKey(Product, null=True,on_delete=models.CASCADE)
photo_type = models.CharField(max_length = 70, db_index = True)
file = models.FileField(upload_to='photos/',default='NoImage.jpg')
cover_photo_flag = models.CharField(default=0,max_length = 5, db_index = True)
uploaded_at = models.DateTimeField(auto_now_add=True)
uploaded_by_id = models.IntegerField(default=0)
status = models.IntegerField(default=0) # 0-->Active,1-->Inactive
class Meta:
ordering = ('-uploaded_at',)
class ProductLikeDislike(models.Model):
product_id = models.ForeignKey(Product,models.SET_DEFAULT,default=0)
product_liked_by_id = models.ForeignKey(User,models.SET_DEFAULT,default=0)
status = models.BooleanField(default=False)
如果可能的话,还请教我如何用纯Django方式编写它?
答案 0 :(得分:0)
类似这样的东西:
user_i_care_about = User.objects.get(username='user2')
productlikedislike_set = models.Prefetch('productlikedislike_set',
ProductLikeDislike.objects.select_related('user') \
.filter(user=user_i_care_about).order_by('id'))
photo_set = models.Prefetch('photo_set', Photo.objects.order_by('id'))
products = Product.objects.prefetch_related(photo_set, productlikedislike_set) \
.filter(models.Q(photo__cover_photo_flag=True) | models.Q(photo__isnull=True)) \
.filter(productlikedislike__user=user_i_care_about, productlikedislike__like=True)
然后您可以使用:
for product in products:
for pic in product.photo_set.all():
print(x.name)
如果您的模型看起来像这样:
class Product(models.Model):
name = models.CharField(max_length=50)
class Photo(models.Model):
cover_photo_flag = models.BooleanField()
name = models.CharField(max_length=50)
product = models.ForeignKey(Product, db_column='reference_id', on_delete=models.CASCADE)
class ProductLikeDislike(models.Model):
product = models.ForeignKey(Product, db_column='product_id', on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
like = models.BooleanField()
完整的WITH测试示例可以在此处查看:https://gist.github.com/kingbuzzman/05ed095d8f48c3904e217e56235af54a
答案 1 :(得分:0)
我得到相同的结果。为什么?请帮助我理解这一点。
因为.raw(..)
[Django-doc]仅接受原始查询并执行它。执行原始操作的模型无关紧要。
我们可以生成如下查询:
from django.db.models import Q
Product.objects.filter(
Q(photo__photo_flag__isnull=True) | Q(photo__photo_flag='yes'),
Q(likedislike__product_liked_by_id_id=2)
)
因此,在这里,我们接受所有Product
的相关Photo
对象具有flag
的{{1}}(如果JOIN不产生任何标记),或者NULL
是photo_flag
)。此外,应该有一个'yes'
为Likedislike
的{{1}}对象。
请注意,通常ForeignKey
[Django-doc]的后缀为 no liked_by_id_id
或前缀2
。为此设置一个_id
也有点“奇怪”,特别是因为大多数数据库仅将严格个正值分配为主键,并且固有地偏爱{{ 1}}仍然在另一个对象上。