템플릿에서 모델 인스턴스 필드 이름과 값을 반복


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>

이 작업을 수행 할 수있는 깔끔한 "Django 승인"방법이 있습니까? 매우 일반적인 작업 인 것 같으므로이 특정 프로젝트를 위해 자주 수행해야합니다.

답변:


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
이것은 여전히 ​​매우 수동적이며 템플릿에 전달하는보기에 일종의 메타 객체를 작성해야합니다. 원하는 것보다 더 많은 해킹입니다. 더 깔끔한 방법이 있어야합니까?
Wayne Koorts

2
ModelForm처럼 클래스에서이 모든 것을 캡슐화 할 수 있습니다.
Ignacio Vazquez-Abrams

18
템플릿에서 _ 메소드를 호출 할 수 있다고 생각하지 않습니다.
Issac Kelly

2
이 방법은 작동하지만 개인 API ( "_"접두어)에 의존해서는 안됩니다. 개인 API에 의존하는 문제는 개인 메소드가 버전마다 작동하지 않는다는 것입니다.
Devy

1
나는이 방법은 우리가 템플릿에서 밑줄로 시작하는 속성에 접근하지 말아야으로 선호하지한다고 생각
GP92

72

Django의 to-python queryset serializer 사용할 수 있습니다 .

다음 코드를보기에 넣으십시오.

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
직렬화를 사용할 필요는 없습니다. 사전을 리턴하는 querysetvalues ​​() 메소드를 사용할 수 있습니다 . 또한이 메소드는 서브 세트화할 필드 목록을 승인합니다. 링크를 참조 하십시오 . 내 전체 답변을 참조하십시오.
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
좋은 솔루션이지만 ForeignKey 필드에 대해서는 model_to_dict를 반환하지 않지만 유니 코드 결과 를 반환하므로 매우 일반적이지 않습니다. 따라서 복잡한 객체를 dict로 직렬화 할 수 없습니다.
Vestel

22
객체를 재정의하는 것은 위험하므로 다른 변수 이름을 사용해야합니다.
Emil Stenström

감사합니다! ForeignKey를 처리 할 수 ​​있도록 Django의 model_to_dict ()를 교체했습니다. 별도의 답변을 참조하십시오 (주석은 코드 형식을 지원하지 않기 때문에 이전 주석을 삭제했습니다. 죄송합니다. 몰랐습니다.)
Magnus Gustavsson

2
이 여기에 가정하면 FooFormA는 ModelForm그냥 어떻게하는 것이 더 쉬울 수 없습니다, 다음과 같습니다 FooForm(instance=Foo.objects.get(pk=object_id)))?
beruic

이 방법으로 편집 가능한 필드 만 표시하는 방법을 알고 있습니까?
alias51

22

Django 1.8의 릴리스 (및 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)

장고 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

@Escher-답변을 업데이트했습니다! 제안 해 주셔서 감사합니다. 내가 놓친 것이 있으면 알려주세요!
Michael B

공감. 필드 이름뿐만 아니라 값 인쇄도 포함하도록 편집했습니다. 당신의 생각을보십시오.
Escher

값을 어디에 인쇄합니까? 이름과 verbose_name 만 인쇄하는 것을 볼 수 있습니까?
Dr. Ernie

@MichaelB 흠. "field.value"를 작동시킬 수 없었습니다. 필드는 실제 열 데이터가 아닌 데이터베이스 필드 인 것으로 보입니다. getattr (object, name)이라는 필터를 사용해야했습니다. 어떤 장고 버전이 효과가 있습니까?
Dr. Ernie

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

User.DoesNotExist 대신 AttributeError를 사용하는 경향이 있습니다. User.DoesNotExist가 발생하는 이유를 알 수 없습니다.
askvictor

또한 django 1.8 이상에서 공식적으로 노출되므로 self._meta.get_fields ()를 사용하는 것이 좋습니다. 그러나, 당신은 당신이 f.is_relation을 확인하여 필터링해야 할 것 코드에서 관계와 끝까지
askvictor

User.DoesNotExist (원래 구현에서 남은 것) 대신 AttributeError를 사용하도록 답변을 편집했습니다. 감사. _meta.get_fields()테스트 할 때까지 보류 중 입니다.
shacker

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]
Sevenearths

영리한 아이디어. 그러나 이미 model객체 가 있다면 필드를 얻기 위해 데이터베이스를 다시 누르십시오. 그 주위에 어떤 방법이 있습니까?
frnhr

@ user1763732는 QuerySet에 대한 문서를 확인하십시오. docs.djangoproject.com/en/dev/ref/models/querysets
olofom

9

사전을 반환하는 의 values()메소드를 사용할 수 있습니다 queryset. 또한이 메소드는 서브 세트화할 필드 목록을 승인합니다. 이 values()메소드는에서 작동하지 않으므로 get()사용해야합니다 filter()( QuerySet API 참조 ).

에서 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>

A의 인스턴스의 컬렉션을 필터에 의해 반환

   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.
David Cain

7

이 작업을 수행하는 기본 제공 방법이 있어야합니다. build_pretty_data_view모델 객체와 양식 인스턴스 (모델을 기반으로 한 양식)를 가져 와서이 유틸리티 를 작성했습니다 SortedDict.

이 솔루션의 이점은 다음과 같습니다.

  • Django의 내장을 사용하여 순서를 유지 SortedDict합니다.
  • label / 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

아래는 Shacker 's 에서 영감을 얻은 광산 get_all_fields입니다. 관계 필드가 발생하면 하나의 모델 인스턴스에 대한 dict를 가져온 다음 필드 값을 dict에 재귀 적으로 할당합니다.

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

모든 모델을 편집하는 대신 주어진 모델의 모든 필드를 반환하는 하나의 템플릿 태그 를 작성하는 것이 좋습니다 . 모든 객체에는 필드 목록이 있습니다 . 모든 필드 객체에는 이름을 반환하는 속성 이 있으며 모델과 함께 제공된 메서드 는 해당 값을 반환합니다. 나머지는 Django documentation 에서 말한 것처럼 간단 합니다 .
._meta.fields
namevalue_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는 완전히 쓸모없는 앱 인 것을 알았지 만 그렇게한다.
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에 전달 된 튜플을 사용하고 필드 이름을 지정하여 필드 레이블을 표시 할 순서를 선택할 수 있다는 것입니다. 또한 tuple을 통해 전달 된 필드 이름 만 최종 사전에 내장되어 있기 때문에 특정 필드 (예 : User foreign key)를 제외시킬 수 있습니다.

나는 누군가가 더 "장고"를 생각 해낼 수 있기 때문에 이것을 대답으로 받아들이지 않을 것입니다 :-)

업데이트 : 나는 이것이 내가 필요한 것을 수행하는 것 중에서 가장 간단하기 때문에 이것을 최종 답변으로 선택하고 있습니다. 답변을 주신 모든 분들께 감사드립니다.


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

이 방법은 django의 ModelForm과 같은 클래스와 {{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))

그런 다음 django의 ModelForm을 서브 클래스 화하여 읽기 전용 버전의 기본 위젯을 교체했습니다.

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
안녕하세요. SO에 오신 것을 환영합니다. 코드 만 답변을 게시하지 마십시오. 또한이 질문에는 이미 허용 된 답변이 있으며 코드 형식이 정확하지 않으며 더 이상 사용되지 않는 HTML 속성을 사용하고 있으며 가장 중요합니다. 코드가 허용되는 것보다 더 나은 솔루션을 제공하는 방법을 설명하고 있지 않습니다.
Frieder
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.