如何在Django用户应用中实现添加、拒绝、删除好友及好友申请功能
Django好友系统实现方案
1. 修改models.py
在原有代码基础上新增好友关系字段和好友申请表单:
from django.db import models from django.contrib.auth.models import User from PIL import Image class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) image = models.ImageField(default='default.jpg', upload_to='profile_pics') # 新增好友多对多字段,symmetrical=True表示好友关系双向生效 friends = models.ManyToManyField("self", symmetrical=True, blank=True) def __str__(self): return f'{self.user.username} Profile' def save(self, *args, **kwargs): super().save(*args,**kwargs) img = Image.open(self.image.path) if img.height > 300 or img.width > 300: output_size = (300, 300) img.thumbnail(output_size) img.save(self.image.path) # 新增好友申请表 class FriendRequest(models.Model): STATUS_CHOICES = ( ('pending', '待处理'), ('accepted', '已接受'), ('rejected', '已拒绝'), ) from_user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sent_requests') to_user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='received_requests') status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='pending') created_at = models.DateTimeField(auto_now_add=True) class Meta: unique_together = ('from_user', 'to_user') # 避免重复发送申请 ordering = ['-created_at'] def __str__(self): return f'{self.from_user.username} -> {self.to_user.username} ({self.status})'
修改完成后执行迁移命令生效:
python manage.py makemigrations python manage.py migrate
2. 新增views.py视图函数
在原有视图代码基础上新增好友功能对应的逻辑:
from django.shortcuts import render, redirect, get_object_or_404 from django.contrib import messages from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from .forms import UserRegisterForm, UserUpdateForm, ProfileUpdateForm from .models import FriendRequest # 原有视图代码保持不变 def register(request): # 原有逻辑不变 ... @login_required def profile(request): # 原有逻辑不变 ... # 新增:用户列表页,用于查找可添加的好友 @login_required def user_list(request): users = User.objects.exclude(id=request.user.id) # 提前获取当前用户的好友ID和已发送申请的用户ID,方便模板判断状态 friend_ids = request.user.profile.friends.values_list('user_id', flat=True) sent_request_ids = FriendRequest.objects.filter(from_user=request.user, status='pending').values_list('to_user_id', flat=True) context = { 'users': users, 'friend_ids': friend_ids, 'sent_request_ids': sent_request_ids } return render(request, 'users/user_list.html', context) # 新增:发送好友申请 @login_required def send_friend_request(request, user_id): to_user = get_object_or_404(User, id=user_id) if request.user == to_user: messages.error(request, '不能给自己发送好友申请') return redirect('user_list') if to_user.profile in request.user.profile.friends.all(): messages.error(request, '你们已经是好友了') return redirect('user_list') if FriendRequest.objects.filter(from_user=request.user, to_user=to_user, status='pending').exists(): messages.error(request, '你已经发送过好友申请,请等待对方处理') return redirect('user_list') FriendRequest.objects.create(from_user=request.user, to_user=to_user) messages.success(request, '好友申请已发送') return redirect('user_list') # 新增:接受好友申请 @login_required def accept_friend_request(request, request_id): friend_request = get_object_or_404(FriendRequest, id=request_id, to_user=request.user, status='pending') # 互相添加好友 request.user.profile.friends.add(friend_request.from_user.profile) friend_request.from_user.profile.friends.add(request.user.profile) friend_request.status = 'accepted' friend_request.save() messages.success(request, f'你已和{friend_request.from_user.username}成为好友') return redirect('friend_requests') # 新增:拒绝好友申请 @login_required def reject_friend_request(request, request_id): friend_request = get_object_or_404(FriendRequest, id=request_id, to_user=request.user, status='pending') friend_request.status = 'rejected' friend_request.save() messages.success(request, '已拒绝好友申请') return redirect('friend_requests') # 新增:删除好友 @login_required def remove_friend(request, user_id): friend = get_object_or_404(User, id=user_id) if friend.profile in request.user.profile.friends.all(): request.user.profile.friends.remove(friend.profile) friend.profile.friends.remove(request.user.profile) messages.success(request, '已删除好友') else: messages.error(request, '对方不是你的好友') return redirect('user_list') # 新增:好友申请列表页 @login_required def friend_requests(request): requests = FriendRequest.objects.filter(to_user=request.user, status='pending') return render(request, 'users/friend_requests.html', {'requests': requests})
3. 配置urls.py路由
在你应用的urls.py中新增对应路由:
from django.urls import path from . import views urlpatterns = [ # 原有路由保持不变 path('register/', views.register, name='register'), path('profile/', views.profile, name='profile'), # 新增好友功能路由 path('users/', views.user_list, name='user_list'), path('friend-request/send/<int:user_id>/', views.send_friend_request, name='send_friend_request'), path('friend-request/accept/<int:request_id>/', views.accept_friend_request, name='accept_friend_request'), path('friend-request/reject/<int:request_id>/', views.reject_friend_request, name='reject_friend_request'), path('friend/remove/<int:user_id>/', views.remove_friend, name='remove_friend'), path('friend-requests/', views.friend_requests, name='friend_requests'), ]
4. 模板示例
用户列表页(templates/users/user_list.html)
{% extends "base.html" %} {% block content %} <h2>用户列表</h2> <div class="user-list"> {% for user in users %} <div class="card mb-2 p-2"> <div class="d-flex align-items-center"> <img src="{{ user.profile.image.url }}" alt="{{ user.username }}" width="40" class="rounded-circle me-3"> <h5 class="mb-0">{{ user.username }}</h5> <div class="ms-auto"> {% if user.id in friend_ids %} <a href="{% url 'remove_friend' user.id %}" class="btn btn-sm btn-danger">删除好友</a> {% elif user.id in sent_request_ids %} <button class="btn btn-sm btn-secondary" disabled>申请已发送</button> {% else %} <a href="{% url 'send_friend_request' user.id %}" class="btn btn-sm btn-primary">发送好友申请</a> {% endif %} </div> </div> </div> {% endfor %} </div> {% endblock %}
好友申请列表页(templates/users/friend_requests.html)
{% extends "base.html" %} {% block content %} <h2>收到的好友申请</h2> {% if requests %} {% for req in requests %} <div class="card mb-2 p-2"> <div class="d-flex align-items-center"> <img src="{{ req.from_user.profile.image.url }}" alt="{{ req.from_user.username }}" width="40" class="rounded-circle me-3"> <h5 class="mb-0">{{ req.from_user.username }} 申请添加你为好友</h5> <div class="ms-auto"> <a href="{% url 'accept_friend_request' req.id %}" class="btn btn-sm btn-success me-2">接受</a> <a href="{% url 'reject_friend_request' req.id %}" class="btn btn-sm btn-danger">拒绝</a> </div> </div> </div> {% endfor %} {% else %} <p>暂无待处理的好友申请</p> {% endif %} {% endblock %}
内容的提问来源于stack exchange,提问作者Rohan_buks
相关产品推荐
相关产品推荐

