简体   繁体   中英

how to update OneToOneField / ForeignKey using ViewSet? Django

I am currently using restful and serializers to create and update my user. Somehow I am not able to update some of the fields if the field has to do with OneToOneField / ForeignKey.

in my models.py, my Student is actually connected to the django build in user model which includes the user's email and connected to the school model which has the name of the school

class Student(Model):
    user = OneToOneField(settings.AUTH_USER_MODEL, on_delete=CASCADE)

    date_of_birth = DateField(blank=True, null=True)

    student_name = CharField(max_length=256)
    school = ForeignKey(School,
                        on_delete=CASCADE,
                        related_name="%(class)ss",
                        related_query_name="%(class)s",
                        blank=True,
                        null=True)

in serializer.py I have

class StudentSerializer(ModelSerializer):
    user_email = SerializerMethodField()
    school_name = SerializerMethodField()

    class Meta:
        model = Student
        fields = (
            'user_email', 'student_name', 'phone', 'school_name')

    def get_user_email(self, obj):
        return obj.user.email

    def get_school_name(self, obj):
        return obj.school.school_name

    def create(self, validated_data):
        return Student.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.user.email = validated_data.get('user_email', instance.user.email)
        instance.student_name = validated_data.get('student_name', instance.student_name)
        instance.phone = validated_data.get('phone', instance.phone)
        instance.school.school_name = validated_data.get('school_name', instance.school.school_name)
        instance.save()
        return instance

in my view.py update function

class UserViewSet(ViewSet):
    queryset = Student.objects.all()

    def update(self, request, pk=None):
        student = get_object_or_404(self.queryset, pk=pk)
        serializer = StudentSerializer(student, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response({'status': True})
        return Response({'status': False, 'message': serializer.errors})

I am able to use the API view to pass in json and update the student_name and phone but as for the other two, user_email and school_name I am not able to update it. I don't get any error output when I submit the json though.

I realized the two fields that I am not able to update are because they OneToOneField / ForeignKey.

Can someone please give me a hand what I am missing here or what I can do to check?

Thanks in advance

I think your serializer isn't completed... the field of user and school is instance model, you need specific field in your serializer to implement the instance model, eg: with source='...' argument.

and example:

class VoteSerializer(serializers.ModelSerializer):
    # by `username`
    user = serializers.CharField(
        source='user.username',
        read_only=True
    )
    # by `pk/id`
    candidate = serializers.IntegerField(
        source='candidate.pk',
        read_only=True
    )

    class Meta:
        model = Vote
        fields = ('user', 'candidate', 'score')

    def create(self, validated_data):
        return Vote.objects.create(**validated_data)

and in your case, perhaps is like this;

class StudentSerializer(ModelSerializer):
    # by `pk/id` from the user
    user = serializers.IntegerField(
        source='user.pk',
        read_only=True
    )
    school = serializers.IntegerField(
        source='school.pk',
        read_only=True
    )

Since you are using SerializerMethodField which is readonly field ( docs ) for user_email and school_name so they won't be available in the validated_data .

Have you check the data you are receiving in validated_data

def update(self, instance, validated_data):
    print('++'*22, validated_data)
    return instance

The nested seriailzer / model / presentation actually helped me get the work done and pretty helpful.

An example is also provided here. http://www.django-rest-framework.org/api-guide/serializers/#writing-update-methods-for-nested-representations

the above is continued from http://www.django-rest-framework.org/api-guide/serializers/#writing-create-methods-for-nested-representations which contained how the nested serializer is being setup in the class and meta's fields

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM