当我有一个带有两个FK的模型到同一个模型时解决FK向后关系

时间:2017-12-01 11:35:01

标签: django django-models django-views

我无法连接工作查询集以获取属于聊天室的所有Message。两个用户或Profiles组成一个Pair对象,该对象应与Room相关 - 代表两个人之间的聊天室。 Message属于聊天室。

这是chat_room的视图,我尝试预先填充以前发送/保存的所有消息:

def chat_room(request, slug):
    # a failing queryset
    messages = reversed(request.user.profile.pairing_requester.get(requester=request.user.profile).room.get(occupants=).messages.order_by('-timestamp')[:50])

    return render(request, "chat/room.html", {
        'messages': messages,
    })  

向后看,这里是相关模型(消息,房间,配对,配置文件):

class Message(models.Model):
    room = models.ForeignKey(Room, related_name='messages')
    handle = models.TextField()
    message = models.TextField()

    timestamp = models.DateTimeField(default=timezone.now, db_index=True)

    def __unicode__(self):
        return '[{timestamp}] {handle}: {message}'.format(**self.as_dict())

    @property
    def formatted_timestamp(self):
        return self.timestamp.strftime('%b %-d %-I:%M %p')

class Room(models.Model):
    """
    A room for people to chat in.
    """
    # Unsure whether to have a single FK to Pair, or two directly to Profile
    occupants = models.ForeignKey(Pair, related_name='room')

    title = models.CharField(max_length=255)

    slug = models.SlugField()

    timestamp = models.DateTimeField(default=timezone.now, db_index=True)

    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

class Pair(models.Model):
    requester = models.ForeignKey(Profile, related_name='pairing_requester')
    accepter = models.ForeignKey(Profile, related_name='pairing_accepter')

class Profile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL,
                                on_delete=models.CASCADE,
                                null=True, blank=True)

从我的角度来看,考虑到房间所属的两​​个配置文件,我如何获取属于房间的所有消息?

编辑:对于它的价值:我计划实施频道,我认为这会影响有关Room模型字段的决策。我不认为它需要明确的用户,因为无论谁在其中,都会向房间广播一条消息。但不太确定。

提前谢谢。

1 个答案:

答案 0 :(得分:1)

您不需要配对模型,它可以在房间内使用两个FK(一个用于所有者,另一个用于参与者)。

class Room(models.Model):
    """
    A room for people to chat in.
    """
    #  two directly to Profile
    owner = models.ForeignKey(Profile, related_name='own_rooms')
    # make it many to many for multiple participants
    participant = models.ForeignKey(Profile, related_name='joined_rooms')

    title = models.CharField(max_length=255)

    slug = models.SlugField()

    timestamp = models.DateTimeField(default=timezone.now, db_index=True)

    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

查看逻辑

def chat_room(request, slug):
    # find all own rooms
    own_rooms = request.user.profile.own_rooms.all()

    # Ideally chat apps displays all the rooms a user is member of and display messages for each rooms. In that case you pass rooms to the template context.

    # same for rooms in which user is participant 
    # find rooms where logged in user is participant
    joined_rooms = request.user.profile.joined_rooms.all()

    # all the rooms where user is owner & participant
    #combine both the rooms
    rooms = list(own_rooms) + list(joined_rooms)