I have a complex detail view where a lot of varied data is rendered dynamically. My model has hundreds of fields, many of which are related to one another. I would like to be able to group a number of these fields in order to do queries. Is there are way to do this?
In order to cherry-pick specific fields and group them, my current approach has been to use word extensions to the field names that is common for each group. For example, field names like:
ampicillin = models.CharField(...)
ciprofloxacin = models.CharField(...)
...
become:
ampicillin_antimicro = models.CharField(...)
ciprofloxacin_antimicro = models.CharField(...)
...
The idea is then to create a field name list and access specific groups of fields using a substring search. How am I to do this? Below is a summary of my attempts and issues so far.
Using _meta
I can access the raw model field name information using _meta:
all_fields = []
for field in MyModel._meta.fields:
all_fields.append(field)
This gives a list like:
[<django.db.models.fields.CharField: ampicillin_antimicro>,
<django.db.models.fields.CharField: ciprofloxacin_antimicro>, ...]
but I've not been able to figure out how to extract the information I need from this, however.
Using _meta and field.get_attname_column()[0]
I can make a list of field name objects as strings:
field_names = []
for field in MyModel._meta.fields:
newfield = field.get_attname_column()[0]
field_names.append(newfield)
This gives an appended list for field_names:
['ampicillin_antimicro', 'ciprofloxacin_antimicro', ...]
Adding a substring search allows me to get the subset of field names I want. For example, using the search string "antimic":
field_names = []
search_string = "antimic"
for field in Bacteria._meta.fields:
newfield = field.get_attname_column()[0]
if search_string in newfield:
field_names.append(newfield)
isolates the field names containing the 'group word extension' successfully. All good, except I can no longer access the actual value of the field names - just the field name itself. When the list is iterated over in the template only the field name is returned.
<li>
{% if field_names %}
<i style="color: blue"><b>A</b>ntibiotic tolerance:</i>
{% for f in field_names %}
{{f|default_if_none:''}}
{% endfor %}
{% endif %}
</li>
Using tuples and dictionaries
If I tuplify and dictify the list and try to use the resulting dictionary:
field_names = []
field_names_dict = dict(zip(field_names, field_names))
field_names_tuple = tuple(field_names_dict)
for key, val in field_names_tuple.items():
if val is not None:
field_names.append(val)
I still get the name as a result, not the value.
Hard-coded dictionaries
So far, the only thing that works is to hard-code a specific dictionary for each query in the detail view:
model = Model.objects.all()
antibiotics = []
antibiotics_dict = {'amp': model.ampicillin_antimicro,
'cipro': model.ciprofloxacin_antimicro, ...}
for key, val in antibiotics_dict.items():
if val is not None:
antibiotics.append(val)
Although this works fine, it gets complicated when the dictionaries get large and I don't like the idea of hard coding the key-value pairs. I feel like I'm very close to a solution but I'm obviously missing something because I'm a coding novice. Can someone help? Cheers.
The Shelvington Solution
Following Mr. Shelvington's suggestion, I have modified the code thus:
search_string = "antimic"
field_names = [f.name for f in Bacteria._meta.get_fields()
if search_string in f.name]
prelist = get_object_or_404(Bacteria.objects.values(*field_names), slug=slug)
for key, val in prelist.items():
if val is not None:
antibiotics = prelist
Note that there are only two variables (the substring and 'antibiotics'). The code is reusable for additional substring and dictionary creation. Then, I changed the template to suit:
<li>
{% if antibiotics %}
<i style="color: blue"><b>A</b>ntibiotic tolerance:</i>
{% for key, val in antibiotics.items %}
{{ val }}
{% endfor %}
{% endif %}
</li>
Additional note: I've iterated over the dictionary within the view so that the html text title disappears if values for the iteration are not found.