karlosss
karlosss

Reputation: 3155

Django REST Framework - access verbose_name of fields in ModelSerializer

Say I have the following Model:

class Book(Model):
    title = CharField(verbose_name="Book title")

and a ModelSerializer:

class BookSerializer(ModelSerializer):
    class Meta:
        model = Book
        fields = "__all__"

I would like to have a function get_verbose_names which returns verbose names of the fields in the model. This is what I have so far:

def get_verbose_names(serializer):
    return [field.label for field in serializer.get_fields().values()]

It seems to work fine but problems occur when I use this for the builtin User model. The only fields which work are ID, E-mail, Active, Superuser status and Staff status. The special thing about those fields is that their verbose name differs from their name. Django REST Framework is probably hiding a super-smart logic which checks this and refuses to set the field label to its verbose name in such cases.

Do Django REST Framework's fields have the verbose names hidden somewhere, or they don't copy them from the original Django model fields at all and I am screwed? Or will the trick be to override this logic? I tried and could not find it.

Upvotes: 1

Views: 1212

Answers (1)

karlosss
karlosss

Reputation: 3155

Django REST Framework really has the mentioned "super-smart logic". It is the function needs_label in utils.field_mapping:

def needs_label(model_field, field_name):
    """
    Returns `True` if the label based on the model's verbose name
    is not equal to the default label it would have based on it's field name.
    """
    default_label = field_name.replace('_', ' ').capitalize()
    return capfirst(model_field.verbose_name) != default_label

Probably the easiest way to bypass this annoying feature is to do this:

def get_verbose_names(serializer):
    return [field.label or name.replace("_", " ").capitalize() 
            for name, field in serializer.get_fields().items()]

Explained in words, check the field label and if none was auto-generated for it, use the needs_label logic to determine it.

Upvotes: 1

Related Questions