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

Django中Student、University双模型多对多关联申请场景高效实现方案咨询

Django申请模型选型及实现方案

选型结论

优先选择方案1(独立Application模型作为多对多关联的中间表),完全不推荐方案2,该方案完全满足百万级数据的性能要求,也适配后续业务迭代需求。

方案2不可行的原因

方案2本质是使用Django默认的隐式多对多中间表,存在两个致命问题:

  • 扩展性为0:默认中间表仅存储student_id和university_id两个关联字段,无法存储申请时间、申请状态、提交材料、审核结果等业务必要字段,后续根本无法支撑业务需求
  • 性能不达标:默认隐式中间表不支持自定义索引,百万级数据下双向查询需要跨表关联,查询效率极低,完全无法满足性能要求
  • 双向查询不灵活:比如要查询某大学收到的待审核申请,需要反向关联Student表后再做过滤,查询开销远高于直接查申请表

独立Application表的效率说明

你担心的独立表效率问题完全不存在:

  • 百万级数据量的单表查询,只要配置合理的索引,延迟可以稳定控制在毫秒级,远高于关联多表查询的效率
  • 独立表支持针对业务查询场景自定义索引、约束,完全可以适配你的性能要求
  • 后续业务迭代成本极低:如果要细化到申请大学的具体课程,仅需在Application表中新增Course外键即可,不需要改动原有模型结构

具体实现代码示例

from django.db import models
from django.utils import timezone

class University(models.Model):
    name = models.CharField(max_length=100)
    # 原有字段保留

class Student(models.Model):
    name = models.CharField(max_length=50)
    # 原有字段保留
    # 通过through参数指定自定义中间表关联多对多关系
    applied_universities = models.ManyToManyField(
        University,
        through='Application',
        related_name='applicants'
    )

class Application(models.Model):
    # 申请状态枚举,可根据业务需要扩展
    STATUS_CHOICES = [
        ('pending', '待审核'),
        ('accepted', '已录取'),
        ('rejected', '已拒绝'),
        ('cancelled', '已取消'),
    ]
    student = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='applications')
    university = models.ForeignKey(University, on_delete=models.CASCADE, related_name='applications')
    apply_time = models.DateTimeField(default=timezone.now)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
    # 可根据业务需要新增任意字段:申请材料路径、审核时间、备注等
    material_file = models.FileField(upload_to='application_materials/', null=True, blank=True)
    audit_time = models.DateTimeField(null=True, blank=True)

    class Meta:
        # 针对常用查询场景配置索引,大幅提升百万级数据的查询效率
        indexes = [
            # 适配学生查询自己的申请记录的场景:按学生ID+申请时间倒序
            models.Index(fields=['student', '-apply_time']),
            # 适配大学查询收到的申请的场景:按大学ID+申请状态+申请时间倒序
            models.Index(fields=['university', 'status', '-apply_time']),
            # 可选唯一约束:避免同一个学生对同一个大学重复提交待审核申请
            models.UniqueConstraint(fields=['student', 'university'], condition=models.Q(status='pending'), name='unique_pending_apply')
        ]

双向查询示例(满足学生、大学双方访问需求)

  • 学生查询自己的所有待审核申请:student.applications.filter(status='pending').order_by('-apply_time')
  • 大学查询收到的所有已录取申请:university.applications.filter(status='accepted').order_by('-apply_time')
  • 查询某学生申请某大学的具体申请记录:Application.objects.get(student=xxx, university=xxx)
    所有查询均可直接基于申请表的字段过滤,无需额外跨表关联,性能最优。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 23:48:05