0

I have a json coming from a view in below format ,

[  
    {  
        "model":"booking.bookeditem",
        "pk":192,
        "fields":{  
            "Booking_id":155,
            "hoarding":9,
            "date_from":"2017-11-21",
            "date_until":"2017-12-06",
            "price_net":"34500",
            "created":"2017-11-07T11:35:49.675Z"
        }
    }
]

I need to iterate through this json and print it in the template.Actually, I want to create an invoice email for the user after booking is performed for that I passed bookeditems as context to email templates.

Here is the view to create booking,

views.py :

def create_order(request,checkout):
    booking = checkout.create_order()
    if not booking:
        return None, redirect('cart:index')
    checkout.clear_storage()
    checkout.cart.clear()
    bookingitems = BookedItem.objects.filter(Booking_id=booking.pk)
    booking.send_invoice_email(booking,user,bookingitems)
    return booking, redirect('home')

Function to send invoice email,

def send_invoice_email(self,booking,user,bookingitems):
        customer_email = self.get_user_current_email()
        data = serializers.serialize('json',bookingitems)
        subject ="invoice"
        ctx = {
                 'hoardings':data
              }
        send_invoice.delay(customer_email, subject, ctx)

and i'm using celery&django EmailMessage to sending invoice email.

task.py:

@shared_task(name="task.send_invoice")
def send_invoice(customer_email, subject, ctx):
    to=[customer_email]
    from_email = 'example@gmail.com'
    message = get_template('email/invoice_email.html').render(ctx)
    msg = EmailMessage(subject,message,to=to,from_email=from_email)
    msg.content_subtype = 'html'
    msg.send()

I tried this :

 {% for i in hoardings %}
        <tr>
           <td>{{ i.pk }}</td>
        </tr>
   {% endfor %}

But it is not working , and the loop are iterating for each and every string.

Where am i going wrong in the iteration? Please help..

user8783337
  • 1
  • 1
  • 3
  • `data` is serialized to a `JSON` string. I don't think you need to serialize `bookingitems`. – Oluwafemi Sule Nov 07 '17 at 13:29
  • @OluwafemiSule I'm getting this error with out serializing `EncodeError at /checkout/summary/ ,date_from=datetime.date(2017, 11, 29), date_until=datetime.date(2017, 12, 7))]> is not JSON serializable` – user8783337 Nov 08 '17 at 04:58
  • Actually, my comment was misleading. Data structures used in celery task need to be serialized. However, I don't understand why data isn't serialized to a `dict`. How is `serializers.serialize` implemented? – Oluwafemi Sule Nov 08 '17 at 09:15
  • @OluwafemiSule imported serializer `from django.core import serializers` then passed objects `data = serializers.serialize('json',bookingitems)`. – user8783337 Nov 08 '17 at 10:25

3 Answers3

0

You've got a list of JSON objects so when you iterate over it, you get a dict in i variable. To access the data in list you have to iterate over items of it, using

{% for i in hoardings %}
    {% for k, v in i.items() %}
    <tr>
        <td>{{ k.pk }}</td> #or just v if you need only values displayed in template
    </tr>
    {% endfor %}
{% endfor %}
py_dude
  • 822
  • 5
  • 13
  • I'm getting this error `Task task.send_invoice[47c9db50-2627-40f7-a062-f3cdaaf1b92f] raised unexpected: TemplateSyntaxError(u"Could not parse the remainder: '()' from 'i.items()'",)' – user8783337 Nov 07 '17 at 15:57
  • Actually the parenthesis is a syntax error realy that's is why you're getting this exception back. the statement should really be: {% for i in hoardings %} {% for k, v in i.items %} – sgvolpe Jun 06 '20 at 17:06
0

Why do you convert it into JSON? If you want to use it in the template, just pass it as a dictionary:

def send_invoice_email(self, booking, user, bookingitems):
    customer_email = self.get_user_current_email()
    subject ="invoice"
    ctx = {
        'hoardings': bookingitems
    }
    send_invoice.delay(customer_email, subject, ctx)

In your template:

{% for i in hoardings %}
    <tr>
       <td>{{ i.pk }}</td>
       <td>{{ i.title }}</td>
    </tr>
{% endfor %}

I don't see the need to convert it to JSON first. That's the problem you have. It is passed to the template as a string, thus you cannot loop over it as if it were a dictionary. If you want to do that, you need to find a template tag or filter so the JSON is converted to a dictionary so you can loop over it like a regular dictionary.

Özer
  • 2,059
  • 18
  • 22
  • I'm getting this error while passing object as context (without serializing)`EncodeError at /checkout/summary/ ,date_from=datetime.date(2017, 11, 29), date_until=datetime.date(2017, 12, 7))]> is not JSON serializable` – user8783337 Nov 07 '17 at 15:49
0

Serialize bookingitems to a list of OrderDict items instead of a JSON string.

As plain Python objects, tasks are easily pickled and put on the task queue. Likewise, in this format the message broker is able to pass this task to the worker.

def send_invoice_email(self, booking, user, bookingitems):
    customer_email = self.get_user_current_email()
    data = serializers.serialize('python', bookingitems)
    subject = 'invoice'
    ctx = {
        'hoardings': data
    }
    send_invoice.delay(customer_email, subject, ctx)

In email template, loop over a list of OrderDict.

{% for queryset in hoardings %}
    <tr>
        <td>{{ queryset.pk }}</td>
    </tr>
{% endfor %}
Oluwafemi Sule
  • 36,144
  • 1
  • 56
  • 81