使用过滤器查询相关表中最近条目的项目

时间:2011-03-29 13:18:44

标签: python html django models

您好我查询时遇到问题。我有一个项目清单。任何项目都可以设置状态(In,out,Collected,Destroyed等)。这是我的看法。

def client_summary(request, client_id):
    client = None
    items = None
try:
    client = models.Client.objects.get(pk = client_id)
    items = client.storageitem_set.all()
    total_items = items.count()
    except:
        return HttpResponse(reverse(return_clients))
    return render_to_response('client_summary.html', {'items':items, 'total_items':total_items, 'client':client}, context_instance = RequestContext(request))

如果我的模板中有

{%for item in items%}
        {{item.itemstatushistory_set.latest}}
{%endfor%}

这将显示所有最新状态。现在我只想打印出状态仅被销毁的所有项目。出于某种原因,我似乎无法做到这一点。

以下是我的模型中的更多信息。

class StorageItem(models.Model):
    type = models.ForeignKey(StorageObject)
    client = models.ForeignKey(Client)
    company_id = models.PositiveIntegerField(unique = True, blank = True, null = True)
    content = models.TextField(blank = True)
    alternative_id = models.CharField(verbose_name = 'Client no.', max_length = 60, blank = True)
    title = models.CharField(max_length = 100)
    format = models.ForeignKey(Format, blank = True, null = True)
    location = models.CharField(max_length = 20, blank = True)
    item_class = models.TextField(blank = True)

    def __unicode__(self):
        return self.title

class Status(models.Model):
    description = models.CharField(max_length = 60)
    notes = models.TextField(blank = True)
    def __unicode__(self):
        return self.description

    class Meta:
        verbose_name_plural = 'Status'
        get_latest_by = 'date'
        ordering = ['date']

class ItemStatusHistory(models.Model):
    date = models.DateTimeField(auto_now = True)
    contact = models.ForeignKey(Contact)
    item = models.ForeignKey(StorageItem)
    status = models.ForeignKey(Status)
    user = models.ForeignKey(User)

    def __unicode__(self):
        return str(self.status

编辑:由于项目之间的关系可能有很多状态,因此仍存在一些问题。但我想只列出最新状态,仅列出已销毁的物品。

示例:假设有3个项目,它们包含item1 = [in, out, destroyed]item2 = [destroyed, in]item3 = [destroyedcollected, destroyed]item4 = [in],其中[1st status, 2nd status, 3rd status, etc]。我只想显示该项目的最新状态。

Mike和kriegar都会得到像[item1, item2, item3, item3]这样的结果。 因为Yuji使用了不同的功能,他将获得[item1, item2, item3]

我需要得到的答案应该是[item1, item3]

2 个答案:

答案 0 :(得分:0)

如果您想要一个属于客户端并被销毁的项目的查询集:

clients_destroyed_items = StorageItem.objects.filter(client=client, 
    itemstatushistory__status__description='destroyed')
  

跨越关系的查找¶

     

Django提供强大而直观的功能   “跟随”关系的方式   查找,处理SQL JOIN   为你自动,在后面   场景。只是为了跨越关系   使用相关字段的字段名称   跨模型,双重分隔   强调,直到你到达   你想要的领域。

     

此示例检索所有Entry   具有名称为的博客的对象   '披头士博客':

     
    
      
        

Entry.objects.filter(blog_ 名称 _exact ='甲壳虫         博客')

      
    
  
     

这种跨越可以和你一样深   等。

     

它也可以倒退。参考一个   “反向”关系,只需使用   模型的小写名称。

答案 1 :(得分:0)

kriegar的解决方案将起作用。还有一个,按状态id搜索而不是description上的文字匹配:

destroyedStatus = Status.objects.get(description="destroyed")
clients_destroyed_items = StorageItem.objects.filter(client=client, 
    itemstatushistory__status=destroyedStatus)

这假设描述是唯一的,但您的模型中没有这样的约束。我不知道哪种实现更快。

编辑:顺便说一下,如果你有一个疯狂的系统,你有多个状态,描述为“已毁坏”,并且你想按状态查询{{1}而不是id,你只会这样做:

description

顺便说一句,在您的destroyedStatusIDs = Status.objects.filter(description="destroyed").values_list("id", flat=True) clients_destroyed_items = StorageItem.objects.filter(client=client, itemstatushistory__status__in=destroyedStatusIDs) related_nameForeignKey关系中设置OneToOneField被认为是一种很好的做法,通常是复数形式。所以你的历史课就变成了:

ManyToManyField

这会将我的第一个例子改为:

class ItemStatusHistory(models.Model):
    date = models.DateTimeField(auto_now=True)
    contact = models.ForeignKey(Contact, related_name="history")
    item = models.ForeignKey(StorageItem, related_name="history")
    status = models.ForeignKey(Status, related_name="history")
    user = models.ForeignKey(User, related_name="history")

编辑2:啊,所以你只想考虑当前(即最新的)状态。这是aggregationF objects进来的地方。基本上,我们的想法是让数据库在表格中创建一个“假列”,其中包含最新的destroyedStatus = Status.objects.get(description="destroyed") clients_destroyed_items = StorageItem.objects.filter(client=client, history__status=destroyedStatus) (即最大{ {1}})状态,然后要求日期匹配以及状态:

date

我没有测试过这个,这是我第一次尝试这个,而且可能有更好的方法,所以欢迎评论。