You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中实现User直接获取所有关联Conversation的方案问询

Hey there! Let's work through this problem to get your Django freelancer platform's conversation system working smoothly. Here's a step-by-step solution to meet your requirements:

1. Fix Core Model Relationships

First, let's address the missing connections in your models and build the proper links for conversations:

Update models.py with Corrected Associations

from django.db import models
from django.contrib.auth.models import User
from django.db.models import Q

class Worker(models.Model):
    user = models.OneToOneField(
        User, 
        on_delete=models.CASCADE, 
        related_name="worker_profile"  # Makes it easy to access worker from User
    )

class Conversation(models.Model):
    # Link to the job this conversation is tied to
    job = models.ForeignKey(
        "Job", 
        on_delete=models.CASCADE, 
        related_name="conversations"
    )
    # Link to the worker involved in the conversation
    worker = models.ForeignKey(
        Worker, 
        on_delete=models.CASCADE, 
        related_name="conversations"
    )

    class Meta:
        # Ensure one unique conversation per job-worker pair
        unique_together = ("job", "worker")

# Add a custom property to User to fetch all related conversations
def get_user_conversations(self):
    # Get conversations where user is the job publisher
    publisher_conversations = Conversation.objects.filter(job__user=self)
    # Get conversations where user is the worker
    worker_conversations = Conversation.objects.filter(worker__user=self)
    # Combine and deduplicate the querysets
    return publisher_conversations.union(worker_conversations)

# Attach the property to the User model
User.add_to_class("conversations", property(get_user_conversations))

class Message(models.Model):
    body = models.TextField(max_length=500, blank=False)
    # Use ForeignKeys instead of IntegerFields for proper ORM relationships
    sender = models.ForeignKey(
        User, 
        on_delete=models.CASCADE, 
        related_name="sent_messages"
    )
    receiver = models.ForeignKey(
        User, 
        on_delete=models.CASCADE, 
        related_name="received_messages"
    )
    conversation = models.ForeignKey(
        Conversation, 
        on_delete=models.CASCADE, 
        related_name="messages"
    )
    created_at = models.DateTimeField(auto_now_add=True)  # Optional: Track message time

class Job(models.Model):
    title = models.CharField(max_length=100, blank=False)
    description = models.TextField(max_length=500, blank=False)
    # Add this critical link: associate jobs with their publishing user
    user = models.ForeignKey(
        User, 
        on_delete=models.CASCADE, 
        related_name="jobs"
    )
    workers = models.ManyToManyField(Worker, through="JobHasWorker")

# Optional: Explicit intermediate table for job-worker links (matches your original logic)
class JobHasWorker(models.Model):
    job = models.ForeignKey(Job, on_delete=models.CASCADE)
    worker = models.ForeignKey(Worker, on_delete=models.CASCADE)
    # Link each job-worker pair to its conversation
    conversation = models.OneToOneField(
        Conversation, 
        on_delete=models.CASCADE, 
        related_name="job_worker_link"
    )

    class Meta:
        unique_together = ("job", "worker")

2. Use the New Conversation Access

Now you can easily fetch all conversations for a logged-in user with:

# In your view
current_user = request.user
my_conversations = current_user.conversations  # Returns a QuerySet you can filter further

This property handles both cases:

  • Conversations for jobs the user published
  • Conversations where the user is the worker assigned to a job

3. Implement Message Permission Validation

For Regular Django Views

Add this check in any view that accesses a single message:

from django.http import HttpResponseForbidden
from django.shortcuts import get_object_or_404

def view_message(request, message_id):
    message = get_object_or_404(Message, id=message_id)
    
    # Verify user is either sender or receiver
    if request.user not in [message.sender, message.receiver]:
        return HttpResponseForbidden("You don't have permission to view this message.")
    
    # Proceed with rendering the message
    ...

For Django REST Framework (if using APIs)

Create a custom permission class:

from rest_framework.permissions import BasePermission

class IsMessageParticipant(BasePermission):
    def has_object_permission(self, request, view, obj):
        # Allow access only if user is sender or receiver
        return obj.sender == request.user or obj.receiver == request.user

Then use it in your view:

from rest_framework.views import APIView

class MessageDetailView(APIView):
    permission_classes = [IsMessageParticipant]

    def get(self, request, message_id):
        message = get_object_or_404(Message, id=message_id)
        # Return message data
        ...

Key Notes

  • Migration Required: After updating models, run python manage.py makemigrations and python manage.py migrate to apply changes to your database.
  • ORM Best Practices: Using ForeignKey instead of IntegerField for sender/receiver ensures referential integrity and makes queries cleaner.
  • Unique Conversations: The unique_together constraint in Conversation prevents duplicate conversations for the same job-worker pair.

内容的提问来源于stack exchange,提问作者GRS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:51:37