在前面的章节中,我们已经通过Django框架搭建了基础的Web应用,学习了模型(Models)、视图(Views)、模板(Templates)和表单(Forms)等核心概念,并实现了用户注册、登录、个人信息管理等基本功能。本章节,我们将正式踏入社交网络的构建之旅,首先聚焦于“用户关系”这一核心部分,它是任何社交网络不可或缺的基础架构。
社交网络的核心在于用户之间的连接与互动。用户关系通常包括好友关系、关注关系、群组关系等,它们构成了社交图谱的基础。在本项目中,我们将从最简单的“好友关系”入手,实现用户之间的添加好友、删除好友、查看好友列表等功能。
在开始编码之前,我们首先需要设计用户关系的数据库模型。Django的ORM(对象关系映射)允许我们以Python类的方式定义数据库模型,极大简化了数据库操作。
通常,Django自带的User
模型已经足够用于大多数场景,但如果你需要额外的用户信息(如昵称、头像等),可以通过继承AbstractUser
来自定义用户模型。这里我们假设已经有一个包含基本信息的用户模型User
。
好友关系可以通过多种方式建模,常见的方法包括使用多对多字段、中间模型(通过自定义模型表示关系)等。为了保持关系的灵活性和可扩展性(比如未来可能需要添加好友关系的创建时间、备注等信息),我们选择使用中间模型。
from django.db import models
from django.contrib.auth.models import User
class Friendship(models.Model):
"""
用户间的好友关系模型
"""
from_user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='friendships_from')
to_user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='friendships_to')
created_at = models.DateTimeField(auto_now_add=True)
# 可以添加更多字段,如备注、关系状态等
class Meta:
unique_together = (('from_user', 'to_user'),) # 确保一对用户之间只存在一种关系
def __str__(self):
return f"{self.from_user} -> {self.to_user}"
这里,Friendship
模型包含了两个ForeignKey
字段,分别指向User
模型,表示关系的发起者和接收者。unique_together
元组确保了在数据库中不会存在重复的(from_user, to_user)对,即每个用户只能对另一个用户发起一次好友请求(尽管在实际应用中,我们可能还需要处理请求接受与否的状态)。
有了模型之后,我们就可以开始实现具体的好友功能了。
添加好友功能通常包括发送好友请求和接受好友请求两个步骤。在这里,我们先实现发送好友请求的功能。
from django.shortcuts import redirect, render
from .models import Friendship
def add_friend(request, user_id):
if request.method == 'POST':
current_user = request.user
target_user = User.objects.get(id=user_id)
# 检查当前用户是否已经向目标用户发送了好友请求或已经是好友
if Friendship.objects.filter(from_user=current_user, to_user=target_user).exists():
return render(request, 'friends/already_friends.html', {'target_user': target_user})
# 发送好友请求
Friendship.objects.create(from_user=current_user, to_user=target_user)
return redirect('user_profile', user_id=target_user.id) # 假设有一个用户资料页的视图
# 如果是GET请求或其他情况,则重定向到用户资料页或其他页面
return redirect('user_profile', user_id=user_id)
注意:在实际应用中,你可能需要为好友请求添加更多的处理逻辑,比如通知机制(通知目标用户有新的好友请求)、好友请求的过期时间等。
好友请求的接受与拒绝可以通过更新Friendship
模型的状态(虽然在这个简单的模型中我们没有显式地定义状态字段)或创建反向的Friendship
记录来实现。这里,我们采用后者作为示例,即当用户接受好友请求时,在数据库中为两个用户之间各自创建一个Friendship
记录。
def accept_friend_request(request, friendship_id):
if request.method == 'POST':
friendship = Friendship.objects.get(id=friendship_id)
# 创建反向的Friendship记录以表示双向好友关系
Friendship.objects.create(from_user=friendship.to_user, to_user=friendship.from_user)
# 可选:删除原始的好友请求记录,如果不再需要
# friendship.delete()
return redirect('user_profile', user_id=friendship.from_user.id)
# 错误处理或重定向逻辑
return HttpResponseBadRequest("Invalid request")
注意:在这个示例中,我们没有直接删除原始的好友请求记录,因为有时你可能想要保留历史记录以供将来分析或审计。然而,根据你的应用需求,你可能想要这样做。
查看好友列表功能相对简单,只需从当前用户出发,查询所有与之关联的Friendship
记录,并获取这些记录的to_user
字段即可。
def view_friends(request):
if request.user.is_authenticated:
friends = User.objects.filter(friendships_to__from_user=request.user)
return render(request, 'friends/friends_list.html', {'friends': friends})
else:
return redirect('login') # 未登录用户重定向到登录页面
这里,我们使用了Django的__
查询语法来跨关系查询。friendships_to__from_user=request.user
意味着查找所有Friendship
记录,其中to_user
字段对应的User
的friendships_to
(即接收到的友谊)中的from_user
是当前用户。
上述代码片段展示了如何在Django中处理用户关系的基本逻辑。然而,要让这些功能对用户可见并可用,你还需要创建相应的视图和模板。视图负责处理HTTP请求并调用业务逻辑,模板则负责渲染数据并展示给用户。
在视图中,你将调用上述定义的函数或方法,并处理可能的异常和错误。在模板中,你将使用Django模板语言来展示数据,如好友列表、好友请求状态等。
虽然我们已经实现了用户关系的基本功能,但还有许多可以扩展和改进的地方:
Friendship
模型添加状态字段(如pending
, accepted
, rejected
),以更精细地控制好友请求的流程。通过这些扩展和改进,你的社交网络应用将变得更加健壮、灵活和易用。