Home > Software design >  how do you iterate through two items in a model and display on site using Django?
how do you iterate through two items in a model and display on site using Django?

Time:11-22

I have a models.py with the following fields:

class ChatStream(models.Model):
    bot = models.TextField()
    user = models.TextField()
    name = models.CharField(max_length=100, null=True)
    created_date = models.DateTimeField(auto_now_add=True)

And I'd like on a website to iterate through "bot" and "user" one at a time, so the site would hypothetically display something like:

bot: hello!
user: what's up?
bot: I'm good
user: What's your name
bot: bot is my name

.... etc. this would keep going... So in my views.py I have

def displayDict(request):
    m = ChatStream.objects.all()
    return render(request, 'chatStream.html',
    {"chat": m})
 

def send(request):
    message = request.POST.get('userMessage', False)
    ip = visitor_ip_address(request)
    response = routes(message, ip)
    print(ip, "user sent:", message, "bot response:", response)
    chatItem = ChatStream(bot=response, user=message, name=ip)
    chatItem.save()
    return HttpResponseRedirect('/chat/') 

Then in my template, chat.html I have

{% block chatStream %} {% endblock %}

And chatStream.html (THIS IS WHERE THE ERROR IS HAPPENING I BELIEVE... how do you iterate through two items in the model so they appear one after the other on the html file?)

{% extends 'chat.html' %}

{% block chatStream %}
{% for a in bot%}
{% for b in user%}
    <p>
        <b>bot:</b> {{a}} <br>
        <b>user:</b> {{b}} <br>
    </p>
{% endfor %}

<form action="/send/" method = "post">{% csrf_token %}
    <input type="text" name="userMessage">
    <input type="submit" value="Send to smallest_steps bot">
</form> 

{% endblock  %}

But this does not work -- no text from the model is displayed on the site. I am not understanding how to iterate through two items within the model at once inside of the chatStream.html

thank you

CodePudding user response:

A lot going on here, lets try to break it down:

First, you need to pass context variables to your templates if you want to render them using the (jinja-like) Django template rendering system.

Your view function for rendering the template would look like this:

views.py

def render_chat_page(request):

    # do some logic:
    ...

    # pack the context variables:
    context = {
        'some_key' : 'some_value',
        'chat_streams' : ChatStream.objects.all(),
        ...
    }

    return render(request, 'chat_page.html', context=context)

Ok, now that we've passed the context variables to the template, we can render html elements using the variables like so:

template.html

<div> The value of "some_key" is: {{some_key}} </div>

{% for chat_stream in chat_streams %}
<div> user says: {{chat_stream.user}}</div>
<div> bot says: {{chat_stream.bot}}</div>
{% endfor %}

This will render the user and bot messages for each ChatStream object. However my hunch is that this is not entirely what you're after, instead you may want something more dynamic.

CodePudding user response:

In your displayDict view you're passing a QuerySet to the context. So, you need to loop over the QuerySet in your template.

{% extends 'chat.html' %}

{% block chatStream %}
{% for item in chat %}
    <p>
        <b>bot:</b> {{item.bot}} <br>
        <b>user:</b> {{item.user}} <br>
    </p>
{% endfor %}

<form action="/send/" method = "post">{% csrf_token %}
    <input type="text" name="userMessage">
    <input type="submit" value="Send to smallest_steps bot">
</form> 

{% endblock  %}
  • Related