0

There is a char field named json_field in Django Model. I am trying to iterate it from the view but it returns only one result as the return statement does. I am trying to figure it out how I can iterate json_field using yield.

the result that Model Object returns like:

id : 1
title : "Some Title"  
json_field : [{"key":"value","key2":"value2"},{"key":"value","key2":"value2"}]
created : "Sat Oct 21 2017 14:00:53 GMT+0300 (+03)"

view.py

import json

def MyView(request):
  model_query = MyModel.objects.all() or MyModel.objects.filter or exclude...

  for item in model_query:
      data_item = json.loads(item.json_field)

  template = "template.html"
  context = {"title":title, "data_item":data_item}

  return render(request, template, context)

in template.html

{% for query_item in model_query %}
<table>
    <thead>
        <tr>
            <th>{{ query_item.title }} - {{ query_item.created }}</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th>Some Heading </th>
            <th>Some Heading </th>

        </tr>

        <!-- json data -->
        {% for item in data_item  %}
        <tr>
            <th>{{ item.key }}</th>    
            <td>{{ item.key2|floatformat:2 }}</td>
        </tr>
        {% endfor %}
        <!-- json data -->

    </thead>
</table><

{% endfor %}

Any help will be appreciated.

oyilmaztekin
  • 713
  • 1
  • 7
  • 25

4 Answers4

1

You can prepare dataset for you template.

# Fetch data from db as queryset of dicts
items = list(MyModel.objects.filter().values('title', 'created', 'json_field'))

# Decode json in-place
for item in items:
    item['json_field'] = json.loads(item['json_field'])

context = {"title":title, "items": items}

Then interate through items inside your template:

{% for item in items %}
<table>
    <thead>
        <tr>
            <th>{{ item.title }} - {{ item.created }}</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th>Some Heading </th>
            <th>Some Heading </th>

        </tr>

        <!-- json data -->
        {% for entry in item.json_field  %}
        <tr>
            <th>{{ entry.key }}</th>    
            <td>{{ entry.key2|floatformat:2 }}</td>
        </tr>
        {% endfor %}
        <!-- json data -->

    </thead>
</table><

{% endfor %}
badshark
  • 26
  • 2
1

If you're using PostgreSQL, you can using JSONField. It uses the postgres's jsonb type, which is optimized for keeping a json serializable text.

If not, you still can use django-jsonfield. It almost gives the same functionality, even though some of the cool features of django's JSONField are not available (like this kind of lookups).

If none of these work for you, you can also implement your own JSONField by inheriting from CharField or TextField, and overriding some of the functions. This way, you won't need any of the logics of your field in your views.

Edit: If you find changing your field hard or don't wanna do it for whatever reason, you can do this in your view:

  for item in model_query:
     item.loaded_json = json.loads(item.json_field)

then you can use it like a normal field in your template:

  {% for query_item in model_query %}
      {% for item in query_item.loaded_json %}
           <span>{{ item.key }}</spam>
      {% endfor %}
  {% endfor %}
0

Thanks for updating your code!

Now I would restructure the json.load() list of dicts so you can use it. That is better style than mangling in the template.

concatenation is done by:

my_dict = dict()
for d in data_item 
    my_dict.update( d )

if you want to merge, check this thread:

How to merge two dictionaries in a single expression?

rollinger
  • 531
  • 1
  • 4
  • 15
0

Hello!

The solution depends on your purposes.

Use comprehensions if you want to construct a list of json arrays:

data_items = [json.loads(item.json_field) for item in model_query]

... or generator of json array:

data_items = (json.loads(item.json_field) for item in model_query)

If you want to have a single array of json objects try this:

data_items = []
for item in model_query:
    data_items.extend(json.loads(item.json_field))

Then you can use data_items as a template context.

A little tip: You can utilize JSONField at ORM level if you use PostgreSQL or MySQL. Consider this approach if you plan to make any filter queries on this field. As additional benefit JSON encoding/decoding will be out of box.

badshark
  • 26
  • 2