Перебирать имена и значения полей экземпляра модели в шаблоне


183

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

Есть ли аккуратный «одобренный Джанго» способ сделать это? Кажется, это очень распространенная задача, и мне нужно будет делать ее часто для этого конкретного проекта.

Ответы:


171

model._meta.get_all_field_names()даст вам все имена полей модели, затем вы сможете использовать model._meta.get_field()ее getattr(model_instance, 'field_name')для перехода к подробному имени и для получения значения из модели.

ПРИМЕЧАНИЕ: model._meta.get_all_field_names()устарело в django 1.9. Вместо этого используйте, model._meta.get_fields()чтобы получить поля модели и field.nameполучить имя каждого поля.


2
Это все еще очень ручная работа, и мне нужно создать мета-объект в виде, который я затем передам в шаблон, что является скорее хаком, чем мне бы хотелось. Конечно, должен быть аккуратный путь?
Уэйн Коортс

2
Вы можете инкапсулировать все это в классе, как это делает ModelForm.
Игнасио Васкес-Абрамс

18
Я не верю, что вы можете вызывать любые _ методы в шаблонах.
Иссак Келли

2
Это работает, но вы не должны зависеть от частного API (поскольку он префикс «_») для достижения этого. Проблема с использованием частного API заключается в том, что частные методы не гарантируют работу от версии к версии.
Деви

1
Я думаю, что этот метод не должен быть предпочтительным, так как мы не должны получать доступ к атрибутам, начинающимся с подчеркивания из шаблонов
GP92

72

Вы можете использовать Джанго для 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'))

Это круто - но с этим методом, как можно ограничить результаты только определенными полями?
Герман Шааф

2
Это должно быть окончательным ответом, обрабатывает внешние ключи и никаких частных вызовов API. Отличный ответ, спасибо.
Юнти

3
Нет необходимости использовать сериализацию. Вы можете использовать метод values ​​() набора запросов , который возвращает словарь. Кроме того, этот метод принимает список полей для поднабора. Смотрите ссылку . Смотрите мой полный ответ.
user3062149

Можем ли мы обновить это, чтобы отправить только в .fields вместо того, чтобы обрабатывать его в цикле? Я не хочу раскрывать названия моделей / таблиц
Loser Coder

Позволяет ли этот метод verbose_nameпередавать поля?
alias51

71

Наконец-то нашел хорошее решение для этого в списке рассылки dev :

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

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 %}

1
Хорошее решение, но не очень универсальное, так как оно возвращает не model_to_dict для полей ForeignKey, а результат Unicode , поэтому вы не можете легко сериализовать сложный объект в dict
Vestel

22
Опасно переопределить объект, вы должны использовать другое допустимое имя.
Эмиль Стенстрём

Спасибо! Я заменил Django model_to_dict (), чтобы иметь возможность обрабатывать ForeignKey. Пожалуйста, смотрите мой отдельный ответ (я удалил свой предыдущий комментарий, так как комментарии не поддерживают форматирование кода. Извините, я не знал этого.)
Магнус Густавссон

2
Предполагая , что здесь FooFormесть ModelForm, не будет ли проще просто сделать: FooForm(instance=Foo.objects.get(pk=object_id)))?
Беруик

Любая идея, как вы будете отображать только редактируемые поля с этим методом?
alias51

22

