Django REST Framework关注粉丝系统如何为关联用户ID匹配对应用户名
实现方案
核心思路
你当前的接口结构无需大改,只需要在对应关系序列化器中补充关联用户字段的映射即可,完全可以保留现有返回的ID字段不破坏原有前端对接,同时新增对应username字段。
第一步:修改关系序列化器
在原有FollowingSerializer和FollowersSerializer中,新增基于外键关联的username字段映射,使用DRF的source参数直接关联外键对象的属性,无需额外写自定义方法:
class FollowingSerializer(serializers.ModelSerializer): # 保留原有数字ID字段的返回逻辑,显式映射外键对象的id属性 following_user_id = serializers.IntegerField(source="following_user_id.id", read_only=True) # 新增被关注用户的username字段 following_username = serializers.CharField(source="following_user_id.username", read_only=True) class Meta: model = UserFollowing fields = ("id", "following_user_id", "following_username", "created") class FollowersSerializer(serializers.ModelSerializer): # 保留原有数字ID字段的返回逻辑 user_id = serializers.IntegerField(source="user_id.id", read_only=True) # 新增粉丝用户的username字段 follower_username = serializers.CharField(source="user_id.username", read_only=True) class Meta: model = UserFollowing fields = ("id", "user_id", "follower_username", "created")
修改后接口返回的样例就会变成:
{ "following": [ { "id": 19, "following_user_id": 14, "following_username": "被关注的用户名", "created": "2021-04-30T17:42:31.491779Z" } ], "followers": [ { "id": 24, "user_id": 13, "follower_username": "粉丝的用户名", "created": "2021-04-30T17:48:56.153387Z" } ] }
第二步:优化查询性能,避免N+1问题
如果不做优化,每一条关注/粉丝关系记录都会单独查询一次对应的用户表,列表数据量稍大就会出现明显的性能损耗。需要修改UserSerializer中获取关注、粉丝列表的方法,通过select_related预加载关联的用户对象:
def get_following(self, obj): # 预加载外键关联的用户对象,减少数据库查询次数 follow_relations = obj.following.all().select_related("following_user_id") return FollowingSerializer(follow_relations, many=True).data def get_followers(self, obj): # 预加载外键关联的用户对象 follow_relations = obj.followers.all().select_related("user_id") return FollowersSerializer(follow_relations, many=True).data
扩展方案:支持后续返回更多用户字段
如果后续你需要在关注/粉丝列表中返回更多用户信息(比如用户头像、昵称等),可以定义一个精简的用户序列化器,通过嵌套的方式直接关联,不用在关系序列化器中逐字段映射:
- 先定义通用的精简用户序列化:
class SimpleUserSerializer(serializers.ModelSerializer): class Meta: model = User # 按需配置需要返回的用户字段,不包含敏感信息 fields = ["id", "username", "first_name", "last_name"] - 修改关系序列化器,嵌套使用上述精简序列化器:
这种方式的扩展性更强,后续新增需要返回的用户字段时,只需要修改class FollowingSerializer(serializers.ModelSerializer): # 嵌套返回完整的关联用户信息 following_user_info = SimpleUserSerializer(source="following_user_id", read_only=True) class Meta: model = UserFollowing fields = ("id", "following_user_id", "following_user_info", "created")SimpleUserSerializer的字段列表即可,不用改动关系序列化器的逻辑。
注意事项
- 你当前的模型中外键字段命名直接使用了
user_id、following_user_id,和Django外键的默认命名习惯略有差异(ORM会自动在数据库层面给外键字段追加_id后缀存储关联值),但只要序列化的source映射和模型字段名保持一致,不需要修改模型结构、不需要额外执行数据库迁移。 - 修改序列化器字段时,一定要保留原有数字ID字段的返回,避免破坏已经对接好的前端逻辑。
内容的提问来源于stack exchange,提问作者Malav Mevada
相关产品推荐
相关产品推荐

