Django REST Framework doesn't display value in

2019-07-24 08:01发布

问题:

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:

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 has 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!

回答1:

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: