tag
,函数datasetfiletagsquery
也会被执行dataset_id
,那么它也会在 retrieve
和其他 action
api 函数中强制执行。dataset_id
查询时,我才需要将 tag
作为所需查询class DatasetFileViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
class DatasetFileFilter(filters.FilterSet):
def datasetfiletagsquery(request):
try:
dataset_id = request.query_params['dataset_id']
qs = Tag.objects.filter(object_id=dataset_id, content_type=ContentType.objects.get_for_model(Dataset),
category=Tag.CategoryChoices.DATASET_FILE)
except KeyError:
raise serializers.ValidationError({'dataset_id': 'This query is required'})
return qs
def datasetfiletagsfilter(queryset, name, value):
tag_ids = [tag.pk for tag in value]
qs = queryset.filter_by_tags(tag_ids)
return qs
dataset_id = filters.NumberFilter()
tag = filters.ModelMultipleChoiceFilter(queryset=datasetfiletagsquery, to_field_name='name', method=datasetfiletagsfilter)
class Meta:
model = DatasetFile
fields = ['dataset_id', 'tag']
queryset = DatasetFile.objects.prefetch_related('tags', 'related_child_dataset_files__child').select_related('datasetbatchfile').extend_order_by()
serializer_class = DatasetFileSerializer
filterset_class = DatasetFileFilter
def get_queryset(self):
if self.action == 'download':
qs = DatasetFile.objects.all()
else:
qs = super().get_queryset()
qs = qs.filter(dataset__organization_id=self.request.user.organization_id)
return qs
@action(methods=['POST'], detail=True, url_path='download', serializer_class=DatasetFileDownloadSerializer)
def download(self, request, pk):
"""
api for downloading dataset file
"""
instance = self.get_object()
instance = instance.dataset.get_datasetfiles_for_download(datasetfile_ids=[instance.pk])[0]
serializer = self.get_serializer(instance)
return Response(serializer.data, status=status.HTTP_200_OK)
datasetfiletagsquery
查询,则不应执行 tag
函数required
字段必须仅针对 list
api 强制执行。执行
datasetfiletagsquery
以获取按标签过滤的所有可能值。它在两种情况下执行:
因此不可能让它不被执行,DRF 在其代码中强制执行它。这里唯一的可能性是从过滤器字段中删除
queryset= datasetfiletagsquery
属性,并在过滤时手动验证是否允许该标签。
第二个问题可能也无法直接解决,除非您将其设为 DRF 不需要的并在过滤期间手动验证它。这也会导致端点的模式错误(它不会指示列表方法中需要这些字段)。如果这对您来说是个问题,您可以将模式覆盖为您自己手动创建的模式。
此外,stackoverflow 上有一条规则,每个问题只需要解决一个问题。
要解决问题 1,请修改 DatasetFileViewSet 中的 datasetfiletagsquery,以在请求中缺少“tag”参数时返回空或默认查询集。对于问题 2,在同一视图集中覆盖 get_filterset_kwargs,以仅在存在标签查询时根据需要动态设置 dataset_id,从而允许您根据请求的上下文有选择地强制执行此条件。该解决方案可确保 Django 应用程序中的高效且上下文敏感的过滤。
您可以尝试以下代码修改:
class DatasetFileViewSet(...):
# ... your existing code code ...
def datasetfiletagsquery(request):
# Check if 'tag' parameter is present
if 'tag' not in request.query_params:
return Tag.objects.none() # or your default queryset
# ... rest of the function ...
def get_filterset_kwargs(self):
kwargs = super().get_filterset_kwargs()
if 'tag' in self.request.query_params:
# Adjust the 'dataset_id' filter to be required
# This may involve custom logic to modify the filter attributes
return kwargs
# ... rest of the viewset ...