gpt4 book ai didi

python - Django 嵌套序列化器不序列化内部模型

转载 作者:太空宇宙 更新时间:2023-11-04 04:44:42 24 4
gpt4 key购买 nike

我正在尝试使用 django-rest-framework 将自定义 action 添加到我在 Django2 中的 ViewSet。问题是我的序列化程序没有序列化嵌套模型,因此出现错误:

{
"labels": [
{
"non_field_errors": [
"Invalid data. Expected a dictionary, but got Label."
]
},
{
"non_field_errors": [
"Invalid data. Expected a dictionary, but got Label."
]
}
]
}

我有两个具有 M:N 关系的模型。

标签模型:

class Label(models.Model):
name = models.CharField(max_length=30, help_text='Name of Label')
desc = models.CharField(max_length=200, help_text='Description of Label')

def __str__(self):
return self.name

标签集模型:

class LabelSet(models.Model):
labels = models.ManyToManyField(Label, blank=True, help_text='ManyToMany field of corresponding labels')
name = models.CharField(max_length=30, help_text='Name of Label Set')
desc = models.CharField(max_length=200, help_text='Description of Label Set')

def __str__(self):
return self.name

机器型号:

class Machine(models.Model):
name = models.CharField(max_length=30, help_text='Name of machine')
desc = models.CharField(max_length=200, help_text='Description of machine')
location = models.ForeignKey(Location, null=True, blank=True, on_delete=models.CASCADE, help_text='ID of machine location')
labelset = models.ForeignKey(LabelSet, null=True, blank=True, on_delete=models.DO_NOTHING, help_text='ID of set of labels relevant for this machine')

def __str__(self):
return self.name

序列化器:

class LabelSerializer(serializers.ModelSerializer):
class Meta:
model = Label
fields = '__all__'

class LabelSetSerializer(serializers.ModelSerializer):
qs = Label.objects.all().values()
labels = LabelSerializer(qs, many=True)
class Meta:
depth = 1
model = LabelSet
fields = ('name', 'desc', 'labels')

viewsets.py 中的自定义操作(我想通过机器检索可用标签,所以路径是 /machines/{id}/labels

class MachineViewSet(viewsets.ModelViewSet):
'''
A viewset used for retrieving and editing Machine instances.
'''
#permission_classes = (DRYPermissions,)
serializer_class = MachineSerializer
queryset = Machine.objects.all()

# /api/v1/machines/{machine_id}/labels
@action(detail=True)
def labels(self, request, pk=None):
# Get labelset id
ls = Machine.objects.get(pk=pk).labelset

# Get LabelSet instance
serializer = LabelSetSerializer(data=model_to_dict(ls))
if serializer.is_valid():
return Response(serializer.data)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

端点工作正常,但在查询 /machines/1/labels 时,我得到的响应是第一个片段:

"Invalid data. Expected a dictionary, but got Label."

我完全没有想法,甚至尝试在 Serializer 中从 qs = Label.objects.all().values() 制作字典,但没有成功。

感谢@Jerin Peter George,现在的输出是:

HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
"name": "TestSet",
"desc": "asd",
"labels": [
{
"id": 1,
"name": "OK",
"desc": "desc"
},
{
"id": 2,
"name": "Broken",
"desc": "asd"
}
]
}

所以 /api/v1/machines/1/labels 有效,但突然 /api/v1/machines/ 无效。 (502 Bad Gateway with error TypeError: 'LabelSet' object is not iterable)

APP 级别的 url:

from django.conf.urls import url
from devices.viewsets import *
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'devices', DeviceViewSet, base_name='device')
router.register(r'projects', ProjectViewSet, base_name='project')
router.register(r'locations', LocationViewSet, base_name='location')
router.register(r'industries', IndustryViewSet, base_name='industry')
router.register(r'companies', CompanyViewSet, base_name='companies')
router.register(r'project_types', ProjectTypeViewSet, base_name='project_type')
router.register(r'device_types', DeviceTypeViewSet, base_name='device_type')
router.register(r'machines', MachineViewSet, base_name='machine')
router.register(r'records', RecordViewSet, base_name='record')
router.register(r'labels', LabelViewSet, base_name='label')
router.register(r'labelsets', LabelSetViewSet, base_name='label_set')
urlpatterns = router.urls

应用级 urls.py

from django.contrib import admin
from django.conf.urls import url
from django.urls import include, path
from rest_framework.documentation import include_docs_urls
from rest_framework_expiring_authtoken import views
from devices.views import AudioUploadView

API_PREFIX = 'api/v1/'

urlpatterns = [
url(API_PREFIX + 'docs/', include_docs_urls(title='API Docs')),
url(API_PREFIX + 'admin/', admin.site.urls),
url(API_PREFIX + 'api-token-auth/', views.obtain_expiring_auth_token),
path(API_PREFIX, include('devices.urls'))
]

编辑:已解决显然我向 MachineSerializer

添加了一个更多的嵌套序列化程序
class MachineSerializer(serializers.ModelSerializer):
labelsets = LabelSetSerializer(many=True)
class Meta:
model = Machine
fields = '__all__'

所以删除行 labelsets = LabelSetSerializer(many=True) 就可以了。这就是错误的来源,现在一切都按预期工作,谢谢:)

最佳答案

将您的 labels() 替换为以下代码段,

@action(detail=True)
def labels(self, request, pk=None):
# Get labelset id
ls = Machine.objects.get(pk=pk).labelset

# Get LabelSet instance
serializer = LabelSetSerializer(ls)
return Response(serializer.data)

关于python - Django 嵌套序列化器不序列化内部模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49879103/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com