В свете выпуска Django 1.8 (и формализации API Model _meta , я подумал, что обновлю это более поздним ответом.

Предполагая ту же модель:

class Client(Model):
    name = CharField(max_length=150)
    email = EmailField(max_length=100, verbose_name="E-mail")

Джанго <= 1,7

fields = [(f.verbose_name, f.name) for f in Client._meta.fields]
>>> fields
[(u'ID', u'id'), (u'name', u'name'), (u'E-mail', u'email')]

Django 1.8+ (формализованная модель _meta API)

Изменено в Django 1.8:

Model _metaAPI всегда существовал как внутренний Django, но не был официально задокументирован и поддержан. В рамках усилий по обеспечению доступности этого API некоторые из уже существующих точек входа API немного изменились. Было предоставлено руководство по миграции, чтобы помочь преобразовать ваш код в новый официальный API.

В приведенном ниже примере мы будем использовать формализованный метод для извлечения всех экземпляров полей модели через Client._meta.get_fields():

fields = [(f.verbose_name, f.name) for f in Client._meta.get_fields()]
>>> fields
[(u'ID', u'id'), (u'name', u'name'), (u'E-mail', u'email')]

На самом деле, мне было доведено до сведения, что вышесказанное немного за борт для того, что было необходимо (я согласен!). Простое лучше, чем сложное. Я оставляю выше для справки. Однако для отображения в шаблоне лучшим способом будет использование ModelForm и передача экземпляра. Вы можете выполнить итерацию по форме (эквивалент итерации по каждому из полей формы) и использовать атрибут label для получения verbose_name поля модели, а также использовать метод value для получения значения:

from django.forms import ModelForm
from django.shortcuts import get_object_or_404, render
from .models import Client

def my_view(request, pk):
    instance = get_object_or_404(Client, pk=pk)
    
    class ClientForm(ModelForm):
        class Meta:
            model = Client
            fields = ('name', 'email')

    form = ClientForm(instance=instance)

    return render(
        request, 
        template_name='template.html',
        {'form': form}
    )

Теперь мы визуализируем поля в шаблоне:

<table>
    <thead>
        {% for field in form %}
            <th>{{ field.label }}</th>
        {% endfor %}
    </thead>
    <tbody>
        <tr>
            {% for field in form %}
                <td>{{ field.value|default_if_none:'' }}</td>
            {% endfor %}
        </tr>
    </tbody>
</table>
 

2
Было бы здорово, если бы вы изменили свой ответ, чтобы показать способ «> 1.8» для помещения полей модели в шаблон. В данный момент ваш ответ не дает прямого ответа на вопрос; он показывает, как получить поля модели в оболочке.
Эшер

@Escher - обновил ответ! Спасибо за предложение. Дайте мне знать, если я что-то пропустил / что-то испортил!
Майкл Б

Upvoted. Я отредактировал, чтобы включить печать значений, а также имена полей. Посмотрите, что вы думаете.
Эшер

Где вы печатаете значения? Я вижу только печать имени и verbose_name?
Доктор Эрни

@MichaelB Хм. Я не смог заставить "field.value" работать; поля выглядят как поля базы данных, а не как фактические данные столбца. Мне пришлось использовать фильтр, который называется getattr (объект, имя). Какая версия Django подходит вам?
Доктор Эрни

19

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

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 %}

3
зачем тебе это except User.DoesNotExist:?
Семь Земель

Я был бы склонен использовать AttributeError вместо User.DoesNotExist - я не могу понять, почему это вызвало бы User.DoesNotExist.
Askvictor

Также может быть лучше использовать self._meta.get_fields (), так как это официально представлено в django 1.8+. Тем не менее, в итоге вы получите отношения в коде, которые вы должны отфильтровать, проверив f.is_relation
askvictor

Я отредактировал ответ, чтобы использовать AttributeError вместо User.DoesNotExist (который остался от моей первоначальной реализации). Спасибо. Я держусь, _meta.get_fields()пока не смогу проверить это.
Шейкер

13

Хорошо, я знаю, что уже немного поздно, но, поскольку я наткнулся на это, прежде чем найти правильный ответ, может кто-то другой.

Из документации Django :

# This list contains a Blog object.
>>> Blog.objects.filter(name__startswith='Beatles')
[<Blog: Beatles Blog>]

# This list contains a dictionary.
>>> Blog.objects.filter(name__startswith='Beatles').values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]

Мне нравится этот ответ. Если ваш запрос возвращает более одной записи, и вы хотите только самую последнюю, сделайте следующее. 1. Убедитесь , что у вас есть ordering = ['-id']в class Meta:вашем объекте models.py. 2. затем используйтеBlog.objects.filter(name__startswith='Beatles').values()[0]
Семь Земель

Умная идея Но если у вас уже есть modelобъект, вы снова попадете в базу данных, чтобы получить поля. Любой способ обойти это?
frnhr

@ user1763732 просто проверьте документацию для QuerySet: docs.djangoproject.com/en/dev/ref/models/querysets
olofom

9

Вы можете использовать values()метод a queryset, который возвращает словарь. Кроме того, этот метод принимает список полей для поднабора. values()Метод не будет работать с get(), так что вы должны использовать filter()(обратитесь к API QuerySet ).

В view...

def show(request, object_id):
   object = Foo.objects.filter(id=object_id).values()[0]
   return render_to_response('detail.html', {'object': object})

В detail.html...

<ul>
   {% for key, value in object.items %}
        <li><b>{{ key }}:</b> {{ value }}</li>
   {% endfor %}
</ul>

Для коллекции экземпляров, возвращаемых фильтром:

   object = Foo.objects.filter(id=object_id).values() # no [0]

В detail.html ...

{% for instance in object %}
<h1>{{ instance.id }}</h1>
<ul>
    {% for key, value in instance.items %}
        <li><b>{{ key }}:</b>  {{ value }}</li>
    {% endfor %}
