我曾经考虑过使用一个额外的和/或注释来执行查询,但是没有得到我想要的结果。在
我想得到一个产品列表,其中有活动的许可证和可用许可证的总数。活动许可证被定义为在日期内未过时,且许可证数减去分配的许可证数(由manytomy字段上的计数定义)。在
我定义的模型是:
class Vendor(models.Model):
name = models.CharField(max_length=200)
url = models.URLField(blank=True)
class Product(models.Model):
name = models.CharField(max_length=200)
vendor = models.ForeignKey(Vendor)
product_url = models.URLField(blank=True)
is_obsolete = models.BooleanField(default=False, help_text="Is this product obsolete?")
class License(models.Model):
product = models.ForeignKey(Product)
num_licenses = models.IntegerField(default=1, help_text="The number of assignable licenses.")
licensee_name = models.CharField(max_length=200, blank=True)
license_key = models.TextField(blank=True)
license_startdate = models.DateField(default=date.today())
license_enddate = models.DateField(null=True, blank=True)
is_obsolete = models.BooleanField(default=False, help_text="Is this licenses obsolete?")
licensees = models.ManyToManyField(User, blank=True)
我试过按许可证模式过滤。这是可行的,但我不知道如何将返回的数据整理/分组/聚合到返回的单个查询集中。在
当尝试按product进行筛选时,我可以很好地找出需要执行的查询。我可以得到零碎的信息,并尝试使用.extra()
select=
查询返回可用许可证的数量(这正是我目前真正需要的),其中有多个许可证将与一个产品关联。在
因此,我想要的最终答案是,我如何检索一个可用产品列表以及Django中可用许可证的数量。我宁愿尽量不要用生的。在
示例queryset获取了我想要的所有许可证详细信息,但我无法获取产品:
^{pr2}$提前谢谢你。在
编辑(2014-02-11): 我想我已经用一种丑陋的方式解决了它。如果可以的话,我不想进行太多的DB调用,所以我使用一个许可证查询获取所有信息,然后用Python对其进行过滤并从manager类中返回所有信息。可能是过度使用了Dict和list。不管怎么说,它是有效的,我可以在以后用附加信息扩展它,而不需要很大的风险或定制SQL。它还使用了我在model类中定义的一些models参数。在
类许可证管理器(模特。经理)公司名称:
def get_available_products(self):
licenses = self.get_queryset().annotate(
used_licenses=Count('licensees')
).extra(
select={
'avail_licenses': 'licenses_license.num_licenses - (SELECT count(*) FROM licenses_license_licensees WHERE licenses_license_licensees.license_id = licenses_license.id)'
}
).filter(
is_obsolete=False,
num_licenses__gt=F('used_licenses')
).exclude(
license_enddate__lte=date.today()
).prefetch_related('product')
products = {}
for lic in licenses:
if lic.product not in products:
products[lic.product] = lic.product
products[lic.product].avail_licenses = lic.avail_licenses
else:
products[lic.product].avail_licenses += lic.avail_licenses
avail_products = []
for prod in products.values():
if prod.avail_licenses > 0:
avail_products.append(prod)
return avail_products
编辑(2014-02-12): 好吧,这是我决定采用的最终解决方案。使用Python过滤结果。减少缓存调用,并具有固定数量的SQL查询。在
这里的教训是,对于具有许多过滤级别的东西,最好根据需要获取,并在返回时使用Python进行过滤。在
class ProductManager(models.Manager):
def get_all_available(self, curruser):
"""
Gets all available Products that are available to the current user
"""
q = self.get_queryset().select_related().prefetch_related('license', 'license__licensees').filter(
is_obsolete=False,
license__is_obsolete=False
).exclude(
license__enddate__lte=date.today()
).distinct()
# return a curated list. Need further information first
products = []
for x in q:
x.avail_licenses = 0
x.user_assigned = False
# checks licenses. Does this on the model level as it's cached so as to save SQL queries
for y in x.license.all():
if not y.is_active:
break
x.avail_licenses += y.available_licenses
if curruser in y.licensees.all():
x.user_assigned = True
products.append(x)
return q
一种策略是从许可证查询集中获取所有产品标识:
然后使用该ID列表查询产品:
^{pr2}$相关问题 更多 >
编程相关推荐