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

如何为User与Skill模型添加带等级值的多对多关联?

在Django中实现带等级的User与Skill多对多关联

这是个非常常见的需求,Django的多对多关系支持通过**自定义中间表(through模型)**来添加额外字段,正好能满足你每个技能绑定等级的需求。下面是具体的实现步骤和代码示例:

1. 定义基础模型

首先我们需要先定义Skill模型,以及用于关联的中间表UserSkill,最后再配置User模型的多对多字段:

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.core.validators import MinValueValidator, MaxValueValidator

# 自定义User模型(推荐使用,替代默认User)
class User(AbstractUser):
    # 多对多字段,指定使用自定义中间表UserSkill
    skills = models.ManyToManyField(
        'Skill',
        through='UserSkill',
        related_name='users_with_skill',
        blank=True
    )

# Skill模型,由用户创建和添加
class Skill(models.Model):
    name = models.CharField(max_length=100, unique=True)  # 技能名称,确保唯一

    def __str__(self):
        return self.name

# 中间表,存储User与Skill的关联及等级
class UserSkill(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    skill = models.ForeignKey(Skill, on_delete=models.CASCADE)
    # 等级字段,限制1-10,同时提供验证和可选的下拉选项
    level = models.IntegerField(
        validators=[
            MinValueValidator(1),
            MaxValueValidator(10)
        ],
        choices=[(i, str(i)) for i in range(1, 11)]  # 可选,让admin/表单显示下拉选择
    )

    class Meta:
        # 确保一个用户对同一个技能只能有一条记录
        unique_together = ('user', 'skill')
        # Django 2.2+ 也可以用constraints替代:
        # constraints = [
        #     models.UniqueConstraint(fields=['user', 'skill'], name='unique_user_skill')
        # ]

    def __str__(self):
        return f"{self.user.username} - {self.skill.name}: Level {self.level}"

2. 关键细节说明

  • 自定义中间表:通过through参数告诉Django使用我们定义的UserSkill来管理多对多关系,这样就能添加level这个额外字段。
  • 等级验证:用MinValueValidator和MaxValueValidator确保等级在1-10之间;choices参数是可选的,能让后台或表单更友好地展示等级选择。
  • 唯一性约束:unique_together(或UniqueConstraint)保证同一个用户不会重复添加同一个技能,避免数据冗余。

3. 使用示例

添加用户技能及等级

# 创建一个技能
python_skill = Skill.objects.create(name="Python")
# 获取用户
user = User.objects.get(username="john")
# 关联技能并设置等级
UserSkill.objects.create(user=user, skill=python_skill, level=8)

查询用户的技能及等级

# 查询用户所有技能及对应等级
user_skills = UserSkill.objects.filter(user=user).select_related('skill')
for us in user_skills:
    print(f"技能:{us.skill.name},等级:{us.level}")

# 或者通过User模型反向查询
for skill in user.skills.all():
    # 通过中间表获取等级
    level = user.userskill_set.get(skill=skill).level
    print(f"技能:{skill.name},等级:{level}")

4. 迁移数据库

写完模型后,别忘了执行迁移命令:

python manage.py makemigrations
python manage.py migrate

这样就完成了带等级的多对多关联实现,完全满足你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:01:17