简体   繁体   中英

Validating a choice field with ModelSerializer with Django

I have a model BaseUser which inherits from AbstractUser and has two additional fields: complex_list and active_complex. complex_list is a ManyToManyField connected to the BaseComplex model through an enrollment table.

I want the default value for active_complex to be null which can be taken care of at the model initiation. I also need the user to be able to choose the active_complex only from the values within the complex_list. For that, I tried to use a customized ModelSerializer:

from rest_framework import serializers
from .models import BaseUser



class ActiveComplexSerializer(serializers.ModelSerializer):
    this_user = serializers.SerializerMethodField('get_this_user')

    choice =[]
    qs = BaseUser.objects.get(username = this_user)
    for cmplx in qs.complex_list:
        choice.append((cmplx.id, cmplx.name))

    active_complex = serializers.ChoiceField(choices = choice)


    class Meta:
        model = BaseUser
        fields = ('active_complex')

    def get_this_user(self, request):

        return request.user

I know I'm doing something wrong because I get a query not found ERROR. I would appreciate it if you could correct this or suggest a better approach to achieving the same goal.

The issue with the current code is that when you're calling

qs = BaseUser.objects.get(username = this_user)

this_user is not bound to any specific value. This code runs only once when the Class is first initialized, not on every new instance of the class.

You instead want to get the user when the serializer class is initialized and then populate the choices.

Here's a rough change, I have not tested this, but it should more or less work.

class ActiveComplexSerializer(serializers.ModelSerializer):
    this_user = serializers.SerializerMethodField('get_this_user')
    active_complex = serializers.ChoiceField(choices=[])

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        choice =[]
        qs = BaseUser.objects.get(username = self.fields['this_user'])
        for cmplx in qs.complex_list:
            choice.append((cmplx.id, cmplx.name))
        self.fields['active_complex'].choices = choice

    class Meta:
        model = BaseUser
        fields = ('active_complex')

    def get_this_user(self, request):
        return request.user

Also on a side note check out get_user_model() from https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#django.contrib.auth.get_user_model - it is preferred to use that function instead of direclty importing user model.

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