Django-filter: Filter pada beberapa bidang dengan kondisi ATAU

Dibuat pada 13 Okt 2019  ·  8Komentar  ·  Sumber: carltongibson/django-filter

Hai,
Bagaimana mungkin memfilter beberapa bidang dengan kondisi ATAU !?
Sebagai contoh:
first_name = foo OR last_name = bar
Setara dengan:
model.objects.filter(Q(first_name=foo) | Q(last_name=bar))

Komentar yang paling membantu

Saya telah melakukan sesuatu seperti berikut ini, saya tidak yakin berfungsi untuk semua kasus tetapi menyelesaikan masalah saya:

class BaseFilter(django_filters.FilterSet):
    def OR(self, queryset, field_name, value):
        if not hasattr(self, "groups"):
            setattr(self, "groups", {})

        self.groups[field_name] = value
        return queryset

    <strong i="6">@property</strong>
    def qs(self):
        base_queryset = super().qs

        if not hasattr(self, "groups"):
            return base_queryset

        query = Q()
        for key, value in self.groups.items():
            query |= Q(**{key: value})

        return base_queryset.filter(query)
class PlanFilter(BaseFilter):
    double_visit__or = django_filters.UUIDFilter("double_visit", method="OR")
    visitor__or = django_filters.UUIDFilter("visitor", method="OR")
    class Meta:
        model = models.Plan
        fields = {
            "id": ["exact"],
            "date": ["exact", "gte", "lte",],
            "visitor": ["exact"],
            "doctor": ["exact"],
            "double_visit": ["exact"]
        }

Semua 8 komentar

Terima kasih telah membuka ini, ini pertanyaan yang sama persis dengan yang saya miliki.

Saat ini, saya mendapatkan peringatan berikut:

/usr/local/lib/python3.7/site-packages/django_filters/rest_framework/backends.py:128: 
UserWarning: <class 'project.api.views.FooBarViewSet'> is not compatible with schema generation

Dan saya memiliki FilterSet dan ViewSet yang terlihat seperti ini:

# models
class FooBarUserAssignment(models.Model):
    user = models.ForeignKey("auth.User", on_delete=models.CASCADE)
    foobar = models.ForeignKey("FooBar", on_delete=models.CASCADE)

    class Meta:
        unique_together = (
            ("user", "foobar"),
        )


class FooBarGroupAssignment(models.Model):
    group = models.ForeignKey("auth.Group", on_delete=models.CASCADE)
    foobar = models.ForeignKey("FooBar", on_delete=models.CASCADE)

    class Meta:
        unique_together = (
            ("group", "foobar"),
        )

class FooBar(models.Model):
    title = models.CharField(max_length=160, unique=True)

    users = models.ManyToManyField(
        to="auth.User",
        through=FooBarUserAssignment,
    )
    groups = models.ManyToManyField(
        to="auth.Group",
        through=FooBarGroupAssignment,
    )

    def __str__(self):
        return self.title

# filters
from django_filters import rest_framework as rest_framework_filters

class FooBarFilter(rest_framework_filters.FilterSet):
    title = rest_framework_filters.CharFilter(field_name="title", lookup_expr="icontains")

    class Meta:
        model = FooBar
        fields = ("title", )

# viewsets
class FooBarViewSet(ModelViewSet):
    queryset = Foobar.objects.order_by("-title")
    serializer_class = FooBarSerializer
    filterset_class = FooBarFilter

    def get_queryset(self):
        queryset = self.queryset

        q_name = Q()
        rel_name = self.request.query_params.get("rel_name", None)
        if rel_name:
            q_name = Q(users__name=rel_name)

        q_groups = Q()
        rel_groups = self.request.query_params.get("rel_groups", "").split(",")
        if any(rel_groups):
            q_groups = Q(groups__name__in=rel_groups)

        qs = queryset.filter(q_name | q_groups).distinct()
        return qs

Bagaimana saya bisa membangun FilterSet untuk menjalankan kueri yang sama persis?
Saya dapat mengimplementasikan bagian dari FilterSet, tetapi masih tidak tahu cara terbaik untuk memindahkan logika OR dari ViewSet.get_queryset() ke FilterSet

import django_filters
from django_filters import rest_framework as rest_framework_filters

class CharInFilter(django_filters.BaseInFilter, rest_framework_filters.CharFilter):
    pass

class FooBarFilter(rest_framework_filters.FilterSet):
    title = rest_framework_filters.CharFilter(field_name="title", lookup_expr="icontains")
    rel_name = rest_framework_filters.CharFilter(field_name="users__name", lookup_expr="exact")
    rel_groups = CharInFilter(field_name="groups__name")

    class Meta:
        model = FooBar
        fields = ("title", )

    def filter_queryset(self, queryset):
        qs = super().filter_queryset(queryset)
        return qs.distinct()

Sepertinya ini adalah bagian dari ekstensi django-filter ini yang dapat dipasang di sepanjang sisi django-filter. https://github.com/philipn/Django-rest-framework-filters#complex -operasi

Halo semua. Saya telah membuat #1167, yang seharusnya menyediakan validasi dan pemfilteran tingkat grup. Untuk OP, penggunaan akan terlihat seperti:

class UserFilter(FilterSet):
    class Meta:
        model = User
        field = ['username', 'first_name', 'last_name']
        groups = [
            CombinedGroup(filters=['first_name', 'last_name'], combine=operator.or_),
        ]

Setiap umpan balik tentang PR akan sangat dihargai.

Masih masalah yang sama di sini, apakah ada solusi mereka?

@JeromeK13 sepertinya bukan apa-apa! Saya memiliki pertanyaan yang sama

Saya telah melakukan sesuatu seperti berikut ini, saya tidak yakin berfungsi untuk semua kasus tetapi menyelesaikan masalah saya:

class BaseFilter(django_filters.FilterSet):
    def OR(self, queryset, field_name, value):
        if not hasattr(self, "groups"):
            setattr(self, "groups", {})

        self.groups[field_name] = value
        return queryset

    <strong i="6">@property</strong>
    def qs(self):
        base_queryset = super().qs

        if not hasattr(self, "groups"):
            return base_queryset

        query = Q()
        for key, value in self.groups.items():
            query |= Q(**{key: value})

        return base_queryset.filter(query)
class PlanFilter(BaseFilter):
    double_visit__or = django_filters.UUIDFilter("double_visit", method="OR")
    visitor__or = django_filters.UUIDFilter("visitor", method="OR")
    class Meta:
        model = models.Plan
        fields = {
            "id": ["exact"],
            "date": ["exact", "gte", "lte",],
            "visitor": ["exact"],
            "doctor": ["exact"],
            "double_visit": ["exact"]
        }

Saya percaya saya menemukan cara yang jauh lebih sederhana:

from django.db.models.query_utils import Q
user_contacts = Contact.objects.order_by('-contact_date').filter(Q(sender_id=request.user.user_id)|Q(receiver_id=request.user.user_id)) 

Dalam kasus saya, saya ingin mengumpulkan semua baris yang memiliki sender_id atau receiver_id . Dan, saya ingin mereka berada dalam satu set kueri untuk memesannya dengan date

Hai,
Bagaimana mungkin memfilter beberapa bidang dengan kondisi ATAU !?
Sebagai contoh:
first_name = foo OR last_name = bar
Setara dengan:
model.objects.filter(Q(first_name=foo) | Q(last_name=bar))

Impor Q

django.db.models impor Q

Itu berhasil untuk saya.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

jwineinger picture jwineinger  ·  3Komentar

xtrinch picture xtrinch  ·  4Komentar

gsvr picture gsvr  ·  3Komentar

GuillaumeCisco picture GuillaumeCisco  ·  3Komentar

chromakey picture chromakey  ·  5Komentar