Django ORM用户技能关联模型验证及操作测试指导求助
嘿,作为Django ORM新手,你已经搭建了一个不错的基础框架!咱们先仔细验证你的模型有效性,再给出各操作的测试方法,最后聊聊优化方向~
模型有效性验证
先拆解每个模型的情况:
没问题的部分
- Skill模型:
skill_name设了unique=True确保技能不重复,Meta指定app_label也符合要求,结构清晰。 - UserSkill模型:通过
unique_together确保一个用户不会重复添加同一个技能,外键关联UserProfile和Skill的逻辑正确,related_name也方便反向查询,__str__方法能直观展示技能名称。 - UserProfile模型:
OneToOneField关联Django自带的auth.User合理,ManyToManyField通过UserSkill中间表关联Skill,through_fields参数设置正确,符合多对多关联的自定义中间表需求。
关键问题点
UserSkillUpvotes模型存在逻辑错误:
- 你给
user_skill和upvote_by都设了OneToOneField且unique=True,这意味着一个技能(UserSkill)只能被一个用户点赞,同时一个用户只能给一个技能点赞,完全不符合“其他用户可为这些技能点赞”的需求。 - 正确的做法是把这两个字段都改成
ForeignKey,保留unique_together = (('user_skill', 'upvote_by'),)来确保同一个用户不会给同一个用户的同一项技能重复点赞。
各操作的测试方法
你可以在Django shell里测试这些操作(运行python manage.py shell进入):
1. 添加新技能
from django.contrib.auth.models import User from wantedly_webapp.models import Skill, UserProfile, UserSkill, UserSkillUpvotes # 创建新技能 new_skill = Skill.objects.create(skill_name="Python开发") # 验证是否创建成功 Skill.objects.filter(skill_name="Python开发").exists() # 应该返回True
2. 将已有技能添加至用户档案
首先得确保有用户和对应的UserProfile:
# 创建测试用户 test_user = User.objects.create_user(username="test_user", password="123456") # 关联UserProfile(如果没有自动创建信号,需要手动创建) user_profile = UserProfile.objects.create(user=test_user) # 获取已有技能(比如刚才创建的Python开发) existing_skill = Skill.objects.get(skill_name="Python开发") # 通过中间表UserSkill添加到用户档案 UserSkill.objects.create(user=user_profile, skill_item=existing_skill) # 验证是否添加成功 test_profile = UserProfile.objects.get(user=test_user) test_profile.user_skills.all() # 应该包含Python开发这个技能
3. 保存其他用户对技能的点赞记录
先修复UserSkillUpvotes模型后再测试:
# 创建另一个用户作为点赞者 voter_user = User.objects.create_user(username="voter", password="654321") # 获取要点赞的UserSkill条目 target_user_skill = UserSkill.objects.get(user=user_profile, skill_item=existing_skill) # 记录点赞 UserSkillUpvotes.objects.create(user_skill=target_user_skill, upvote_by=voter_user) # 验证点赞是否存在 UserSkillUpvotes.objects.filter(user_skill=target_user_skill, upvote_by=voter_user).exists() # 返回True # 尝试重复点赞(应该抛出IntegrityError,因为unique_together约束) UserSkillUpvotes.objects.create(user_skill=target_user_skill, upvote_by=voter_user)
模型优化建议
替换过时的
unique_together:Django 2.2及以后推荐用UniqueConstraint替代unique_together,更灵活且支持数据库索引优化。比如在UserSkill的Meta里改成:class Meta: app_label = "wantedly_webapp" constraints = [ models.UniqueConstraint(fields=['user', 'skill_item'], name='unique_user_skill') ]UserSkillUpvotes同理。
修复UserSkillUpvotes的字段类型:把
OneToOneField改成ForeignKey,修正后的模型:class UserSkillUpvotes(models.Model): user_skill = models.ForeignKey('UserSkill', on_delete=models.CASCADE) upvote_by = models.ForeignKey('auth.User', on_delete=models.CASCADE) class Meta: app_label = "wantedly_webapp" constraints = [ models.UniqueConstraint(fields=['user_skill', 'upvote_by'], name='unique_user_skill_upvote') ] def __str__(self): return f"{self.upvote_by.username} 点赞了 {self.user_skill}"添加时间戳字段:给UserSkill和UserSkillUpvotes添加
created_at字段,记录操作时间,方便后续统计:created_at = models.DateTimeField(auto_now_add=True)优化
__str__方法:让模型的字符串表示更清晰,比如UserSkill的__str__可以改成:def __str__(self): return f"{self.user.user.username} 的技能:{self.skill_item.skill_name}"可选:给Skill添加创建者字段:如果需要区分技能是系统预设还是用户创建的,可以给Skill加一个
creator外键:creator = models.ForeignKey('auth.User', null=True, blank=True, on_delete=models.SET_NULL)这样用户创建新技能时可以关联自己,系统预设技能的creator设为null即可。
内容的提问来源于stack exchange,提问作者Divyanshu Jimmy
相关产品推荐
相关产品推荐

