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))
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))
django.db.models impor Q
Itu berhasil untuk saya.
Komentar yang paling membantu
Saya telah melakukan sesuatu seperti berikut ini, saya tidak yakin berfungsi untuk semua kasus tetapi menyelesaikan masalah saya: