Функциональность обмена сообщениями в Django не работает

Итак, я пытаюсь добавить функцию обмена сообщениями на свой сайт электронной коммерции, где покупатели могут отправлять сообщения продавцам, а продавцы могут отправлять сообщения покупателям, когда покупатель что-то у них купил (я еще не написал код для этого, просто хочу, чтобы базовая функциональность обмена сообщениями была убрана с дороги). Вот что я пробовал.

Теперь есть три проблемы с этим. Первая заключается в том, что когда я нахожусь в файле user_message.html, если я ввожу сообщение и нажимаю кнопку "Отправить", я получаю ошибку:

Page not found (404) No Business matches the given query.

Когда очевидно, что у меня есть url для этого.

Во-вторых, когда я отправляю сообщение через представление message_seller, создается экземпляр сообщения, это работает, но получатель не получает сообщение на своей странице user_messages_view, что как бы лишает его цели.

В-третьих, я пытался заставить счетчики работать, но оба счетчика не работают. Счетчик unread_message_counter должен показывать количество непрочитанных сообщений от разных предприятий/пользователей, а счетчик individual_business_message_counter должен показывать количество непрочитанных сообщений от конкретного предприятия. Когда я нажимаю на сообщение, чтобы перейти к детальному просмотру беседы, именно тогда сообщения должны быть is_read = True.

Три проблемы, может ли кто-нибудь помочь мне решить их? Заранее спасибо!

Мой models.py:


class Business(models.Model):
    BUSINESS_TYPE_CHOICES = [
        ('product', 'Product Business'),
        ('service', 'Service Business'),
    ]
    seller = models.OneToOneField(CustomUser, on_delete=models.CASCADE, related_name='business')
    business_name = models.CharField(max_length=100)
    description = models.TextField()
    business_slug = models.SlugField(unique=True, blank=True)
    business_type = models.CharField(max_length=20, choices=BUSINESS_TYPE_CHOICES)
    country = models.ForeignKey(Country, on_delete=models.CASCADE)
    address = models.CharField(max_length=200)
    phone = models.CharField(max_length=20)
    website = models.URLField(blank=True, null=True)
    email = models.EmailField(blank=True, null=True)
    profile_picture = models.ImageField(upload_to='business_profiles/', blank=True, null=True)
    banner_image = models.ImageField(upload_to='business_banners/', blank=True, null=True)
    is_featured = models.BooleanField(default=False)

    def __str__(self):
        return self.business_name

    def save(self, *args, **kwargs):
        if not self.business_slug:
            self.business_slug = slugify(self.business_name)
        super().save(*args, **kwargs)

class Message(models.Model):
    sender = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='sent_messages')
    recipient = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='received_messages')
    business = models.ForeignKey(Business, on_delete=models.CASCADE, related_name='messages', 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.username} to {self.recipient.username}"

Мой views.py:

Мой urls.py:

urlpatterns = [
    path('', views.home, name="home"),
    path('message/<slug:business_slug>/', views.message_seller, name='message_seller'),
    path('messages/', views.user_messages_view, name='user_messages'),
    path('messages/?business_slug=<slug:business_slug>', views.user_messages_view, name='user_messages'),
]

Мое сообщение.html:

Мой user_messages.html:

когда пользователь пишет владельцу бизнеса, владелец бизнеса не получает сообщение.

Я имею в виду, что сообщение не отображается в папке входящих сообщений получателя.

Ваш запрос касается только сообщений, отправленных бизнесу и полученных от него, а не сообщений, полученных для бизнеса. В вопросе не определено, как должны отображаться такие чаты с каждым отправителем, поскольку в вопросе сообщения чата сгруппированы по бизнесам.

Тем не менее, в этом ответе будет показано, как запрашивать и отображать сообщения для бизнеса с другими пользователями. Аналогичным образом вам нужно будет обработать if request.user == business.seller для случая, когда "владельцы бизнеса могут сообщить покупателю" в if request.method == 'POST', который не показан в этом ответе.

Messages for business with selected user

1.a. Запросите user_messages для бизнеса у других пользователей, передайте 'user' в шаблон:

def user_messages_view(request):
    businesses = Business.objects.filter(
        Q(messages__sender=request.user) | Q(messages__recipient=request.user)
    ).distinct()
    user_messages = []

    for business in businesses:
        if request.user == business.seller:
            # Query user_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)
                user_messages.append({
                    'business': business,
                    'last_message': last_message,
                    'user': user,
                })
        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_businesses = set()
            if Message.objects.filter(recipient=request.user, business=business, is_read=False).exists():
                unread_businesses.add(business)
            user_messages.append({
                'business': business,
                'last_message': last_message,
                'unread_count': len(unread_businesses),
            })

    ...

1.b. Обращайтесь с дисплеем user_messages для ведения бизнеса с другими пользователями, используя message.user:

{% 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">
        <div class="badge bg-success float-right">{{ individual_business_message_counter }}</div>
        <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">{{ 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">
        <div class="badge bg-success float-right">{{ individual_business_message_counter }}</div>
        <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">{{ message.last_message.content }}</div>
                {% else %}
                <p>No messages yet.</p>
                {% endif %}
            </div>
        </div>
    </a>
    {% endif %}
{% endfor %}

2.a. Запрос messages на selected_business с selected_user, используя username:

def user_messages_view(request):
    ...

    selected_business = 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')
            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')

    ...

2.b. Обращайтесь к дисплею messages с selected_business:

{% for message in messages %}
{% if message.sender == request.user %}
...
{% elif selected_business.seller == request.user %}
{# Handle display messages from selected_business #}
<div class="chat-message-right pb-4">
    <div>
        <img src="{{ selected_business.banner_image.url }}" class="rounded-circle mr-1" alt="{{ selected_business.business_name }}" width="40" height="40">
        <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 %}
...
{% endif %}
{% endfor %}

2.c. Отображение рукояток selected_user:

{% 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>
Вернуться на верх