我有一个复杂的详细视图,其中动态呈现了许多不同的数据。我的模型有数百个字段,其中许多是相互关联的。我希望能够对这些字段中的一些进行分组以进行查询。有没有办法做到这一点?
为了挑选特定字段并将它们分组,我目前的方法是对每个组通用的字段名称使用词扩展。例如,字段名称如下:
ampicillin = models.CharField(...)
ciprofloxacin = models.CharField(...)
...
变得:
ampicillin_antimicro = models.CharField(...)
ciprofloxacin_antimicro = models.CharField(...)
...
然后的想法是创建一个字段名称列表并使用子字符串搜索访问特定的字段组。我该怎么做?以下是我迄今为止的尝试和问题的摘要。
使用 _meta
我可以使用 _meta 访问原始模型字段名称信息:
all_fields = []
for field in MyModel._meta.fields:
all_fields.append(field)
这给出了一个类似的列表:
[<django.db.models.fields.CharField: ampicillin_antimicro>,
<django.db.models.fields.CharField: ciprofloxacin_antimicro>, ...]
但是我无法弄清楚如何从中提取我需要的信息。
使用 _meta 和 field.get_attname_column()[0]
我可以将字段名称对象列表作为字符串:
field_names = []
for field in MyModel._meta.fields:
newfield = field.get_attname_column()[0]
field_names.append(newfield)
这给出了 field_names 的附加列表:
['ampicillin_antimicro', 'ciprofloxacin_antimicro', ...]
添加子字符串搜索可以让我得到我想要的字段名称的子集。例如,使用搜索字符串“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)
成功隔离包含“组词扩展”的字段名称。一切都很好,除了我不能再访问字段名称的实际值 - 只是字段名称本身。在模板中迭代列表时,仅返回字段名称。
<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>
使用元组和字典
如果我对列表进行 tuplify 和 dictify 并尝试使用生成的字典:
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)
结果,我仍然得到名称,而不是值。
硬编码字典
到目前为止,唯一可行的方法是在详细视图中为每个查询硬编码一个特定的字典:
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)
虽然这很好用,但当字典变大时它会变得复杂,而且我不喜欢硬编码键值对的想法。我觉得我非常接近解决方案,但我显然错过了一些东西,因为我是编码新手。有人可以帮忙吗?干杯。
谢尔文顿解决方案
按照谢尔文顿先生的建议,我修改了代码:
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
请注意,只有两个变量(子字符串和“抗生素”)。该代码可重复用于其他子字符串和字典的创建。然后,我更改了模板以适应:
<li>
{% if antibiotics %}
<i style="color: blue"><b>A</b>ntibiotic tolerance:</i>
{% for key, val in antibiotics.items %}
{{ val }}
{% endfor %}
{% endif %}
</li>
附加说明:我已经迭代了视图中的字典,因此如果未找到迭代的值,则 html 文本标题会消失。