2

Yesterday I posted a question and found a solution to that problem. The solution however caused another issue.
Please take a look at the question, so I don't have to duplicate the contents.

In the Browsable API the value for 'class_name' is not displayed in the PUT form.

The rendered HTML looks like this:

<div class="form-group ">
  <label class="col-sm-2 control-label ">
    Class
  </label>

  <div class="col-sm-10">
    <input name="class_name" class="form-control" type="text">
  </div>
</div>

For the other fields it displays the value properly, for example:

<div class="form-group ">
  <label class="col-sm-2 control-label ">
    Order
  </label>

  <div class="col-sm-10">
    <input name="order" class="form-control" value="Carnivora" type="text">
  </div>
</div>

Here are screenshots illustrating the problem: enter image description here enter image description here

You can see that the value for the key "class" is there. The name of the input element as well the field name in the model is "class_name".

I poked around the source code and found out that the form is rendered in the file renderers.py in the following order:

  • In the class BrowsableAPIRenderer the method get_context creates the form and calls the method get_rendered_html_form.
  • The method get_rendered_html_form calls the method render_form_for_serializer.
  • The method render_form_for_serializer calls the method render of the class HTMLFormRenderer.

But I still don't know where to interfere and what should I change.

Also I tried to implement the method to_internal_value in the serializer, but this is only for the deserialization and has nothing to do with the form rendering.

Does anyone have an idea where the problem lies and what could be done?

UPDATE

I have created GitHub repo with the code. You can clone it or fork it and try to help me.
Many thanks!

cezar
  • 11,616
  • 6
  • 48
  • 84
  • 1
    Can you provide a repo to debug? The most obvious issue may be that the renderer code is trying to use `class_name` and not `class` will need to debug where you could override. So it would be easier if you provide a repo to debug – Tarun Lalwani Dec 08 '17 at 07:24
  • @TarunLalwani Thank you for your response! Yes, that's the issue, however I don't know where to intervene. Do you have any concrete proposal about the repo? Otherwise I'll put the code example on GitHub. – cezar Dec 08 '17 at 08:31
  • @TarunLalwani I created a repo on GitHub. Please check the updated answer. – cezar Dec 08 '17 at 11:41

1 Answers1

6

I worked out another way which seemed to be working fine for me. This was to define a class field for the serializer outside the class:

class SpeciesSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Species
        fields = (
            'url', 'id', 'canonical_name', 'slug',  'species', 'genus',
            'subfamily', 'family', 'order','class', 'phylum',
            'ncbi_id', 'ncbi_taxonomy',
        )
        read_only_fields = ('slug',)
        extra_kwargs = {
            'url': {'lookup_field': 'slug'}
        }

SpeciesSerializer._declared_fields["class"] = serializers.CharField(source="class_name")

After that both Raw Data and HTML Form look fine:

HTML Form

Raw Data

cezar
  • 11,616
  • 6
  • 48
  • 84
Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265
  • Excellent! This is a great solution. Very simple, straightforward and pythonic. Unfortunately I couldn't find any hint in the official documentation about this. Would you please add this answer also to my previous question, linked above. Here I can upvote only once. – cezar Dec 09 '17 at 08:01