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


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.