Output Django Model as Table

16,238

Solution 1

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.

Solution 2

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.

Solution 3

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.

Share:
16,238
Reznor
Author by

Reznor

Updated on June 15, 2022

Comments

  • Reznor
    Reznor almost 2 years

    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() and then output it as simply {{ output }} then it shows me what I would see in the Django shell.