Rsnake
Rsnake

Reputation: 11

How to access a field name in Django model via the verbose name or Column name

I have the verbose name or column name of a model and I would like to get the corresponding field name. I'm able to access all the field names by using _meta..., but I only want to access a particular field name based on the verbose name.

I would like to plug in the verbose name or column name and get back what the field name is. All the examples that I've found you can only enter the field name in the Model._meta.get_field('fieldname') and not the verbose name to get whatever the field name is.

res = Model._meta.get_field('test_field').verbose_name
res returns  'Test Field'

res = Model._meta.get_field('test_field').name
res returns 'test_field'

If I enter the verbose name for ex:

res = Model._meta.get_field('Test Field').name   

I get an error raise FieldDoesNotExist KeyError" 'Test Field'

I would like the output to be the field name 'test_field'

Upvotes: 1

Views: 2110

Answers (2)

Jamie Counsell
Jamie Counsell

Reputation: 8123

I agree with Willem that there are issues here with reliability and determistic behaviour, but something like this would work:

{field.verbose_name: field for field in model._meta.get_fields()}['Test Field']

Upvotes: 1

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476750

A problem might be here that multiple fields can have the same verbose_name, hence it is not a good identifier. It is not the task of a verbose name to act as an identifier anyway, these are used, as the documentation says to:

A human-readable name for the field. If the verbose name isn't given, Django will automatically create it using the field's attribute name, converting underscores to spaces.

We can make a function that does this, like:

def get_field_from_verbose(meta, verbose_name):
    try:
        return next(f for f in _meta.get_fields() if f.verbose_name == verbose_name)
    except:
        raise KeyError(verbose_name)

We can let it work with multiple names of a field, like:

def get_field_from_verbose(meta, verbose_name):
    try:
        return next(
            f for f in _meta.get_fields()
            if f.verbose_name in (f.name, f.verbose_name, f.db_column)
        )
    except:
        raise KeyError(verbose_name)

But this even looks more problematic, since now the database column name of one field can be equal to the verbose name of another field, making it even more non-sensical.

and thus call it with:

get_field_from_verbose(Model._meta, 'Test Field')

It will raise a KeyError as well, given no such field can be found.

After a user selects a check box that displays the verbose name I'm using that name to access the fieldname to use in a query.

If this is more the sake of user interface, you should attack the field name as value to the checkbox, and the verbose name as "label". Like for example:

<input type="checkbox" name="sel_fields[]" value="fieldname1">Verbose fieldname 1<br>
<input type="checkbox" name="sel_fields[]" value="fieldname2">Verbose fieldname 2<br>
<input type="checkbox" name="sel_fields[]" value="fieldname3">Verbose fieldname 3<br> 

Here the user will thus see Verbose fieldname 1 for the first checkbox, but if the user selects that checkbox, and hits the submit button, the view will receive the fieldname1 value, so the real name of that field.

This is in essence what Django does when you for example use a ModelChoiceField in a form: it presents the items nicely, but behind the curtains, it passes the primary key as value, and thus when one submits the form, we receive the primary key of the selected item back, not the textual representation of that object.

Upvotes: 2

Related Questions