django 显示对象表 [英] Display table of objects django

查看:19
本文介绍了django 显示对象表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要用 Django 显示我的数据库中的一个表.显而易见的方法是手动输入表标题并循环遍历model.objects.all() 的查询结果.但是,我很懒惰,我想自动执行此操作,即通过自省加载模型中的所有字段以显示为列标题并加载所有字段值以显示为行.这种方法还可以为我节省一些时间,因为我不必在模型更改时更新我的​​模板代码.我让它工作了,但有两个问题:

  1. 我找不到加载 AutoField 字段 (id) 值的方法,因此我必须切掉 ID 列.
  2. 代码看起来很乱,尤其是在使用随机模板标签的情况下.

这是我的代码.请注意,代码运行良好,因此我将跳过所有正确的导入:

<块引用>

views.py 我使用序列化程序来序列化数据,这是我在 stackoverflow 某处读到的一个技巧

def 索引(请求):字段 = MyModel._meta.fieldsdata = serializers.serialize("python", MyModel.objects.all())context_instance = RequestContext(请求,{'数据':数据,字段":字段,})返回模板响应(请求,'index.html',context_instance)

<块引用>

template/index.html:请注意,我必须通过切掉字段列表的第一个元素来切掉 ID 列

{% with fields|slice:"1:" as cached_fields %}<表格><头><tr>{% 用于 cached_fields 中的字段 %}<th>{% get_verbose_name 字段 %}</th>{% 结束为 %}</tr></thead>{% 例如在数据 %}<tr>{% 用于 cached_fields 中的字段 %}<td>{% get_value_from_key instance.fields 字段 %}</td>{% 结束为 %}</tr>{% 结束为 %}</tbody>{% 以 %} 结尾

<块引用>

templatetags/extra_tags.py

# 标签在模板中获取字段的详细名称@register.simple_tagdef get_verbose_name(object):返回 object.verbose_name# 标签以在模板中通过名称获取字段的值@register.simple_tagdef get_value_from_key(object, key):# 这里有必要检查 isinstance(object, dict) 吗?返回对象[key.name]

解决方案

耶!由于 Видул Петров 关于将数据序列化为 json 的建议,我找到了解决方法,这也允许我加载 pk 字段.它仍然感觉过于手动和hackish(和冗长),但我想我已经接近了.请帮助我进一步重构此代码.

<块引用>

views.py 将数据序列化为 JSON 对象列表并解析为字典列表以将其传递给模板

from django.utils import simplejson as json定义索引(请求):字段 = MyModel._meta.fields数据 = json.loads(serializers.serialize("json", MyModel.objects.all()))定义解析数据(数据):结果 = []# 压平字典def flatten_dict(d):"""因为这里唯一的嵌套字典是字段,所以让我们删除字段"后缀,以便可以加载字段模板名称"""定义项目():对于键,d.items() 中的值:如果是实例(值,字典):对于子键, flatten_dict(value).items() 中的子值:产量子键,子值别的:yield 键,值返回 dict(items())对于数据中的 d:# 将 'pk' 密钥名称更改为其在数据库中的实际名称d[Employee._meta.pk.name] = d.pop('pk')# 将每个对象的字段值的 flattend dict 附加到结果中result.append(flatten_dict(d))返回结果context_instance = RequestContext(请求,{'数据':解析数据(数据),字段":字段,})返回模板响应(请求,'index.html',context_instance)

<块引用>

template/index.html 模板现在好多了

<头><tr>{% 用于 cached_fields 中的字段 %}<th>{% get_verbose_name 字段 %}</th>{% 结束为 %}</tr></thead>{% for d in data %}<tr>{% 用于字段中的字段 %}<td>{% get_value_from_key d 字段%}</td>{% 结束为 %}</tr>{% 结束为 %}</tbody>

I need to display a table from my database with Django. The obvious way is to manually type in the table headings and loop through query results of model.objects.all(). However, being quite lazy, I want to do this automatically, i.e. load all fields from model through introspection to display as column headings and load all field values to display as rows. This approach can also save me some time later because I don't have to update my template code when my model changes. I got it to work but there are two problems:

  1. I can't find away to load the AutoField field (id) value so I have to slice off the ID column.
  2. The code looks quite messy especially with the use of random template tags.

Here is my code. Please note that the code works fine so I'll skip all the imports as they are correct:

views.py I use serializers to serialize the data, a trick I read somewhere on stackoverflow

def index(request):
   fields    = MyModel._meta.fields
   data      = serializers.serialize("python", MyModel.objects.all())
   context_instance = RequestContext(request, {    
       'data'      : data,
       'fields'    : fields,
   })
   return TemplateResponse(request, 'index.html', context_instance)

template/index.html: note that I have to slice off the ID column by slicing off the first element of the fields list

{% with fields|slice:"1:" as cached_fields %}
<table>
    <thead>
        <tr>
            {% for field in cached_fields %}
                <th>{% get_verbose_name field %}</th>
            {% endfor %}
        </tr>
    </thead>
    <tbody>
        {% for instance in data %}
        <tr>
            {% for field in cached_fields %}
                <td>{% get_value_from_key instance.fields field %}</td>
            {% endfor %}
        </tr>
        {% endfor %}
    </tbody>
</table>
{% endwith %}

templatetags/extra_tags.py

# tag to get field's verbose name in template 
@register.simple_tag
def get_verbose_name(object):
    return object.verbose_name

# tag to get the value of a field by name in template
@register.simple_tag
def get_value_from_key(object, key):
    # is it necessary to check isinstance(object, dict) here? 
    return object[key.name]

解决方案

Yay! I found a work around thanks to Видул Петров's suggestion about serializing the data to json, which allows me to load the pk field as well. It still feels too manual and hackish (and verbose) but I think I'm getting close. Please help me refactor this code further.

views.py Serialize data into a list of JSON objects and parse it into a list of dictionaries to pass it to template

from django.utils import simplejson as json    

def index(request):
   fields    = MyModel._meta.fields
   data      = json.loads(serializers.serialize("json", MyModel.objects.all()))

   def parse_data(data):

        result = [] 

        # flatten the dictionary
        def flatten_dict(d):
            """ 
            Because the only nested dict here is the fields, let's just
            remove the 'fields' suffix so that the fields can be loaded in 
            template by name
            """
            def items():
                for key, value in d.items():
                    if isinstance(value, dict):
                        for subkey, subvalue in flatten_dict(value).items():
                            yield subkey, subvalue
                    else:
                        yield key, value

            return dict(items())

        for d in data:
            # change the 'pk' key name into its actual name in the database
            d[Employee._meta.pk.name] = d.pop('pk') 
            # append the flattend dict of each object's field-value to the result 
            result.append(flatten_dict(d))

        return result


   context_instance = RequestContext(request, {    
       'data'      : parse_data(data),
       'fields'    : fields,
   })
   return TemplateResponse(request, 'index.html', context_instance)

template/index.html The template is much nicer now

<table>
    <thead>
        <tr>
            {% for field in cached_fields %}
                <th>{% get_verbose_name field %}</th>
            {% endfor %}
        </tr>
    </thead>
    <tbody>            
            {% for d in data %}
                <tr>
                    {% for field in fields %}
                        <td>{% get_value_from_key d field %}</td>
                    {% endfor %}
                </tr>
            {% endfor %}            
    </tbody>
</table>

这篇关于django 显示对象表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