2012-03-23 6 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? 

私は 'id'のスペルを間違えなかったと確信しているので、私はこのようなもののためにタグ付けを使う方法についていくつか検索しました。ドキュメントでは、カスタムマネージャについては多くのことがありますが、どういうわけか、私はそれらを使って自分が望むものを得る方法を知ることができません。

編集:

回避が整数のリストである
self.queryset=self.queryset.exclude(_tags__in=avoid) 

に上記のコードを修正しました。それで、ジャンゴタギングのTagFieldが特別なCharField(またはTextField?)にすぎないという問題が残されています。私が整数のリストと照らし合わせて照会するだけでは、何も並べ替えることはできません。

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

だけでなく醜いですが、また、複数の単語または他のタグのマッチング部品で作られたタグの問題を私に残します:私はこのような方法でこれを解決しようとすることができます。

私は何とか、これは、ジャンゴタギングの仕組みを理解している人によって、はるかにきれいに解決できるという疑いがあります。

答えて

0

Chrisの回答のコメントに記載されているように、djangoタグ付けはmodel._tagにアクセスするときにタグ文字列を渡しません。

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:このためのモデルは、このようになっていることを完了するために

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) 

:最後に、私は、クエリを実行し、その後、特定のタグを含むループを整理するよりも、他の解決策がありませんでした私はしばらくの間、私はオブジェクトのクエリチェーンにタグをタグ付けしてタグを照合する方法を見つけませんでした。このプロジェクトではタグ付けに苦しんでいますが、これは本当の欠点です...

3

モデルはどのように定義されていますか? _tagsはForeignKeyフィールドですか?

__id部分を削除しない場合

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

また、テンプレート内の_tagsフィールドに直接アクセスすることはできません。アンダースコアで始まるフィールド名は使用できません。私はアンダースコアで名前を始めることをお勧めしません。 – Mikael

+0

あなたの素早い答えに感謝します。あなたは質問の引数については絶対に妥当でしたが、それは私の問題を解決するものではありません。 _tagsは、モデルにtagsという名前のプロパティがあるため、テンプレートからアクセスするほうがはるかに簡単です; – marue

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

+1

'Q'は単にクエリ引数をカプセル化するオブジェクトです。 ORと非従来のANDなどを使用して複雑なクエリを行うことができます。https://docs.djangoproject.com/ja/dev/topics/db/queries/#complex-lookups-with-q –

+0

もう1つ私はちょうど気付いた:残念なことにdjangoタグは 'model._tags'にアクセスするときにタグ文字列を渡していません。 TagFieldの作成は、モデルをタグ付け可能なものとして登録する別の方法です。だからこのソリューションでさえ働いていない:( – marue

関連する問題