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)

ここで、avoidは整数のリストです。そして、それはdjango-taggingのTagFieldが単なる特別なCharField(またはTextField?)であるという問題を私に残します。もちろん、整数のリストに対してクエリを実行しただけでは、何も分類されません。私はこれを次のように解決しようとすることができます:

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

これは醜いだけでなく、複数の単語で構成されたタグや他のタグの一部と一致するという問題も抱えています。

私はどういうわけか、これはdjangoのタグ付けがどのように機能するかを理解している誰かによってはるかにきれいな方法で解決できるのではないかと疑っています。

4

3 に答える 3

3

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

そうでない場合は、__id部分を削除します

self.queryset=self.queryset.exclude(_tags__in=avoid)
于 2012-03-23T13:25:57.507 に答える
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)に切り替えることをお勧めします。

于 2012-03-23T14:57:57.840 に答える
0

クリスの回答へのコメントで説明されているように、django-taggingはにアクセスするときにタグ文字列を配信しませんmodel._tag。結局、クエリを実行し、後で特定のタグを含むループを整理する以外に解決策はありませんでした。

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)

かなり長い間試しましたが、タグのタグ付けに対するクエリをオブジェクトのクエリチェーンにチェーンする方法が見つかりませんでした。このプロジェクトでは、タグ付けにこだわっていますが、これは本当の欠点です...

于 2012-03-24T12:25:26.710 に答える