</ul>
{% endfor %}

Это потрясающе, спасибо! У меня вопрос, не могли бы вы мне помочь; Я помещаю все данные об объектах в a table, поэтому мне нужен каждый keys в th. Как мне это сделать без петель? Просто возьмите любой экземпляр объекта и выполните итерацию по нему для keys? В настоящее время я отдельно схожу model_to_dict(Model())за th, но я думаю, что это ненужный экземпляр объекта.
Oxwivi

Фантастический ответ. Лично я использовал это как в виде списка, так и в подробном виде. Представление списка в значительной степени очевидно для реализации, но в представлении подробностей я переопределяю get_objectпредставление подробностей (искаженное из-за ограничения встроенного кода в комментариях, и не чувствую, что этого достаточно для его собственного ответа, учитывая, насколько насыщен этот поток): def get_object(self, **kwargs): obj = super().get_object(**kwargs) obj = obj.__class__.objects.filter(pk=obj.pk).values()[0] return obj
sdconrox

Как бы вы добавили obj.get_absolute_urlв этот список, не дублируя строки?
alias51

8

Я использовал https://stackoverflow.com/a/3431104/2022534, но заменил Django's model_to_dict () этим, чтобы иметь возможность обрабатывать ForeignKey:

def model_to_dict(instance):
    data = {}
    for field in instance._meta.fields:
        data[field.name] = field.value_from_object(instance)
        if isinstance(field, ForeignKey):
            data[field.name] = field.rel.to.objects.get(pk=data[field.name])
    return data

Пожалуйста, обратите внимание, что я немного упростил это, удалив части оригинала, которые мне не нужны. Возможно, вы захотите вернуть их обратно.


8

Вы можете иметь форму сделать работу за вас.

def my_model_view(request, mymodel_id):
    class MyModelForm(forms.ModelForm):
        class Meta:
            model = MyModel

    model = get_object_or_404(MyModel, pk=mymodel_id)
    form = MyModelForm(instance=model)
    return render(request, 'model.html', { 'form': form})

Тогда в шаблоне:

<table>
    {% for field in form %}
        <tr>
            <td>{{ field.name }}</td>
            <td>{{ field.value }}</td>
        </tr>
    {% endfor %}
</table>

3
Этот метод (используется в DetailView) хорошо работает для меня. Тем не менее, вы можете использовать field.labelвместо field.name.
Дэвид Кейн

7

Там действительно должен быть встроенный способ сделать это. Я написал эту утилиту, build_pretty_data_viewкоторая берет объект модели и экземпляр формы (форму, основанную на вашей модели) и возвращаетSortedDict .

Преимущества этого решения включают в себя:

  • Сохраняет порядок, используя встроенный Django SortedDict.
  • Когда пытается получить метку / verbose_name, но возвращается к имени поля, если оно не определено.
  • Также будет необязательно принимать exclude()список имен полей, чтобы исключить определенные поля.
  • Если ваш класс формы включает в себя Meta: exclude(), но вы все еще хотите вернуть значения, добавьте эти поля в необязательный append()список.

Чтобы использовать это решение, сначала добавьте этот файл / функцию куда-нибудь, а затем импортируйте его в свой views.py.

utils.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: ai ts=4 sts=4 et sw=4
from django.utils.datastructures import SortedDict


def build_pretty_data_view(form_instance, model_object, exclude=(), append=()):
    i=0
    sd=SortedDict()

    for j in append:
        try:
            sdvalue={'label':j.capitalize(),
                     'fieldvalue':model_object.__getattribute__(j)}
            sd.insert(i, j, sdvalue)
            i+=1
        except(AttributeError):
            pass

    for k,v in form_instance.fields.items():
        sdvalue={'label':"", 'fieldvalue':""}
        if not exclude.__contains__(k):
            if v.label is not None:
                sdvalue = {'label':v.label,
                           'fieldvalue': model_object.__getattribute__(k)}
            else:
                sdvalue = {'label':k,
                           'fieldvalue': model_object.__getattribute__(k)}
            sd.insert(i, k, sdvalue)
            i+=1
    return sd

Так что теперь views.pyвы можете сделать что-то вроде этого

from django.shortcuts import render_to_response
from django.template import RequestContext
from utils import build_pretty_data_view
from models import Blog
from forms import BlogForm
.
.
def my_view(request):
   b=Blog.objects.get(pk=1)
   bf=BlogForm(instance=b)
   data=build_pretty_data_view(form_instance=bf, model_object=b,
                        exclude=('number_of_comments', 'number_of_likes'),
                        append=('user',))

   return render_to_response('my-template.html',
                          RequestContext(request,
                                         {'data':data,}))

Теперь в вашем my-template.htmlшаблоне вы можете перебирать данные так ...

{% for field,value in data.items %}

    <p>{{ field }} : {{value.label}}: {{value.fieldvalue}}</p>

{% endfor %}

Удачи. Надеюсь, это поможет кому-то!


7

Ниже мой, вдохновленный Шакером get_all_fields . Он получает диктат одного экземпляра модели, если встречается поле отношения, а затем рекурсивно присваивается значение поля дикту.

def to_dict(obj, exclude=[]):
    """生成一个 dict, 递归包含一个 model instance 数据.
    """
    tree = {}
    for field in obj._meta.fields + obj._meta.many_to_many:
        if field.name in exclude or \
           '%s.%s' % (type(obj).__name__, field.name) in exclude:
            continue

        try :
            value = getattr(obj, field.name)
        except obj.DoesNotExist:
            value = None

        if type(field) in [ForeignKey, OneToOneField]:
            tree[field.name] = to_dict(value, exclude=exclude)
        elif isinstance(field, ManyToManyField):
            vs = []
            for v in value.all():
                vs.append(to_dict(v, exclude=exclude))
            tree[field.name] = vs
        elif isinstance(field, DateTimeField):
            tree[field.name] = str(value)
        elif isinstance(field, FileField):
            tree[field.name] = {'url': value.url}
        else:
            tree[field.name] = value

    return tree

Эта функция в основном используется для выгрузки экземпляра модели в данные json:

def to_json(self):
    tree = to_dict(self, exclude=('id', 'User.password'))
    return json.dumps(tree, ensure_ascii=False)

Отличная работа! Предложите добавить поддержку выбора ... elif hasattr (field, 'choices'): tree [field.name] = dict (field.choices) .get (value, value)
oden

5

Вместо того, чтобы редактировать каждую модель, я бы рекомендовал написать один тег шаблона, который будет возвращать все поля любой модели .
У каждого объекта есть список полей ._meta.fields.
У каждого объекта поля есть атрибут, nameкоторый будет возвращать свое имя, а метод value_to_string(), предоставленный вашей моделью, objectбудет возвращать его значение.
Остальное так же просто, как сказано в документации Django .

Вот мой пример, как этот тег шаблона может выглядеть:

    from django.conf import settings
    from django import template

    if not getattr(settings, 'DEBUG', False):
        raise template.TemplateSyntaxError('get_fields is available only when DEBUG = True')


    register = template.Library()

    class GetFieldsNode(template.Node):
        def __init__(self, object, context_name=None):
            self.object = template.Variable(object)
            self.context_name = context_name

        def render(self, context):
            object = self.object.resolve(context)
            fields = [(field.name, field.value_to_string(object)) for field in object._meta.fields]

            if self.context_name:
                context[self.context_name] = fields
                return ''
            else:
                return fields


    @register.tag
    def get_fields(parser, token):
        bits = token.split_contents()

        if len(bits) == 4 and bits[2] == 'as':
            return GetFieldsNode(bits[1], context_name=bits[3])
        elif len(bits) == 2:
            return GetFieldsNode(bits[1])
        else:
            raise template.TemplateSyntaxError("get_fields expects a syntax of "
                           "{% get_fields <object> [as <context_name>] %}")

4

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


Я собирался сказать .... databrowse делает именно это, хотя я обнаружил, что это совершенно бесполезное приложение.
mpen

4

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

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

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


4

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

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, и указав имена полей. Это также позволяет мне исключить некоторые поля (например, внешний ключ пользователя), так как в окончательный словарь встроены только имена полей, переданные через кортеж.

Я не собираюсь принимать это как ответ, потому что я уверен, что кто-то может придумать что-то более «Джангоническое» :-)

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


3

Django 1.7 решение для меня:

Там переменные точны для вопроса, но вы определенно должны быть в состоянии разобрать этот пример

Ключевым моментом здесь является использование .__dict__модели
views.py :

def display_specific(request, key):
  context = {
    'question_id':question_id,
    'client':Client.objects.get(pk=key).__dict__,
  }
  return render(request, "general_household/view_specific.html", context)

шаблон :

{% for field in gen_house %}
    {% if field != '_state' %}
        {{ gen_house|getattribute:field }}
    {% endif %}
{% endfor %}

в шаблоне я использовал фильтр для доступа к полю в dict
filters.py :

@register.filter(name='getattribute')
def getattribute(value, arg):
  if value is None or arg is None:
    return ""
  try:
    return value[arg]
  except KeyError:
    return ""
  except TypeError:
    return ""

2

Я использую это, https://github.com/miracle2k/django-tables .

<table>
<tr>
    {% for column in table.columns %}
    <th><a href="?sort={{ column.name_toggled }}">{{ column }}</a></th>
    {% endfor %}
</tr>
{% for row in table.rows %}
    <tr>
    {% for value in row %}
        <td>{{ value }}</td>
    {% endfor %}
    </tr>
{% endfor %}
</table>

2

Этот подход показывает, как использовать класс, такой как ModelForm django, и тег шаблона, такой как {{form.as_table}}, но при этом вся таблица должна выглядеть как вывод данных, а не как форма.

Первым шагом было создание подкласса виджета TextInput в django:

from django import forms
from django.utils.safestring import mark_safe
from django.forms.util import flatatt

class PlainText(forms.TextInput):
    def render(self, name, value, attrs=None):
        if value is None:
            value = ''
        final_attrs = self.build_attrs(attrs)
        return mark_safe(u'<p %s>%s</p>' % (flatatt(final_attrs),value))

Затем я создал подкласс ModelForm в django, чтобы поменять виджеты по умолчанию на версии только для чтения:

from django.forms import ModelForm

class ReadOnlyModelForm(ModelForm):
    def __init__(self,*args,**kwrds):
        super(ReadOnlyModelForm,self).__init__(*args,**kwrds)
        for field in self.fields:
            if isinstance(self.fields[field].widget,forms.TextInput) or \
               isinstance(self.fields[field].widget,forms.Textarea):
                self.fields[field].widget=PlainText()
            elif isinstance(self.fields[field].widget,forms.CheckboxInput):
                self.fields[field].widget.attrs['disabled']="disabled" 

Это были единственные виджеты, которые мне были нужны. Но не должно быть сложно распространить эту идею на другие виджеты.


1

Просто редактирование @wonder

def to_dict(obj, exclude=[]):
    tree = {}
    for field in obj._meta.fields + obj._meta.many_to_many:
        if field.name in exclude or \
           '%s.%s' % (type(obj).__name__, field.name) in exclude:
            continue
        try :
            value = getattr(obj, field.name)
        except obj.DoesNotExist as e:
            value = None
        except ObjectDoesNotExist as e:
            value = None
            continue
        if type(field) in [ForeignKey, OneToOneField]:
            tree[field.name] = to_dict(value, exclude=exclude)
        elif isinstance(field, ManyToManyField):
            vs = []
            for v in value.all():
                vs.append(to_dict(v, exclude=exclude))
            tree[field.name] = vs
        else:
            tree[field.name] = obj.serializable_value(field.name)
    return tree

Пусть Django обрабатывает все остальные поля, кроме связанных полей. Я чувствую что стабильнее



0

Я только что проверил что-то вроде этого в оболочке и, похоже, выполняет свою работу:

my_object_mapped = {attr.name: str(getattr(my_object, attr.name)) for attr in MyModel._meta.fields}

Обратите внимание, что если вам нужно представление str () для сторонних объектов, вы должны определить его в методе str . Из этого у вас есть толкование значений для объекта. Затем вы можете сделать какой-то шаблон или еще что-нибудь.


0

Джанго> = 2.0

Добавьте get_fields()к вашему models.py:

class Client(Model):
    name = CharField(max_length=150)
    email = EmailField(max_length=100, verbose_name="E-mail")

    def get_fields(self):
        return [(field.verbose_name, field.value_from_object(self)) for field in self.__class__._meta.fields]

Тогда назовите это как object.get_fieldsна вашем template.html:

<table>
    {% for label, value in object.get_fields %}
        <tr>
            <td>{{ label }}</td>
            <td>{{ value }}</td>
        </tr>
    {% endfor %}
</table>

-1

<table border='1'>
	<tr>
		{% for mfild in fields%}
			<td>{{mfild}}</td>
		{% endfor%}
	</tr>
    {%for v in records%}
        <tr>
        	<td>{{v.id}}</td>
        	<td>{{v.title}}</td>
        	<td class="">{{v.desc}}</td>

        </tr>

    {% endfor%}
 </table>
 
 
enter code here


1
Привет и добро пожаловать в ТАК. Пожалуйста, не отправляйте код только ответы. Также на этот вопрос уже есть принятый ответ, неправильное форматирование кода, вы используете устаревшие атрибуты html и самое важное: вы не объясняете, как ваш код обеспечивает лучшее решение, чем принятый.
Фридер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.