Ітерація над іменами полів екземплярів моделі та значеннями в шаблоні


183

Я намагаюся створити базовий шаблон для відображення значень поля вибраного екземпляра разом з їх іменами. Розгляньте це як лише стандартний висновок значень цього екземпляра у форматі таблиці, з назвою поля (конкретно, якщо назва вказано в полі) у першому стовпці та значенням цього поля у другому стовпчику.

Наприклад, скажімо, у нас є таке визначення моделі:

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 полягає в тому, що приватні методи не гарантовано працюють від версії до версії.
Devy

1
Я думаю, цей метод не слід віддавати перевагу, оскільки ми не повинні мати доступ до атрибутів, починаючи з підкреслення з шаблонів
GP92

72

Ви можете використовувати Джанго к-пітона QuerySet серіалайзер.

Просто введіть у свій подання такий код:

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. Чудова відповідь, дякую.
Yunti

3
Не потрібно використовувати серіалізацію. Можна використовувати метод значень () набору запитів , який повертає словник. Далі цей метод приймає список полів, до яких слід підмножитися. Дивіться посилання . Дивіться мою повну відповідь.
user3062149

Чи можемо ми оновити це лише для надсилання у .fields, а не для обробки в циклі? Я не хочу виставляти назви моделі / таблиці
Loser Coder

Чи дозволяє цей метод verbose_nameпередати поле?
alias51

71

Нарешті знайшов хороше рішення для цього у списку розсилки розробників :

У поданні додайте:

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
Небезпечний для переосмислення об'єкта, ви повинні використовувати іншу змінну назву.
Еміль Стенстрем

Дякую! Я замінив model_to_dict () Джанго, щоб мати можливість працювати з ForeignKey. Будь ласка, дивіться мою окрему відповідь (я видалив попередній коментар, оскільки коментарі не підтримують форматування коду. Вибачте, я цього не знав.)
Магнус Густавссон

2
Якщо припустити, що FooFormце є ModelForm, чи не було б простіше просто зробити FooForm(instance=Foo.objects.get(pk=object_id))):?
Беруїк

Будь-яка ідея, як за допомогою цього методу ви могли б відображати лише редаговані поля?
alias51

22

У світлі випуску Django 1.8 (та формалізації API Model _meta API) я подумав, що оновлю це ще більш свіжою відповіддю.

Припускаючи ту ж модель:

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:

Модель _metaAPI завжди існувала як Джанго внутрішнє, але формально не документована і підтримується. У рамках зусиль щодо оприлюднення цього 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 модельного поля, а також використовувати метод значення для отримання значення:

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 - оновив відповідь! Дякую за пропозицію. Дайте мені знати, якщо я щось пропустив / заплутав щось!
Майкл Б

Отримано. Я редагував, щоб включати друк значень, а також назви полів. Подивіться, що ви думаєте.
Ешер

Де ви друкуєте значення? Я бачу, як він друкує ім'я та ім'я_назва_назви?
Доктор Ерні

@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:?
Sevenearths

Я схильний використовувати AttributeError замість User.DoesNotExist - я не можу зрозуміти, чому це кине User.DoesNotExist.
askvictor

Крім того, можливо, буде краще використовувати self._meta.get_fields (), оскільки це офіційно виставлено у django 1.8+. Однак потім у вас виникають відносини в коді, які вам доведеться відфільтрувати, перевіривши f.is_relation
askvictor

Я відредагував відповідь на використання AttributeError замість User.DoesNotExist (що було залишком від моєї оригінальної реалізації). Дякую. Я затримуюсь, _meta.get_fields()поки не зможу перевірити це.
шейкер

13

Гаразд, я знаю, що це трохи пізно, але оскільки я натрапив на це, перш ніж знайти правильну відповідь, може, хтось інший.

З док-джанго :

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

Це дивовижно, дякую! У мене питання, чи можете ви мені допомогти; Я вкладаю всі дані об’єктів у table, тому мені потрібні кожне keyс у 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 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яка приймає об'єкт моделі та екземпляр форми (форма на основі вашої моделі) і повертає aSortedDict .

Переваги цього рішення включають:

  • Він зберігає порядок, використовуючи вбудований Django SortedDict.
  • Коли намагається отримати label / verbose_name, але повертається до імені поля, якщо його не визначено.
  • Він також необов'язково візьме exclude()список імен полів для виключення певних полів.
  • Якщо ваш клас класу містить a 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 (значення, значення)
oden

5

Замість редагування кожної моделі я рекомендував би написати один тег шаблону, який поверне все поле будь-якої заданої моделі .
Кожен об’єкт має список полів ._meta.fields.
Кожен польовий об’єкт має атрибутname який повертає його ім'я та метод, value_to_string()що постачається разом із вашою моделлю object, повертає його значення.
Решта така ж проста, як сказано в документації про Джанго .

Ось мій приклад того, як може виглядати цей тег шаблонів:

    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 робить саме це, хоча я виявив це абсолютно марний додаток.
квітня

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

Я не збираюся це сприймати як відповідь, тому що я впевнений, що хтось може придумати щось більше "Djangonic" :-)

Оновлення: я вибираю це як остаточну відповідь, тому що це найпростіший із тих, хто дає, робить те, що мені потрібно. Дякуємо всім, хто надав відповіді.


3

Рішення Django 1.7 для мене:

Там змінні точні до питання, але ви, безумовно, повинні мати змогу розрізати цей приклад

Головне тут - в значній мірі використовувати .__dict__модель
view.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}}, але всі таблиці мають вигляд даних, а не форми.

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

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

Нехай Джанго обробляє всі інші поля, крім відповідних. Я відчуваю, що це стабільніше



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
Привіт і ласкаво просимо до SO. Будь ласка, не публікуйте лише відповіді. Крім того, на це питання вже є прийнята відповідь, ваше форматування коду невірно, ви використовуєте застарілі атрибути html та найголовніше: Ви не пояснюєте, як ваш код забезпечує кращі рішення, ніж прийнятий.
Фрідер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.