我有
class Supplier(Model) :
pass
class Customer(Model) :
pass
class Dock(Model) :
pass
class SupplierDockAccess(Model) :
supplier = ForeignKey(Supplier)
dock = ForeignKey(Dock)
class SupplierCustomerAccess(Model):
supplier = ForeignKey(Supplier)
customer = ForeignKey(Customer)
我有一个Customer实例,我想获得客户可以访问的所有Docks。客户可以通过SupplierCustomerAccess访问供应商,供应商可以通过SupplierDockAccess访问Docks。我可以这样做:
# get the suppliers the customer has access to
supplier_customer_accesses = SupplierCustomerAccess.objects.filter(customer=customer)
suppliers = [s.supplier for s in supplier_customer_accesses]
# get the docks those suppliers have access to
supplier_dock_accesses = SupplierDockAccess.objects.filter(supplier__in=suppliers)
docks = [s.dock for s in supplier_dock_accesses]
...但是生成的码头列表包含重复项,我真的认为它应该可以一次完成。有人觉得要展示一些强大的django-fu?
答案 0 :(得分:2)
好吧,我明白了。谈论它的其中一个似乎就是诀窍:
docks = Dock.objects.filter(supplierdockaccess__supplier__suppliercustomeraccess__customer=customer).distinct()
...并且看着sql,它确实在一个大的连接中做到了。尼斯。很抱歉回答我自己的问题。
答案 1 :(得分:2)
我能想到的最简单的方法是ManyToManyField
s和custom QuerySet/Manager的组合。
from django.db import models
class CustomQuerySetManager(models.Manager):
"""
Class for making QuerySet methods available on result set
or through the objects manager.
"""
def get_query_set(self):
return self.model.QuerySet(self.model)
def __getattr__(self, attr, *args):
try:
return getattr(self.__class__, attr, *args)
except AttributeError:
return getattr(self.get_query_set(), attr, *args)
class Customer(models.Model):
suppliers = models.ManyToManyField(through=SupplierCustomerAccess)
objects = CustomQuerySetManager()
class QuerySet(QuerySet):
def docks(self):
return Dock.objects.filter(
supplierdockaccess__supplier__in=self.suppliers
).distinct()
...
class Supplier(models.Model):
docks = models.ManyToManyField(through=SupplierDockAccess)
...
您应该只看到一两次点击数据库(取决于您是否在获得客户时使用select_related
),并且您的代码非常干净:
docks = customer.docks()
suppliers = customer.suppliers.all()
...