Выполните итерации по образцовым именам поля экземпляра и значениям в шаблоне

Я пытаюсь создать основной шаблон для отображения значений полей выбранного экземпляра, наряду с их именами. Думайте о нем как просто стандартный вывод значений того экземпляра в формате таблицы с именем поля (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-утвержденный" способ сделать это? Это походит на очень общую задачу, и я должен буду часто делать это для этого конкретного проекта.

174
задан Wayne Koorts 2 October 2014 в 11:54
поделиться

7 ответов

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 () , чтобы получить поля модели и поле , чтобы получить каждое имя поля.

166
ответ дан 23 November 2019 в 20:29
поделиться

Я придумал следующий метод, который работает для меня, потому что в каждом случае модель будет связана с ним модификация.

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»: -)

Обновление: Я выбираю это как окончательный ответ, потому что Это самый простой из тех, кто дал, что делает то, что мне нужно. Спасибо всем, кто внес ответы.

4
ответ дан 23 November 2019 в 20:29
поделиться

Да, это не красиво, вам придется сделать свою собственную обертку. Посмотрите на встроенные PATCENROWSE приложение, которое имеет все функциональные возможности, которые вам нужны действительно.

4
ответ дан 23 November 2019 в 20:29
поделиться

Вот еще один подход, использующий метод моделирования. Эта версия разрешает поля пикилиста/выбора, пропускает пустые поля и позволяет исключить определенные поля.

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 %}
17
ответ дан 23 November 2019 в 20:29
поделиться

Это можно считать взломом, но я сделал это до того, как использовал modelform_factory для преобразования экземпляра модели в форму.

Класс Form содержит намного больше информации, которую очень легко перебирать, и он будет служить той же цели за счет немного больших накладных расходов. Если размеры вашего набора относительно малы, я думаю, что влияние на производительность будет незначительным.

Одним из преимуществ, помимо удобства, конечно же, является то, что вы можете легко превратить таблицу в редактируемую сетку данных позже.

4
ответ дан 23 November 2019 в 20:29
поделиться

Вы можете использовать сериализатор набора запросов 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'))
69
ответ дан 23 November 2019 в 20:29
поделиться

Наконец-то нашел хорошее решение этой проблемы в списке рассылки разработчиков :

В представлении добавьте:

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 %}
66
ответ дан 23 November 2019 в 20:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: