2012-03-23 74 views
3

我有一個查詢集包含一些對象。根據一些案例或其他的我現在要排除不特定標籤的所有對象(_tags是TagField對我的模型名稱):如何搜索沒有特定標籤的對象?

self.queryset=self.queryset.exclude(_tags__id__in=avoid) 

但這只是給我留下了一個錯誤:

Caught FieldError while rendering: 
Join on field '_tags' not permitted. 
Did you misspell 'id' for the lookup type? 

因爲我很確定我沒有拼錯'身份證',我做了一些搜索如何使用標籤這樣的事情。在文檔中有很多關於自定義管理器,但不知何故,我不能得到它,我如何使用它們來獲得我想要的。

編輯:

校正上面

self.queryset=self.queryset.exclude(_tags__in=avoid) 

其中忌是整數列表的代碼。這讓我擔心django-tagging的TagField只是一個特殊的CharField(或TextField?)。當然,如果我只是針對整數列表查詢它,那麼它將不會理清任何東西。我可以嘗試這樣的方式來解決這個問題:

for tag in avoid: 
    self.queryset=self.queryset.exclude(_tags__contains=tag.name) 

這不僅難看,而且也給我留下的由多個單詞或其他標記的配套件標籤的問題。

我不知何故懷疑這可以通過了解django標記如何工作​​的人以更漂亮的方式解決。

回答

0

正如Chris在回答的評論中所述,當訪問model._tag時,django-tagging不會傳遞tagstring。最後,我沒有其他的解決方案,而不是做查詢,並整理出含有一定標籤之後的循環:

itemlist = list(queryset) 
avoid = some_list_of_tag_ids    
# search for loops that have NONE of the avoid tags 
for item in itemlist: 
    # has tags and [ if a tag.id in avoid this list has an element] 
    if (item.tags) and [tag for tag in item.tags if tag.id in avoid]: 
     # remove the item from the list 
     itemlist.remove(item) 

要完成,爲了這個模型看起來是這樣的:

class Item(models.Model): 

    _tags = TagField(blank=True,null=True) 

    def _get_tags(self): 
     return Tag.objects.get_for_object(self) 
    def _set_tags(self, tags): 
     Tag.objects.update_tags(tags) 

    tags = property(_get_tags, _set_tags) 

Allthough我嘗試了很長一段時間,我發現沒有辦法將查詢鏈接到查詢鏈中。對於這個項目我堅持標記,但這是一個真正的缺點...

3

您的模型是如何定義的? _tags是一個ForeignKey字段嗎?

如果不去取下__id部分

self.queryset=self.queryset.exclude(_tags__in=avoid) 
+0

此外,您不能直接在模板中訪問_tags字段。不允許以下劃線開頭的字段名稱。我建議不要用下劃線開頭名稱 – Mikael 2012-03-23 13:48:58

+0

感謝您的快速回答。您對查詢參數非常正確,但這並不能解決我的問題。被稱爲_tags的原因是因爲模型上有一個名爲tags的屬性 - 從模板中訪問會更容易;) – marue 2012-03-23 13:53:41

2

不幸的是,沒有,沒有漂亮的方式。事實上,實際的解決方案甚至醜陋,但是當所有的標籤都存儲在一個單一的文本字段中,有沒有其他的方法:

from django.db.models import Q 

startswith_tag = Q(_tags__startswith=tag.name+' ') 
contains_tag = Q(_tags__contains=' '+tag.name+' ') 
endswith_tag = Q(_tags__endswith=' '+tag.name) 
self.queryset=self.queryset.exclude(startswith_tag | contains_tag | endswith_tag) 

上面的代碼假設標記與空格分隔。如果沒有,您將不得不修改代碼以匹配它們的分隔方式。這個想法是,您使用分隔符作爲搜索的一部分,以確保它是實際標記,而不僅僅是另一個標記的一部分。

如果你不想這樣做,我建議切換到另一個標籤系統,它不會將它們全部轉儲到單個文本字段中,例如django-taggit

+0

好的,謝謝。我很久以前就會轉而使用taggit,但不幸的是,它使用標記卡住了其他應用程序......順便問一下,什麼是Q?佔位符? – marue 2012-03-23 15:18:26

+1

'Q'只是一個封裝查詢參數的對象。它存在允許使用OR和非傳統AND等的複雜查詢。請參閱:https://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q – 2012-03-23 16:23:12

+0

還有一件事我剛剛意識到:不幸的是,在訪問'model._tags'時,django-tagging沒有提供tagstring。看起來創建TagField只是將模型註冊爲可標記的另一種方式。所以即使這個解決方案工作:( – marue 2012-03-24 12:11:18