开发者

Output Django Model as Table

开发者 https://www.devze.com 2022-12-20 17:07 出处:网络
I have a view definition that (attempts to) outputs a model as a table. This is what I have so far: def output_table(request):

I have a view definition that (attempts to) outputs a model as a table. This is what I have so far:

def output_table(request):
    output = My_Model()
    return render_to_response('outputtable.html', {'output': output})

Here's the HTML for outputtable.html:

<html>
<table>
    {{ output.as_table }}
</table>
</html>

What am I doing wrong? It doesn't work. Now, it's passing the model correctly, because if I change My_Model() to My_Model.objects.all() 开发者_StackOverflowand then output it as simply {{ output }} then it shows me what I would see in the Django shell.


So what you need to do is the following:

1) add

from django.forms import ModelForm to your models.py

2) add

class My_Model_Form(ModelForm):  
           class Meta:  
               model = My_Model 

3) in your views.py, change output = My_Model() to output = My_Model_Form()

Now you are all set. So the trick is to inherit your Form from your original model.


If you're just looking to output one specific model, change your template to something like

<tr>
  <td>Name:</td>
  <td>{{ output.name}}</td>
</tr>

for all the fields you care about. If this is something you want to be able to do for any arbitrary model in your app, take a look at this snippet. That would provide you with a fields collection to loop over.


The models.Model class doesn't have a method as_table() like the forms.ModelForm class does.

My solution was to also use template tags. I went with an inclusion tag.

myapp/templatetags/model_helpers.py

from django import template
register = template.Library()


@register.inclusion_tag('myapp/model_table.html', takes_context=True)
def model_as_table(context, model_key=None, model_table_attrs_key=None):

    if model_key is None:
        model_key = 'object'

    if model_table_attrs_key is None:
        model_table_attrs_key = 'model_table_attrs'

    try:
        attrs = context[model_table_attrs_key]
    except KeyError:
        attrs = context[model_key]._meta.get_all_field_names()

    table_context = {'rows': []}
    for attr in attrs:
        try:
            value = str(getattr(context[model_key], attr))
            if value:
                table_context['rows'].append({'attr': attr,
                                              'value': context[model_key][attr]})
        except AttributeError:
            pass
        # Needs a way to display many_to_many fields.
        except StopIteration:
            pass

    return table_context

myapp/templates/myapp/model_table.html

{% for row in rows %}
    <tr>
        <td class="name">{{ row.attr }}</td>
        <td class="field">{{ row.value }}</td>
    </tr>
{% endfor %}

myapp/templates/myapp/outputtable.html

{% load model_helpers %}

<table>
    {% model_as_table %}
</table>

With this implementation you can pass which model's attributes you want to display and in which order.

myapp/views.py

def output_table(request):
    output = My_Model()
    return render_to_response('outputtable.html',
                              {'output': output, 'model_table_attrs': ['attr1', 'attr2']})

I also like this cleanly separate html and python code.


There is no method as_table on a model instance (MyModel())or on Querysets (MyModel.objects.all()). You may have seen as_table as the forms method as_table. You don't have a form there.

If you want to print a model instance/ a queryset as a table, you will have to design it yourself.


OMG this is old but Generic Views seem to be a good fit for this problem, for me at least. A List detail view should help me get running faster. :)


I came up with a solution that worked for my specific need which renders any simple model's data into table rows. Add the following filter into templatetags/your_tags_file.py (don't forget the __init__.py file in the templatetags folder):

from django import template
register = template.Library()

@register.filter()
def as_table(model):
    ret = ""
    for name in model._meta.get_all_field_names():
        try:
            field = str(getattr(model, name))
            if field:
                ret += '<tr><td class="name">'+name+'</td><td class="field">'+field+'</td></td>'
        except AttributeError:
            pass
    return ret

In the template now you can just do:

{% load your_tags_file %}
<table>
    {{output|as_table|safe}}
</table>

This will render the model in a simple table for you. You can easily add any desired thead and tbody logic as you see fit by modifying the logic of how ret is generated. Hope this helps someone.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号