我想我已经阅读了大部分“相关/重复”的问题(例如verbose from template-tag,iterate over field names,iterate through models和few,{{3 }})...)
不幸的是,我担心我需要一些手握......因为我是django n00b并且似乎无法使它工作。这是我想要的结果:
<!-- this in some section of the template -->
First Name : . Joe
Last Name : .. Blogs
<!-- this in another section -->
City: ....... Xanadu
Country: ..... Mongolia
Occupation: .. Programmer
<!-- this in another section of the template -->
Age: ......... 75
Height: ...... 180 cm
Eye color: .. red
有4个或5个部分和10个可能的字段,我不想只做
{% if data.first_name %}
First Name: {{ data.first_name }}
{% endif %}
四十次! : - / ...所以这是(大致)我的尝试:
model.py
class GenericPerson(models.Model):
first_name = models.CharField(_('First Name'),
max_length = 200,
help_text = _('What is your name?'))
last_name = models.CharField(_('Last Name'),
max_length = 200,
help_text = _('What is your name?'))
etc, etc ...
class Meta:
abstract = True
class Person(GenericPerson):
age_in_years = models.PositiveIntegerField(_('Age'),
null = True,
blank = True,
help_text=_('When was you born?, mate'))
location = models.ForeignKey(GeographicalProfile,
verbose_name=_('geolocations'),
null = True,
blank = True)
height = ... etc, etc.
views.py
...
try:
person = Person.objects.filter(pk=product_id)
except Person.DoesNotExist:
raise Http404
generaldata = person.values('first_name',
'last_name',
etc, etc,
)[0]
localdata = person.values('city',
'country',
etc, etc
)[0]
physicaldata = person.values('age',
'height',
'eye_color',
etc, etc
)[0]
extra_context[data] = generaldata
extra_context[loc] = localdata
extra_context[phys] = physicaldata
return render_to_response(template_name, extra_context ,context_instance=RequestContext(request))
使用该视图,我可以
template.html
{% for p in phys.items %}
<ul>
{% if p.1 %}
<li>{{p.0}} : {{p.1}}</li>
{% endif %}
</ul>
{% endfor %}
适用于不同的部分。但是这会将字段作为age_in_years,eye_color(而不是名称)返回。好的,所以从上面的帖子中我创建了一个自定义模板标签,
from django import template
register = template.Library()
@register.filter
def get_name(object):
return object._meta.verbose_name # put here whatever you would like to return
register.tag('get_name', get_name)
,将其加载到模板{%load person_extras%}中,现在......我已经盲目地在模板中的任何地方使用此{{something | get_object_name}} ...但是我的蛮力没有理解就给了我:
'str'对象没有属性'_meta'
'list'对象没有属性'_meta'
'tuple'对象没有属性'_meta'
'dict'对象没有属性'_meta'
'ValuesQuerySet'对象没有属性'_meta'
那么,我在哪里使用这个模板标签?或者如何修改我的视图以在for循环中使用此模板标记?
感谢您的见解
答案 0 :(得分:3)
当您致电person = Person.objects.filter(pk=product_id)
时,将返回QuerySet
个People
个对象。当您随后在此查询集上使用values
时 - 用文档的话语:
返回一个ValuesQuerySet - 一个QuerySet子类,当用作可迭代的而不是模型实例对象时返回字典。
所以基本上,在您尝试调用模板标记的模板中,您试图在字典对象而不是._meta.verbose_name
对象上调用Person
,这将无效。
所以,你可以做的只是将普通的查询集传递给模板,然后限制你想要为每个部分显示的字段(一般,本地,物理),并使用一些模板过滤器来帮助你。如下所示:
try:
people = Person.objects.filter(pk=product_id)
except Person.DoesNotExist:
raise Http404
extra_context = {
'people' : people,
'general_fieldnames' : ['first_name', 'last_name' ...],
'local_fieldnames' : ['age', 'weight' ...],
'physical_fieldnames' : ['age', 'height' ...],
}
return render_to_response(template_name, extra_context
,context_instance=RequestContext(request))
虽然存在问题(如您所知),因为没有简单的方法来遍历对象的字段,或者获取其详细的名称。相反,我们可以遍历我们的physical_fieldnames
列表,从对象中获取相应的字段,并使用过滤器来表示详细的名称。
from django import template
register = template.Library()
@register.filter
def get_field_value(obj, field_name):
return getattr(obj, field_name, None)
@register.filter
def get_verbose_name(obj, field_name):
return obj._meta.get_field(field_name).verbose_name
register.tag('get_verbose_name', get_verbose_name)
register.tag('get_field_value', get_field_value)
现在在模板中
{% for person in people %}
<h1>General</h1>
<ul>
{% for field_name in general_fieldnames %}
{{ person|get_verbose_name:field_name }} : {{ person|get_field_value:field_name }}
{% endfor %}
</ul>
{% endfor %}
...