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()