I am trying to use context_processors.py to show the number of unread_messages on my base.html message icon, but for some reason it is not working.
While the unread_message counter is working for the user_messages_view properly, it just won’t work for base.html. I tried changing the logic of my context_processors.py, but same result.
So my models.py:
class Message(models.Model):
sender = models.ForeignKey(CustomUser, related_name='sent_messages', on_delete=models.CASCADE)
recipient = models.ForeignKey(CustomUser, related_name='received_messages', on_delete=models.CASCADE)
business = models.ForeignKey(Business, related_name='messages', on_delete=models.CASCADE, null=True)
content = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
is_read = models.BooleanField(default=False)
def __str__(self):
return f'Message from {self.sender} to {self.recipient} in {self.business}'
@property
def sender_is_business(self):
return self.sender.business.exists()
@property
def recipient_is_business(self):
return self.recipient.business.exists()
My views.py:
@login_required
def user_messages_view(request):
businesses = Business.objects.filter(
Q(messages__sender=request.user) | Q(messages__recipient=request.user)
).distinct()
user_messages = []
latest_messages = []
for business in businesses:
if request.user == business.seller:
# Query messages for business with other users
messages = Message.objects.filter(
Q(sender=business.seller) | Q(recipient=business.seller)
).filter(business=business).order_by('-timestamp')
for user, chat in itertools.groupby(messages, lambda m: m.recipient if m.sender == request.user else m.sender):
last_message = next(chat)
unread_count = Message.objects.filter(recipient=business.seller, sender=user, business=business, is_read=False).count()
user_messages.append({
'business': business,
'last_message': last_message,
'user': user,
'unread_count': unread_count,
})
latest_messages.append(last_message)
else:
last_message = Message.objects.filter(
Q(sender=request.user, recipient=business.seller) |
Q(sender=business.seller, recipient=request.user)
).filter(business=business).order_by('-timestamp').first()
unread_count = Message.objects.filter(recipient=request.user, sender=business.seller, is_read=False).count()
user_messages.append({
'business': business,
'last_message': last_message,
'unread_count': unread_count,
})
latest_messages.append(last_message)
# Sort user_messages by the latest message timestamp
user_messages = sorted(user_messages, key=lambda um: um['last_message'].timestamp, reverse=True)
unread_message_counter = sum(msg['unread_count'] for msg in user_messages)
if request.method == 'POST':
business_slug = request.POST.get('business_slug')
business = get_object_or_404(Business, business_slug=business_slug)
content = request.POST.get('content')
if content:
if request.user == business.seller:
# Business sending message to user
username = request.POST.get('username')
if username:
recipient = get_object_or_404(CustomUser, username=username)
Message.objects.create(
sender=request.user,
recipient=recipient,
business=business,
content=content
)
return redirect(f'{request.path}?business_slug={business.business_slug}&username={recipient.username}')
else:
# User sending message to business
Message.objects.create(
sender=request.user,
recipient=business.seller,
business=business,
content=content
)
return redirect(f'{request.path}?business_slug={business.business_slug}')
selected_business = None
selected_user = None
messages = []
if 'business_slug' in request.GET:
business_slug = request.GET.get('business_slug')
selected_business = get_object_or_404(Business, business_slug=business_slug)
if request.user == selected_business.seller and 'username' in request.GET:
# Query messages for selected_business with selected_user
username = request.GET.get('username')
if username:
selected_user = get_object_or_404(CustomUser, username=username)
messages = Message.objects.filter(
Q(sender=selected_user, recipient=selected_business.seller) |
Q(sender=selected_business.seller, recipient=selected_user)
).filter(business=selected_business).order_by('timestamp')
else:
messages = Message.objects.filter(
Q(sender=request.user, recipient=selected_business.seller) |
Q(sender=selected_business.seller, recipient=request.user)
).filter(business=selected_business).order_by('timestamp')
Message.objects.filter(recipient=request.user, business=selected_business).update(is_read=True)
context = {
'user_messages': user_messages,
'selected_business': selected_business,
'selected_user': selected_user,
'messages': messages,
'unread_message_counter': unread_message_counter,
}
return render(request, 'business/user_messages.html', context)
My user_messages.html:
<main class="content mt-5 mb-5">
<div class="container p-0">
<h1 class="h3 mb-3">Your Messages</h1>
<div class="card">
<div class="row g-0">
<div class="col-12 col-lg-5 col-xl-3 border-right">
{% for message in user_messages %}
{% if message.user %}
{# Handle display user_messages for business with other users #}
<a href="{% url 'user_messages' %}?business_slug={{ message.business.business_slug }}&username={{ message.user.username }}" class="list-group-item list-group-item-action border-0">
{% if message.unread_count > 0 %}
<div class="badge bg-success float-right">{{ message.unread_count }}</div>
{% endif %}
<div class="d-flex align-items-start">
<img src="https://ui-avatars.com/api/?name={{ message.user.username }}" class="rounded-circle mr-1" width="40px" height="40px">
<div class="flex-grow-1 ml-3">
{{ message.user.username }}
{% if message.last_message %}
<div class="small {% if message.unread_count > 0 %}font-weight-bold{% endif %}">{{ message.last_message.content }}</div>
{% else %}
<p>No messages yet.</p>
{% endif %}
</div>
</div>
</a>
{% else %}
<a href="{% url 'user_messages' %}?business_slug={{ message.business.business_slug }}" class="list-group-item list-group-item-action border-0">
{% if message.unread_count > 0 %}
<div class="badge bg-success float-right">{{ message.unread_count }}</div>
{% endif %}
<div class="d-flex align-items-start">
<img src="{{ message.business.profile_picture.url }}" class="rounded-circle mr-1" width="40px" height="40px">
<div class="flex-grow-1 ml-3">
{{ message.business.business_name }}
{% if message.last_message %}
<div class="small {% if message.unread_count > 0 %}font-weight-bold{% endif %}">{{ message.last_message.content }}</div>
{% else %}
<p>No messages yet.</p>
{% endif %}
</div>
</div>
</a>
{% endif %}
{% endfor %}
<hr class="d-block d-lg-none mt-1 mb-0">
</div>
{% if selected_business %}
<div class="col-12 col-lg-7 col-xl-9">
<div class="py-2 px-4 border-bottom d-none d-lg-block">
<div class="d-flex align-items-center py-1">
{% if selected_user %}
{# Handle display selected_user #}
<div class="position-relative">
<img src="https://ui-avatars.com/api/?name={{ selected_user.username }}" class="rounded-circle mr-1" alt="{{ selected_user.username }}" width="40" height="40">
</div>
<div class="flex-grow-1 pl-3">
<strong>{{ selected_user.username }}</strong>
</div>
{% else %}
<div class="position-relative">
<img src="{{ selected_business.profile_picture.url }}" class="rounded-circle mr-1" alt="{{ selected_business.business_name }}" width="40" height="40">
</div>
<div class="flex-grow-1 pl-3">
<strong>{{ selected_business.business_name }}</strong>
</div>
{% endif %}
</div>
</div>
{% endif %}
<div class="position-relative">
<div class="chat-messages p-4">
{% for message in messages %}
{% if message.sender == request.user %}
<div class="chat-message-right pb-4">
<div>
{% if request.user == selected_business.seller %}
<img src="{{ request.user.business.profile_picture.url }}" class="rounded-circle mr-1" alt="{{ request.user.business.business_name }}" width="40" height="40">
{% else %}
<img src="https://bootdey.com/img/Content/avatar/avatar1.png" class="rounded-circle mr-1" alt="User Avatar" width="40" height="40">
{% endif %}
<div class="text-muted small text-nowrap mt-2">{{ message.timestamp }}</div>
</div>
<div class="flex-shrink-1 bg-light rounded py-2 px-3 mr-3">
<div class="font-weight-bold mb-1">You</div>
{{ message.content }}
</div>
</div>
{% else %}
<div class="chat-message-left pb-4">
<div>
{% if selected_user %}
<img src="https://ui-avatars.com/api/?name={{ selected_user.username }}" class="rounded-circle mr-1" alt="{{ selected_user.username }}" width="40" height="40">
{% else %}
<img src="{{ selected_business.profile_picture.url }}" class="rounded-circle mr-1" alt="{{ selected_business.business_name }}" width="40" height="40">
{% endif %}
<div class="text-muted small text-nowrap mt-2">{{ message.timestamp }}</div>
</div>
<div class="flex-shrink-1 bg-light rounded py-2 px-3 ml-3">
{% if selected_user %}
<div class="font-weight-bold mb-1">{{ selected_user.username }}</div>
{% else %}
<div class="font-weight-bold mb-1">{{ selected_business.business_name }}</div>
{% endif %}
{{ message.content }}
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>
{% if request.user.is_authenticated and selected_business %}
<form method="post" action="{% url 'user_messages' %}?business_slug={{ selected_business.business_slug }}">
{% csrf_token %}
<input type="hidden" name="business_slug" value="{{ selected_business.business_slug }}">
{% if request.user == selected_business.seller and selected_user %}
<input type="hidden" name="username" value="{{ selected_user.username }}">
{% endif %}
<div class="flex-grow-0 py-3 px-4 border-top">
<div class="input-group">
<input name="content" type="text" class="form-control" placeholder="Type your message">
<button class="btn btn-primary">Send</button>
</div>
</div>
</form>
{% endif %}
</div>
</div>
</div>
</div>
</main>
My context_processors.py:
def unread_message_count(request):
if request.user.is_authenticated:
unread_count = Message.objects.filter(recipient=request.user, is_read=False).count()
else:
unread_count = 0
return {
'unread_message_count': unread_count,
}
My settings.py:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'business.context_processors.unread_message_count',
],
},
},
]
My base.html:
<a href="{% url "user_messages" %}">
<div class="max-md:hidden wishlist-icon flex items-center relative cursor-pointer">
<i class="ph-bold ph-chats text-2xl"></i>
<span class="quantity wishlist-quantity absolute -right-1.5 -top-1.5 text-xs text-white bg-black w-4 h-4 flex items-center justify-center rounded-full">{{ unread_message_count }}</span>
</div>
</a>
All my other context processor counts are working except for this one. According to me, the unread_message_counter logic seems fine. I can’t figure out why this won’t work.