django - 为什么我的 ViewSet 在使用 get_object_or_404 使用 for loop ang 后继续循环?
问题描述
我正在为我的图像的 image_tags 端点使用额外的操作。我想为每个图像的 image_tags 发布和删除。我还可以使用 image_id 来访问lookup_field
我的 Image 中使用的每个图像。
例如,对于图像 IMG_123 的 image_tags,我有这个端点:
localhost:8000/my_app/images/IMG_123/image_tags
这是我的代码:
#models.py
class ImageTag(models.Model):
name = models.CharField()
description = models.CharField()
class Image(models.Model):
image_id = models.CharField(unique=True)
image_tags = models.ManyToManyField(ImageTag, blank=True)
...
#serializers.py
class ImageSerializer(serializers.ModelSerializer):
class Meta:
model = Image
fields = '__all__'
class ImageTagSerializer(serializers.ModelSerializer):
image_tags = serializers.StringRelatedField(many=True)
class Meta:
model = Image
fields = ('image_tags',)
def to_internal_value(self, data):
return data
#views.py
class ImageExtraAction(viewsets.ModelViewSet):
@action(detail=True, methods=['get', 'post', 'delete'])
def image_tags(self, request, capture_id=None):
print("REQ", request.data)
capture = self.get_object()
data = request.data.copy()
image_tags = request.data.get('image_tags')
print("IMG", image_tags)
#print("LEN", len(image_tags))
if image_tags:
print("HERE")
for tag in image_tags:
obj_ = get_object_or_404(ImageTag, name=tag)
data['image_tags'].append(obj_)
print("DATA", data)
serializer = ImageTagSerializer(capture, data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class ImageViewSet(ImageExtraAction, viewsets.ModelViewSet):
queryset = Image.objects.all()
serializer_class = ImageSerializer
lookup_field = 'image_id'
...
#urls.py
router.register(r'images', ImageViewSet, basename='image')
当我发布:
{"image_tags": ["Urban", "Vegetation"]}
我希望它们被添加到 image_tags 字段中。但是我遇到了问题,因为它一直在代码块处循环:
for tag in image_tags:
obj_ = get_object_or_404(ImageTag, name=tag)
data['image_tags'].append(obj_)
为什么会这样?我该如何解决?
我已经尝试调试寻找它的长度,它的长度为 2,但是当它涉及到循环时,它只是无限循环,因此我的请求没有得到满足。
解决方案
它无限循环的原因是因为您要添加到列表的末尾。
这是您每次迭代的列表。
1. ["Urban", "Vegetation"]
2. ["Urban", "Vegetation", "Urban"]
3. ["Urban", "Vegetation", "Urban", "Vegetation"]
4. ["Urban", "Vegetation", "Urban", "Vegetation", "Urban"]
...
这种情况一直没有结束。
一种更好的方法是image_tags
使用一个查询来查询所有内容。这也更高效,因为您不会对每个标签进行单独的数据库查询。
data['image_tags'] = get_list_or_404(ImageTag, name_in=image_tags)
# or
data['image_tags'] = ImageTag.objects.filter(name_in=image_tags).all()
如果它丢失了创建一个...
# Query all image tags
tags = ImageTag.objects.filter(name_in=data['image_tags']).all()
# create a list of all existing tags
existing_tags = [tag.name for tag in tags]
# create a list of all tags in the request that don't exist.
missing_tags = [tag for tag in data['image_tags'] if tag not in existing_tags]
missing_tags
是不存在的标签列表。您可以简单地对其进行迭代并创建新标签。
推荐阅读
- asp.net-core - Asp.net core 3.0 - 结合身份认证和挑战方案
- python-3.x - 转换日期时间后,我的时间戳中未显示小时、分钟和秒
- amazon-sqs - 尝试在 SQS 中保存时请求返回 AccessDenied
- javascript - 如何通过单击按钮更改 css 属性的值
- javascript - 为chart.js中的水平条添加值
- javascript - 确定视频的播放时间
- reactjs - 用于 React 的 MailChimp 和 Stripe 集成
- c# - 具有不同发行者的 ASP 网络核心身份验证
- python - 代码重构 scipy SLSQP 期间的参数数量无效
- prestashop - 将类别作为整数名称导入产品