我是编程新手,也是 Django 新手,我正在尝试设计我的第一个社交媒体应用程序。我想看看是否有一种有效的方法来检索用户提要,从而可以快速检索用户提要,而无需对数据库进行大量操作。我想了解构建高效 API 视图时应遵循的最佳实践。
下面提供的是我当前的用户模型、关注模型和用于检索用户源的 API 视图。我想知道我可以对当前的实现进行哪些改进,以便我可以更多地了解 Django 以及如何构建高效的应用程序。
目前,我的 API 视图检索请求用户关注的所有用户,然后检索这些用户发布的帖子。但是,如果用户关注很多人,则获取请求用户关注的所有用户列表的查询可能效率低下,至少我这么认为。是否有更好的实现来执行,以便我可以获得在数据库检索方面不会密集的用户源?
我有以下用户模型:
class User(AbstractUser):
# Additional fields for user profiles
profile_picture = models.ImageField(upload_to='profiles/', null=True, blank=True) # Profile picture for the user
bio = models.TextField(max_length=300, blank=True) # Short bio or description for the user
contact_information = models.CharField(max_length=100, blank=True) # Contact information for the user
profile_privacy = models.CharField(max_length=10, choices=[('public', 'Public'), ('private', 'Private')], default='public') # Privacy setting for user profile
num_followers = models.PositiveIntegerField(default=0) # counter to keep track of users num of followers
num_following = models.PositiveIntegerField(default=0) # counter to keep track of num of users a user is following
num_posts = models.PositiveIntegerField(default=0) # counter to keep track of num of posts made by the user
我有一个关注模型:
class Follow(models.Model):
FOLLOW_STATUS_CHOICES = [
('pending', 'Pending'),
('accepted', 'Accepted'),
]
follower = models.ForeignKey(User, on_delete=models.CASCADE, related_name='following') # ForeignKey User that is following another User
following = models.ForeignKey(User, on_delete=models.CASCADE, related_name='follower') # ForeignKey User that is being followed by another User
follow_status = models.CharField(max_length=10, choices=FOLLOW_STATUS_CHOICES, default='pending')
class Meta:
unique_together = ('follower', 'following') # Ensure unique follower-following pairs
indexes = [
models.Index(fields=['follower', 'following', 'follow_status']), # Combined index
]
下面是我目前使用 API 视图检索用户提要的实现:
# API view to get posts from the users that the current user follows
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def user_feed(request):
# Obtains all the users the requesting user is following
following_users = User.objects.filter(follower__follower=request.user, follower__follow_status='accepted')
# Set a default page size of 20 returned datasets per page
default_page_size = 20
# Utility function to get current page number and page size from the request's query parameters and calculate the pagination slicing indeces
start_index, end_index, validation_response = get_pagination_indeces(request, default_page_size)
if validation_response:
return validation_response
# fetch the posts from the users in following_users
feed_posts = Post.objects.filter(user__in=following_users)[start_index:end_index]
# The context is used to pass the request to the PostSerializer to perform custom logic
serializer = PostSerializer(feed_posts, many=True, context={'request': request})
return Response(serializer.data, status=status.HTTP_200_OK)
我目前的方法有效,但我只是想知道它是否可以更好
无需先检索
following_users
,可以直接使用:进行过滤
feed_posts = Post.objects.filter(
user__follower__follower=request.user, follower__follow_status='accepted'
)
自己实现分页或自己实例化序列化器可能也不是一个好主意。这一切都可以通过
ListAPIView
[drf-doc] 来完成,它已经过更广泛的测试,因此不太可能包含错误:
class UserFeedListAPIView(ListAPIView):
permission_classes = [IsAuthenticated]
serializer_class = PostSerializer
queryset = Post.objects.all()
def get_queryset(self):
return (
super()
.get_queryset()
.filter(
user__follower__follower=request.user,
follower__follow_status='accepted',
)
)
然后您可以注入自定义分页器,但这些设置也可以应用于所有视图,这可能是一个更好的主意,因为这引入了一致性。您可以在 Django Rest Framework 文档的分页部分阅读更多相关信息。例如,如果未排序,分页器也会对查询集进行排序。在这种情况下,例如通过主键。这是必要的,否则查询同一页面可能会产生不同的结果,因此“下一页”本身不会是下一页。