English 中文(简体)
Django:Nested Queries from Non-Nested Models
原标题:Django: Nested Queries from Non-Nested Models
  • 时间:2009-09-03 14:32:54
  •  标签:

我试图从一套非封不动的模式中找到一条nes子的最佳途径。 鉴于此等原因:

class Beverage(models.Model):
   country = models.ForeignKey(Country,null=True,blank=True)    
   region = models.ForeignKey(Region,null=True,blank=True)
   subregion = models.ForeignKey(SubRegion,null=True,blank=True) 
   in_stock = models.BooleanField()
   ...

由此产生的菜单如下:

France
    Region 1
        Subregion 1
        Subregion 2
    Region 2
        Subregion 3
        Subregion 4
Spain
    ....

没有国家、区域或次区域在菜单上出现,而没有钱。 由于一个次区域始终属于一个区域,一个区域始终属于一个国家,因此,我最初的做法是将模型本身确定为一体,而只是将分红放在一边。 届时,该次区域将永远知道这些饮料。 不幸的是,世界上有太多真正的例外,使得这一点变得可行——与某个区域而不是一个次区域的 wine等等。 因此,我按上述方式统一了布局。

现在的问题是,如何从这一模式的布局中得出菜单。 它像一个深层次 que的问候清单一样,将是一个前进的道路,但这似乎在计算上是昂贵的,而且很复杂。 是否有更清洁的方法?

最佳回答

在进行了大量争辩之后,我认为我已经找到了一种工作解决办法,即通过建立一套nes令和清单,使用很少的LOC。 我想向模板发送真正的物体,而不仅仅是说明(极力试图尽可能接近一般查询方法)。 产生字典的形式是:

{
    Country1:{
        region1:[subregion1,subregion2],
        region2:[subregion3,subregion4]
        },
    Country2: {
        region3:[subregion5,subregion6],
        region4:[subregion7,subregion8]    
    },
}

每一个国家、区域和次区域都是一个真正的目标,而不是扼杀。 这里是业务目标(正处在一个模板中)。 请注意,我们检查每件储存中的现有存货,只有确定一个字典或清单项目。

regionmenu = {}
for c in Country.objects.all() :
    if Wine.objects.filter(country=c,inventory__gt=0).count() > 0 :
        regionmenu[c] = {}

    for r in c.region_set.all(): 
        if Wine.objects.filter(country=c,region=r,inventory__gt=0).count() > 0 :
            regionmenu[c][r] = []           

        for s in r.subregion_set.all():
            if Wine.objects.filter(country=c,region=r,subregion=s,inventory__gt=0).count() > 0 :
                regionmenu[c][r].append(s)

糖尿病完全适合需要,除非你丧失了进行分类的能力,因此,我不得不在以后为字母化做一些说明。

3. 通过模板中的字句进行检索:

<ul>
{% for country, regions in regionmenu.items  %}
    <li>{{ country }} 
        <ul>
        {% for region, subregions in regions.items %}
        <li>{{ region }}
            <ul>
            {% for subregion in subregions %}
                <li>{{ subregion }}</li>
            {% endfor %}
            </ul>
        </li>
        {% endfor %}
        </ul>
    </li>
{% endfor %}
</ul>   

自我们通过物体而不是扼杀装置以来,我现在可以进行URL的逆转,在每个层次上每个项目都得到解冻等(例如删除)。

问题回答

我过去曾用来解决类似问题的一个进程是,选择所有物品,根据当时的次区域国家发出单项命令。 然后,你通过问答结果,并维持你为国家和区域所看到的最后一点的变量。 如果下一个国家/区域在饮料上为最后一笔补贴,那么你就可以从旧清单中删除,并开始一个新的清单。 这里有一些真实的粗略/mes字典来解释这一想法:

beverages = Beverage.objects.order_by( country ,  region ,  subregion )
last_country = -1
menu = []
country_obj = None
for beverage in beverages:
    if beverage.country_id != last_country:
        if country_obj is not None:
            if region_obj is not None:
                if subregion_obj is not None:
                    region_obj[ children ].append(subregion_obj)
                country_obj[ children ].append(region_obj)
            menu.append(country_obj)
        country_obj = { name : beverage.country.name,  children : []}
        last_country = beverage.country_id
        last_region = -1
        region_obj = None
        last_subregion = -1
        subregion_obj = None
    if beverage.region is None:
        country_obj[ children ].append(beverage)    
    else:
        if beverage.region_id != last_region:
            if region_obj is not None:
                if subregion_obj is not None:
                    region_obj[ children ].append(subregion_obj)
                country_obj[ children ].append(region_obj)
            region_obj = { name : beverage.region.name,  children : []}
            last_region = beverage.region_id
            last_subregion = -1
            subregion_obj = None
        if beverage.subregion is None:
            region_obj[ children ].append(beverage)
        else:
            if beverage.subregion_id != last_subregion:
                if subregion_obj is not None:
                    region_obj[ children ].append(subregion_obj)
                subregion_obj = { name : beverage.subregion.name,  children : []}
                last_subregion = beverage.subregion_id
            subregion_obj[ children ].append(beverage)
if beverage.subregion is not None:
    region_obj[ children ].append(subregion_obj)
if beverage.region is not None:
    country_obj[ children ].append(region_obj)
menu.append(country_obj)

如你可能知道的那样,每个级别都有相同的逻辑:如果id改,如果它吞.了旧的x_obj,开始新的.。 最后五条线是处理最后的饮料,因为你在目前开销期间始终不停以前的项目(最后一个项目没有下一个开具)。 这确实是edge的,但是它把我手头的工作推向只需要一问。

我在经过编辑后发现,我最后去做。 这似乎是为了我简单的测试案例。

两种观点

  • To make your first approach work, you could hold GenericForeignKeys to either Country, Region, or SubRegion. Or what ever can be identifying the origin. Use limit_choices_to with Q objects to control, what types can be added.

法典:

content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
origin = generic.GenericForeignKey( content_type ,  object_id , 
                                   limit_choices_to = 
                              Q(name= contry , app_label= what ever is the name of the app )| 
                              Q(name= region , app_label= what ever is the name of the app )| 
                              Q(name= subregion , app_label= what ever is the name of the app ) )))

当然,这些想法可以结合起来。





相关问题
热门标签