You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

模型优化建议
  1. 替换过时的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同理。

  2. 修复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}"
    
  3. 添加时间戳字段:给UserSkill和UserSkillUpvotes添加created_at字段,记录操作时间,方便后续统计:

    created_at = models.DateTimeField(auto_now_add=True)
    
  4. 优化__str__方法:让模型的字符串表示更清晰,比如UserSkill的__str__可以改成:

    def __str__(self):
        return f"{self.user.user.username} 的技能:{self.skill_item.skill_name}"
    
  5. 可选:给Skill添加创建者字段:如果需要区分技能是系统预设还是用户创建的,可以给Skill加一个creator外键:

    creator = models.ForeignKey('auth.User', null=True, blank=True, on_delete=models.SET_NULL)
    

    这样用户创建新技能时可以关联自己,系统预设技能的creator设为null即可。


内容的提问来源于stack exchange,提问作者Divyanshu Jimmy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:37:04