28

次のような基本的な Django モデルがあります。

class Business(models.Model):
    name = models.CharField(max_length=200, unique=True)
    email = models.EmailField()
    phone = models.CharField(max_length=40, blank=True, null=True)
    description = models.TextField(max_length=500)

上記のモデルで次のような複雑なクエリを実行する必要があります。

qset = (
    Q(name__icontains=query) |
    Q(description__icontains=query) |
    Q(email__icontains=query)
    )
results = Business.objects.filter(qset).distinct()

運が悪いので、 tastypieを使用して次のことを試しました。

def build_filters(self, filters=None):
    if filters is None:
        filters = {}
    orm_filters = super(BusinessResource, self).build_filters(filters)

    if('query' in filters):
        query = filters['query']
        print query
        qset = (
                Q(name__icontains=query) |
                Q(description__icontains=query) |
                Q(email__icontains=query)
                )
        results = Business.objects.filter(qset).distinct()
        orm_filters = {'query__icontains': results}

    return orm_filters

そして、tastypie のクラス Meta では、フィルタリングを次のように設定しています。

filtering = {
        'name: ALL,
        'description': ALL,
        'email': ALL,
        'query': ['icontains',],
    }

これにどのように取り組むことができるかについてのアイデアはありますか?

ありがとう - ニュートン

4

3 に答える 3

42

あなたは正しい軌道に乗っています。ただし、build_filtersリソース ルックアップを ORM ルックアップに移行することになっています。

デフォルトの実装では、に基づいてクエリ キーワードを__key_bits と値のペアに分割し、検索したリソースとそれに相当する ORM の間のマッピングを見つけようとします。

あなたのコードは、そこにフィルターを適用するだけではなく、ビルドするだけです。改善された修正版は次のとおりです。

def build_filters(self, filters=None):
    if filters is None:
        filters = {}
    orm_filters = super(BusinessResource, self).build_filters(filters)

    if('query' in filters):
        query = filters['query']
        qset = (
                Q(name__icontains=query) |
                Q(description__icontains=query) |
                Q(email__icontains=query)
                )
        orm_filters.update({'custom': qset})

    return orm_filters

def apply_filters(self, request, applicable_filters):
    if 'custom' in applicable_filters:
        custom = applicable_filters.pop('custom')
    else:
        custom = None

    semi_filtered = super(BusinessResource, self).apply_filters(request, applicable_filters)

    return semi_filtered.filter(custom) if custom else semi_filtered

Q オブジェクトを使用しているため、標準apply_filtersメソッドはカスタム フィルター キーを適用するほどスマートではありません (何もないため)。そうするbuild_filtersことで、適切なフィルターを見つけ、それが何を意味するかを構築し、それをカスタムとして apply_filters に渡すことができます。これは、その値をディクショナリーからアイテムとしてアンパックしようとするのではなく、直接適用するだけです。

于 2012-04-05T03:20:07.107 に答える