Django rest framework:当嵌套序列化程序为空时排除结果
Django rest framework: exclude results when nested serializer is empty
我有一个可用的嵌套序列化程序,但我想排除嵌套序列化程序为空的实例。我在嵌套序列化程序上使用的过滤有效,但目前此代码 return 是所有站点,其中大多数站点在应用过滤器时具有空 site_observations 数组。我只想 return 包含 site_observations 的站点。我已经为 site_observations 尝试了 SerializerMethodField 但遇到了同样的问题。使用 DRF 3.12
相关模型是 Site 和具有 FK 的 Observation,related field=site_observations
serializers.py
class FilteredObsListSerializer(serializers.ListSerializer):
def to_representation(self, data):
projName = self.context["projName"]
# this is my filter which works
data = filter_site_observations(data, self.context["request"],
projName)
return super(FilteredObsListSerializer, self).to_representation(data)
class ObsFilterSerializer(serializers.ModelSerializer):
class Meta:
list_serializer_class = FilteredObsListSerializer
model = Observation
fields = "__all__"
class SiteSerializer(GeoFeatureModelSerializer):
site_observations = ObsFilterSerializer(many=True)
class Meta:
model = Site
geo_field = "geometry"
fields = ("id", "name", "geometry", "site_observations")
views.py
class SiteList(generics.ListAPIView):
queryset = Site.objects.all().order_by("pk")
serializer_class = SiteSerializer
# this is for filtering Observations on segment of an url:
def get_serializer_context(self):
context = super(SiteList, self).get_serializer_context()
context.update({"projName": self.kwargs["name"]})
return context
如何排除 site_observations 为空列表的网站?谢谢
一种方法是告诉您的视图仅适用于满足某些条件的特定对象:
class SiteList(generics.ListAPIView):
queryset = Site.objects.filter(
site_observations__isnull=False,
).distinct().order_by('pk')
这将告诉 SiteList
仅使用存在 site_observation
关系的 Site
对象。您需要按照 this.
所述在此处调用 distinct
感谢您的建议,这导致了一个答案。序列化程序中的 运行ning filter_site_observations 不起作用。我在视图中将过滤器重新设计为 运行 并获得了我需要的结果。 (我在使用 SerializerMethodField 之前尝试过这个,但无法正确过滤它;嵌套序列化程序似乎是更好的方法。)感谢您的建议!这是过滤器:
def filter_site_observations(queryset, request, projName):
'''
filters a collection on project, observer status
'''
if request.user.is_authenticated:
authprojects = [
item.project.name
for item in ObserverStatus.objects.filter(observer=request.user.id)
]
if projName in authprojects:
return queryset.filter(site_observations__project__name=projName)
else:
return queryset.filter(
site_observations__project__name=projName).filter(
site_observations__private=False)
else:
return queryset.filter(
site_observations__project__name=projName).filter(
site_observations__private=False)
和 views.py:
class SiteList(generics.ListAPIView):
serializer_class = SiteSerializer
def get_serializer_class(self, *args, **kwargs):
if self.request.method in ("POST", "PUT", "PATCH"):
return SitePostSerializer
return self.serializer_class
def get_queryset(self):
projName = self.kwargs["name"]
queryset = Site.objects.all().order_by('pk')
queryset = filter_site_observations(queryset, self.request, projName)
queryset = queryset.filter(
site_observations__isnull=False, ).distinct()
queryset = self.get_serializer_class().setup_eager_loading(queryset)
return queryset
8 月 28 日更新
实际上,为了获得我需要的过滤,我必须 运行 在 Observation 序列化程序和 SiteList views.py 中使用几乎相同的过滤器。无论我对子数据使用 SerializerMethodField 还是简单的嵌套序列化程序,都是如此。否则,我会得到:1) 所有网站,包括没有任何观察的网站,或 2) 有一些非私人观察但也显示所有私人观察的网站。
filters.py
from users.models import ObserverStatus
def filter_site_observations(queryset, request, projName):
'''
filters a collection on project, observer status; used in views.py.
Both of these filters seem to be required to get proper filtering.
'''
queryset = queryset.filter(site_observations__project__name=projName)
if request.user.is_authenticated:
authprojects = [
item.project.name
for item in ObserverStatus.objects.filter(observer=request.user.id)
]
if projName in authprojects:
return queryset
else:
return queryset.filter(site_observations__private=False)
else:
return queryset.filter(site_observations__private=False)
def filter_observations(queryset, request, projName):
'''
filters observations in ObsSerializer on observer status
'''
if request.user.is_authenticated:
authprojects = [
item.project.name
for item in ObserverStatus.objects.filter(observer=request.user.id)
]
if projName in authprojects:
return queryset
else:
return queryset.filter(private=False)
else:
return queryset.filter(private=False)
所以我过滤了两次,不确定为什么需要这样。
我有一个可用的嵌套序列化程序,但我想排除嵌套序列化程序为空的实例。我在嵌套序列化程序上使用的过滤有效,但目前此代码 return 是所有站点,其中大多数站点在应用过滤器时具有空 site_observations 数组。我只想 return 包含 site_observations 的站点。我已经为 site_observations 尝试了 SerializerMethodField 但遇到了同样的问题。使用 DRF 3.12
相关模型是 Site 和具有 FK 的 Observation,related field=site_observations
serializers.py
class FilteredObsListSerializer(serializers.ListSerializer):
def to_representation(self, data):
projName = self.context["projName"]
# this is my filter which works
data = filter_site_observations(data, self.context["request"],
projName)
return super(FilteredObsListSerializer, self).to_representation(data)
class ObsFilterSerializer(serializers.ModelSerializer):
class Meta:
list_serializer_class = FilteredObsListSerializer
model = Observation
fields = "__all__"
class SiteSerializer(GeoFeatureModelSerializer):
site_observations = ObsFilterSerializer(many=True)
class Meta:
model = Site
geo_field = "geometry"
fields = ("id", "name", "geometry", "site_observations")
views.py
class SiteList(generics.ListAPIView):
queryset = Site.objects.all().order_by("pk")
serializer_class = SiteSerializer
# this is for filtering Observations on segment of an url:
def get_serializer_context(self):
context = super(SiteList, self).get_serializer_context()
context.update({"projName": self.kwargs["name"]})
return context
如何排除 site_observations 为空列表的网站?谢谢
一种方法是告诉您的视图仅适用于满足某些条件的特定对象:
class SiteList(generics.ListAPIView):
queryset = Site.objects.filter(
site_observations__isnull=False,
).distinct().order_by('pk')
这将告诉 SiteList
仅使用存在 site_observation
关系的 Site
对象。您需要按照 this.
distinct
感谢您的建议,这导致了一个答案。序列化程序中的 运行ning filter_site_observations 不起作用。我在视图中将过滤器重新设计为 运行 并获得了我需要的结果。 (我在使用 SerializerMethodField 之前尝试过这个,但无法正确过滤它;嵌套序列化程序似乎是更好的方法。)感谢您的建议!这是过滤器:
def filter_site_observations(queryset, request, projName):
'''
filters a collection on project, observer status
'''
if request.user.is_authenticated:
authprojects = [
item.project.name
for item in ObserverStatus.objects.filter(observer=request.user.id)
]
if projName in authprojects:
return queryset.filter(site_observations__project__name=projName)
else:
return queryset.filter(
site_observations__project__name=projName).filter(
site_observations__private=False)
else:
return queryset.filter(
site_observations__project__name=projName).filter(
site_observations__private=False)
和 views.py:
class SiteList(generics.ListAPIView):
serializer_class = SiteSerializer
def get_serializer_class(self, *args, **kwargs):
if self.request.method in ("POST", "PUT", "PATCH"):
return SitePostSerializer
return self.serializer_class
def get_queryset(self):
projName = self.kwargs["name"]
queryset = Site.objects.all().order_by('pk')
queryset = filter_site_observations(queryset, self.request, projName)
queryset = queryset.filter(
site_observations__isnull=False, ).distinct()
queryset = self.get_serializer_class().setup_eager_loading(queryset)
return queryset
8 月 28 日更新 实际上,为了获得我需要的过滤,我必须 运行 在 Observation 序列化程序和 SiteList views.py 中使用几乎相同的过滤器。无论我对子数据使用 SerializerMethodField 还是简单的嵌套序列化程序,都是如此。否则,我会得到:1) 所有网站,包括没有任何观察的网站,或 2) 有一些非私人观察但也显示所有私人观察的网站。
filters.py
from users.models import ObserverStatus
def filter_site_observations(queryset, request, projName):
'''
filters a collection on project, observer status; used in views.py.
Both of these filters seem to be required to get proper filtering.
'''
queryset = queryset.filter(site_observations__project__name=projName)
if request.user.is_authenticated:
authprojects = [
item.project.name
for item in ObserverStatus.objects.filter(observer=request.user.id)
]
if projName in authprojects:
return queryset
else:
return queryset.filter(site_observations__private=False)
else:
return queryset.filter(site_observations__private=False)
def filter_observations(queryset, request, projName):
'''
filters observations in ObsSerializer on observer status
'''
if request.user.is_authenticated:
authprojects = [
item.project.name
for item in ObserverStatus.objects.filter(observer=request.user.id)
]
if projName in authprojects:
return queryset
else:
return queryset.filter(private=False)
else:
return queryset.filter(private=False)
所以我过滤了两次,不确定为什么需要这样。