【问题标题】:Nested Multiple choice field serialize in Django and VueJS appDjango和VueJS应用程序中的嵌套多项选择字段序列化
【发布时间】:2020-01-19 19:42:39
【问题描述】:

我有多项选择嵌套序列化程序,我能够获得值,但在补丁调用期间 subjects 没有得到更新

这里User和Subject是两个模型,

**Model.py**

class Subject(models.Model):
    uid = models.AutoField(verbose_name='ID', 
                                  serialize=False, 
                                  auto_created=True, 
                                  primary_key=True)
    ENG = "ENGLISH"
    HND = "HINDI"

    SUBJECT = (
        (ENG, "English"),
        (HND, "Hindi"),
    )

    subject = models.CharField(
        max_length=50, choices=SUBJECT, default=ENG)

    def __str__(self):
        return self.subject


class User(AbstractUser):
    uid = models.AutoField(verbose_name='ID', 
                                  serialize=False, 
                                  auto_created=True, 
                                  primary_key=True)
    TEACHER = "Teacher"
    STUDENT = "Student"

    user_type = models.CharField(max_length=30, default=STUDENT)
    approved = models.BooleanField(default=True)

    def save(self, *args, **kwargs):
        if self.user_type == User.TEACHER and self._state.adding:
            self.approved = False
        super().save(*args, **kwargs)

    @property
    def syllabus(self):
        ret = self.teacher.syllabus_set.all()
        if ret:
            return ret
        else:
            return ''

这是我的序列化程序调用


**serializers.py**

class TeacherProfileDetails(serializers.ModelSerializer):
    logger = logging.getLogger(__name__)
    teacher_date = AvailabilityDetails(many=True, read_only=True)
    first_name = serializers.CharField(source='user.first_name', read_only=True)
    last_name = serializers.CharField(source='user.last_name', read_only=True)
    cities = CitySerializer(many=True, read_only=True)
    subject = serializers.SerializerMethodField()
    user = UserDetailsSerializer(read_only=True)

    class Meta:
        model = Teacher
        fields = ('user', 'first_name', 'last_name', 
                  'bio', 'teacher_cost', 'subject', 'teacher_date', 'cities')

    def get_subject(self, obj):
        subject_list = []
        for i in obj.subject.all():
            subject_list.append(i.subject)
        return subject_list

这是我的views.py调用

**views.py**

class TeacherListCreateAPIView(APIView):
        logger = logging.getLogger(__name__)

        #def create(self, request, *args, **kwargs):
        def get(self, request, *args, **kwargs):
            self.logger.info("Geeting TeacherListCreateAPIView information")
            teacherList = Teacher.objects.filter(user__username=kwargs["username"])
            self.logger.info(teacherList)
            serializers = TeacherProfileDetails(teacherList, many=True)
            self.logger.info(serializers.data)
            return Response(serializers.data)
        def patch(self, request, *args, **kwargs):
            teacher = Teacher.objects.get(user__username=kwargs['username'])
            serializers = TeacherProfileDetails(data=request.data, instance=teacher)
            self.logger.info(serializers)
            if serializers.is_valid():
                serializers.save()
                return Response(serializers.data, status=status.HTTP_201_CREATED)
            return Response(serializers.errors, status=status.HTTP_400_BAD_REQUEST)

这里是 urls.py

path('teacher/<str:username>/details',
         TeacherListCreateAPIView.as_view(), name="teacher-details"),

问题:

我能够获取教师详细信息,但补丁调用未更新主题,看起来我在序列化主题时在 TeacherProfileDetails 中犯了一些错误

【问题讨论】:

    标签: django django-models django-rest-framework django-forms django-serializer


    【解决方案1】:

    SerializerMethodField只读的。因此,提供的序列化程序中的所有字段都是只读的。

    您可以改用SlugRelatedField 序列化程序,用于读取和写入:

    subjects = serializers.SlugRelatedField(
        many=True,
        slug_field='subject',
        queryset=Subject.objects.all(),
    )
    

    为了写得更好,在视图中添加逻辑以使subjects 包含独特的元素,甚至允许将patch 中的一个主题添加到已经存在的主题中。


    或者您可以使用两个单独的序列化程序 - 一个用于读取(当前一个),一个用于写入(只允许更改字段 - 它可以是 SlugRelatedField,甚至只是带有自定义 update() 方法逻辑的 ListField 等)。

    【讨论】:

    • 出现以下错误,我应该在哪里写 queryset ` super().__init__(**kwargs) File "/...../venv/lib/python3.7/site-packages/rest_framework /relations.py", line 108, in init '关系字段必须提供queryset 参数,' AssertionError: 关系字段必须提供queryset 参数,覆盖get_queryset,或设置只读=True。 `
    • 添加了查询集。
    • 现在可以了,我可以用同一个 SlugRelatedField 读写,那为什么你建议有单独的读写
    • 为了更具可读性/更明确。这里几乎所有字段都是只读的,乍一看很难猜到一个字段是用于写入的。
    • 另外,SlugRelatedField 在更高级的场景中可能不是很直观——更多相互依赖的字段等等。
    猜你喜欢
    • 1970-01-01
    • 2015-10-02
    • 1970-01-01
    • 2016-02-26
    • 2015-03-27
    • 2019-07-14
    • 2016-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多