In Django REST Framework, how to get the “query pa

2019-08-19 01:34发布

问题:

I have an html page for listing the model "Descriptions", and at the end of it there's a button to go to the Description creation page, while sending the "character_id" that is intended to be a default initial value for the new Description (and I have set up the context so that the character_id would be there:

<!--The code for listing the Descriptions-->

<form action="{% url 'polls:description_detail_create_from_character' %}">
    <input type="hidden" value="{{ serializer.context.character_id }}" name="character_id">
    <input type="submit" value="New Description"/>
</form>

On the browser, if I click "New Description", it will bring me to:

http://localhost:8000/polls/description_detail_create_from_character/?character_id=3

However, then I don't know how can I get this "character_id" from description_detail_create_from_character (the next page)'s template. Thought it could be request.query_params.get('character_id', None), but doesn't work. By debugging, I can find the dict query_params, however, there's nothing in it.

Just don't know how can I get this character_id=3. It's nowhere to be found in the {% debug %} either. Is something more to be done in the Serializer? Or View? Is this ?character_id=3 here actually a query parameter here? If it is not then what it is?

Code:

Serializers.py:

# The serializer for the creation page
class DescriptionCreateFromCharacterSerializer(DescriptionSerializer):

    author = serializers.HiddenField(default=serializers.CreateOnlyDefault(DefaultFieldCurrentUser())) # This works btw, unlike the next one
    character = serializers.HiddenField(default=serializers.CreateOnlyDefault(DefaultFieldData(param_class=Character, param_key_field_name='character_id')))
    class Meta:
        model = Description
        fields = ['character', ...other fields]

# The helper class
class CustomDefaultField(object):
    def set_context(self, serializer_field):
        # setting field "type", calculated by other serializer fields
        self.request = serializer_field.context['request']


class DefaultFieldCurrentUser(CustomDefaultField):
    def __call__(self):
        return self.request.user


class DefaultFieldData(CustomDefaultField):
    def __init__(self, **kwargs):
        self.param_class = kwargs['param_class']
        self.param_key_field_name = kwargs['param_key_field_name']

    def __call__(self, **kwargs):
        key_value = self.request.query_params.get(self.param_key_field_name, None)
        if key_value:
            obj = get_object_or_None(self.param_class, id=key_value) # Always id for now
            if obj:
                return obj
        # Omitting some exception handling/assertion

views.py:

# The view for the create page
# Has a couple of hierarchy but I inlined all relevant/my stuff together

class DescriptionDetailCreateFromCharacterView(generics.CreateAPIView):
    permission_classes = [polls.permissions.NovelUserPermission]
    renderer_classes = [TemplateHTMLRenderer]

    url_to_redirect_reverse = ''

    def get(self, request):
        serializer = self.get_serializer()
        return Response({'serializer': serializer})

    def post(self, request):
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            if not self.url_to_redirect_reverse:
                return Response({'serializer': serializer}, status=status.HTTP_201_CREATED)
            else:
                return redirect(django.urls.reverse_lazy(self.url_to_redirect_reverse))
        else:
            return Response({'serializer': serializer}, status=status.HTTP_400_BAD_REQUEST)

    def get_serializer_class(self):
        return self._writable_serializer

    _model_class = Description
    _writable_serializer = DescriptionCreateFromCharacterSerializer
    _data_name_single = 'description'
    _data_name_plural = 'descriptions'

    template_name = 'polls/description_detail_create_from_character.html'
    url_to_redirect_reverse = 'polls:character_description_list.html'

    def get_queryset(self):
        return self.model_class.objects.all()