首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django Rest框架关系序列化

Django Rest框架关系序列化
EN

Stack Overflow用户
提问于 2019-08-04 06:57:11
回答 2查看 249关注 0票数 1

我试图用外键获取以下模型的序列化数据,但在输出中,我只获取i,而不是与超链接相关的模型字段。

我试过使用配置文件序列化程序中的注释行获取技能模型的所有字段,但没有成功。

models.py

代码语言:javascript
复制
class Profile(models.Model):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    first_name = models.CharField(max_length=20, null=True)
    last_name = models.CharField(max_length=20, null=True)

    def __str__(self):
        return 'Profile for user {}'.format(self.user.username)


class Skill(models.Model):
    skill = models.CharField(max_length=20, null=True)
    level = models.CharField(max_length=20, null=True)
    user = models.ForeignKey(Profile, null=True,
                             on_delete=models.PROTECT, related_name='skills')

    def __str__(self):
        return '%s: %s: %s' % (self.user, self.skill, self.level)

serializer.py

代码语言:javascript
复制
class SkillSerializer(serializers.ModelSerializer):

    class Meta:
        model = Skill
        fields = ('user', 'skill', 'level')

class ProfileSerializer(serializers.ModelSerializer):

    class Meta:
        # skills = SkillSerializer(many=True, read_only=True)  # serializes child model's data inside this model's data
        # skills = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='skill-detail')
        # skills = serializers.StringRelatedField(many=True)
        # skills = serializers.HyperlinkedIdentityField( view_name = "skill-list", lookup_field = "user")
        url = HyperlinkedIdentityField( view_name="profile-detail", lookup_field = "id")
        # user = serializers.ReadOnlyField(source='user.username')
        # pdb.set_trace()

        model = Profile
        fields = ['id', 'user', 'url', 'skills']

views.py

代码语言:javascript
复制
class ProfileList(generics.ListCreateAPIView):
    queryset = Profile.objects.all()
    serializer_class = ProfileSerializer

class ProfileDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Profile.objects.all()
    serializer_class = ProfileSerializer

class SkillList(generics.ListCreateAPIView):
    queryset = Skill.objects.all()
    serializer_class = SkillSerializer

class SkillDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Skill.objects.all()
    serializer_class = SkillSerializer

urls.py

代码语言:javascript
复制
path('profiles/', views.ProfileList.as_view(), name='profile-list'),
path('profiles/<int:pk>/', views.ProfileDetail.as_view(), name='profile-detail'),   
path('skills/', views.SkillList.as_view(), name='profile-list'),
path('skills/<int:pk>/', views.SkillDetail.as_view(), name='skill-list'),

输出:http://127.0.0.1:8000/authenticator/profiles/

代码语言:javascript
复制
   [  "id": 6,
        "user": 4,
        "url": "http://127.0.0.1:8000/authenticator/profiles/6/",
        "skills": [
            57,
            55
        ],
   ]

预期产出:

代码语言:javascript
复制
   [  "id": 6,
        "user": 4,
        "url": "http://127.0.0.1:8000/authenticator/profiles/6/",
        "skills": [
              {
                "user": 6,
                "skill": "ABC",
                "level": "Beginner"
              },
              {
                "user": 6,
                "skill": "DEF",
                "level": "Intermediate"
              },
         ]
    ]
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-08-04 07:12:34

这通常适用于serializer.py中的以下内容:

代码语言:javascript
复制
class ProfileSerializer(serializers.ModelSerializer):
    skills = SkillSerializer(many=True, read_only=True)  # serializes child model's data inside this model's data
    url = HyperlinkedIdentityField( view_name="profile-detail", lookup_field = "id")

    class Meta:
        model = Profile
        fields = ['id', 'user', 'url', 'skills']

因此,基本上取消ProfileSerializer被告知使用SkillsSerializers序列化技能的行,这样整个技能对象都包含在结果中,而不是in中。

票数 1
EN

Stack Overflow用户

发布于 2019-08-04 12:16:17

您可以为解决方案使用嵌套序列化器的概念。

创建两个序列化程序ProfileReadSerializerProfileWriteSerializer

serializers.py

代码语言:javascript
复制
class SkillSerializer(serializers.ModelSerializer):
    class Meta:
        model = Skill
        fields = ('user', 'skill', 'level')


class ProfileReadSerializer(serializers.ModelSerializer):
    skills = SkillSerializer(many=True, read_only=True)
    url = HyperlinkedIdentityField( view_name="profile-detail", lookup_field = "id")

    class Meta:
        model = Profile
        fields = ('id', 'user', 'url', 'skills')


class ProfileWriteSerializer(serializers.ModelSerializer):
    skills = SkillSerializer(many=True)

    class Meta:
        model = Profile
        fields = ('id', 'user', 'url', 'skills')

在视图中,您可以简单地使用ModelViewSet使事情变得简单,并使用get_serializer_class

views.py

代码语言:javascript
复制
from rest_framework.viewsets import ModelViewSet

class ProfileVewSet(ModelViewSet):
    queryset = Profile.objects.all()

    def get_serializer_class(self):
        if self.request.method == 'POST' or self.request.method == 'PUT' or self.request.method == 'PATCH':
            return ProfileWriteSerializer
        else:
            return ProfileReadSerializer

最后,如果您正在使用ModelViewSet,则需要更改urls.py

urls.py

代码语言:javascript
复制
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('profile', views.ProfileViewSet, base_name='profile')

urlpatterns = [
    path('', include(router.urls))
]

我想这能解决你的问题。请看一下。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57344515

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档