Я пытаюсь создать основной шаблон для отображения значений полей выбранного экземпляра, наряду с их именами. Думайте о нем как просто стандартный вывод значений того экземпляра в формате таблицы с именем поля (verbose_name конкретно, если указано на поле) в первом столбце и значении того поля во втором столбце.
Например, скажем, у нас есть следующее образцовое определение:
class Client(Model):
name = CharField(max_length=150)
email = EmailField(max_length=100, verbose_name="E-mail")
Я хотел бы, чтобы это было произведено в шаблоне как так (примите экземпляр с данными значениями):
Field Name Field Value
---------- -----------
Name Wayne Koorts
E-mail waynes@email.com
То, чего я пытаюсь достигнуть, является способностью передать экземпляр модели к шаблону и смочь выполнить итерации по нему динамично в шаблоне, чем-то вроде этого:
<table>
{% for field in fields %}
<tr>
<td>{{ field.name }}</td>
<td>{{ field.value }}</td>
</tr>
{% endfor %}
</table>
Существует ли аккуратный, "Django-утвержденный" способ сделать это? Это походит на очень общую задачу, и я должен буду часто делать это для этого конкретного проекта.
Aviad P. является правильным. Это то, что я делаю:
<Border Background="Transparent">
<Path ... />
</Border>
Это работает, потому что, когда «ударить тестирование», чтобы определить, где можно регулировать щелчок мышью, «прозрачная» щетка рассмотрена так, как если бы это был обычный цвет.
-121--2818442- Model._Meta.get_All_Field_Names ()
предоставит вам все имена поля модели, затем вы можете использовать Model._Meta.get_field ()
для работы На название Verbose и Getattr (Model_Instance, 'field_name')
, чтобы получить значение из модели.
Примечание: Model._Meta.get_All_Field_Names ()
устарели в Django 1.9. Вместо этого используйте Model._meta.get_fields ()
, чтобы получить поля модели и поле
, чтобы получить каждое имя поля.
Я придумал следующий метод, который работает для меня, потому что в каждом случае модель будет связана с ним модификация.
def GetModelData(form, fields):
"""
Extract data from the bound form model instance and return a
dictionary that is easily usable in templates with the actual
field verbose name as the label, e.g.
model_data{"Address line 1": "32 Memory lane",
"Address line 2": "Brainville",
"Phone": "0212378492"}
This way, the template has an ordered list that can be easily
presented in tabular form.
"""
model_data = {}
for field in fields:
model_data[form[field].label] = eval("form.data.%s" % form[field].name)
return model_data
@login_required
def clients_view(request, client_id):
client = Client.objects.get(id=client_id)
form = AddClientForm(client)
fields = ("address1", "address2", "address3", "address4",
"phone", "fax", "mobile", "email")
model_data = GetModelData(form, fields)
template_vars = RequestContext(request,
{
"client": client,
"model_data": model_data
}
)
return render_to_response("clients-view.html", template_vars)
Вот экстракт из шаблона, который я использую для этого конкретного представления:
<table class="client-view">
<tbody>
{% for field, value in model_data.items %}
<tr>
<td class="field-name">{{ field }}</td><td>{{ value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
Приятная вещь об этом методе состоит в том, что я могу выбрать на шаблонном шаблоне, который я хотел бы отобразить Полевые этикетки, используя кортеж, передавали в GetModeldata и указание имени поля. Это также позволяет мне исключить определенные поля (например, пользовательский внешний ключ) как только имена поля, передаваемые через кортеж, встроены в окончательный словарь.
Я не собираюсь принять это как ответ, потому что я уверен, что кто-то может придумать чем-то более «Djangonic»: -)
Обновление: Я выбираю это как окончательный ответ, потому что Это самый простой из тех, кто дал, что делает то, что мне нужно. Спасибо всем, кто внес ответы.
Да, это не красиво, вам придется сделать свою собственную обертку. Посмотрите на встроенные PATCENROWSE приложение, которое имеет все функциональные возможности, которые вам нужны действительно.
Вот еще один подход, использующий метод моделирования. Эта версия разрешает поля пикилиста/выбора, пропускает пустые поля и позволяет исключить определенные поля.
def get_all_fields(self):
"""Returns a list of all field names on the instance."""
fields = []
for f in self._meta.fields:
fname = f.name
# resolve picklists/choices, with get_xyz_display() function
get_choice = 'get_'+fname+'_display'
if hasattr(self, get_choice):
value = getattr(self, get_choice)()
else:
try:
value = getattr(self, fname)
except AttributeError:
value = None
# only display fields with values and skip some fields entirely
if f.editable and value and f.name not in ('id', 'status', 'workshop', 'user', 'complete') :
fields.append(
{
'label':f.verbose_name,
'name':f.name,
'value':value,
}
)
return fields
Затем в вашем шаблоне:
{% for f in app.get_all_fields %}
<dt>{{f.label|capfirst}}</dt>
<dd>
{{f.value|escape|urlize|linebreaks}}
</dd>
{% endfor %}
Это можно считать взломом, но я сделал это до того, как использовал modelform_factory для преобразования экземпляра модели в форму.
Класс Form содержит намного больше информации, которую очень легко перебирать, и он будет служить той же цели за счет немного больших накладных расходов. Если размеры вашего набора относительно малы, я думаю, что влияние на производительность будет незначительным.
Одним из преимуществ, помимо удобства, конечно же, является то, что вы можете легко превратить таблицу в редактируемую сетку данных позже.
Вы можете использовать сериализатор набора запросов Django to-python .
Просто поместите следующий код в ваше представление:
from django.core import serializers
data = serializers.serialize( "python", SomeModel.objects.all() )
И затем в шаблоне:
{% for instance in data %}
{% for field, value in instance.fields.items %}
{{ field }}: {{ value }}
{% endfor %}
{% endfor %}
Его большим преимуществом является тот факт, что он обрабатывает поля отношений.
Для подмножества полей попробуйте:
data = serializers.serialize('python', SomeModel.objects.all(), fields=('name','size'))
Наконец-то нашел хорошее решение этой проблемы в списке рассылки разработчиков :
В представлении добавьте:
from django.forms.models import model_to_dict
def show(request, object_id):
object = FooForm(data=model_to_dict(Foo.objects.get(pk=object_id)))
return render_to_response('foo/foo_detail.html', {'object': object})
в шаблоне добавьте:
{% for field in object %}
<li><b>{{ field.label }}:</b> {{ field.data }}</li>
{% endfor %}