Ali Aref
Ali Aref

Reputation: 2402

change django view context based on template

I'm wondering if there is a way to change django view context based on template (I've no idea if it's possible)

I'm building a chat application where I loop through all the thread messages and I'm looping through all images that if the image message id equals to message id to show the message related image. It's something like this

..
{% for message in chatmessages %}
    <p>{{ message.message }}</p>
    {% for img in images %}
        {% if img.message.id == message.id %}
           <img src="{{ img.image.url }}">
        {% endif %}
    {% endfor %}
{% endfor %}

and the same for attachments. I'm sending these context from my view

    context = {
        "me": me,
        "threads": threads,
        "other_user": other_user,
        "chatmessages": ChatMessage.objects.filter(thread=thread.id),
        "images": MultipleImage.objects.all(),
        "attachments": MultipleAttchment.objects.all(),
    }

Any better way to reduce my looping in template for a better functionality!? here is my models.py

...
class ChatMessage(models.Model):
    thread = models.ForeignKey(Thread, null=True, blank=True, on_delete=models.SET_NULL)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    message = models.TextField(null=True)
    timestamp = models.DateTimeField(auto_now_add=True)
    voice = models.FileField(upload_to=upload_voice_dir, blank=True, null=True)

class MultipleImage(models.Model):
    message = models.ForeignKey('ChatMessage', on_delete=models.CASCADE)
    image = models.ImageField(upload_to=upload_img_dir, blank=True, null=True)

class MultipleAttchment(models.Model):
    message = models.ForeignKey(ChatMessage, on_delete=models.CASCADE)
    attachment = models.FileField(upload_to=upload_att_dir, blank=True, null=True)
...

looking for a better way :(

Upvotes: 0

Views: 118

Answers (1)

Abdul Aziz Barkat
Abdul Aziz Barkat

Reputation: 21807

You don't need to match related object like this, Django can do it for you. Try something like this:

{% for message in chatmessages %}
    <p>{{ message.message }}</p>
    {% for img in message.multipleimage_set.all %}
        <img src="{{ img.image.url }}">
    {% endfor %}
{% endfor %}

Here what we have done is that we have used the relation between the Message and MultipleImage to fetch the related images from the database.
multipleimage_set is just the model name in lower case with _set appended, you can change this if you set a related_name attribute in your ForeignKey like so:

message = models.ForeignKey('ChatMessage', on_delete=models.CASCADE, related_name='images')

Now we can write {% for img in message.images.all %} if we want to.

Upvotes: 1

Related Questions