【问题标题】:Link Data From One Table To Another Which Are Joined By An Intermediate Table将数据从一个表链接到另一个由中间表连接的表
【发布时间】:2020-06-25 01:11:30
【问题描述】:

我在设计数据库时遇到了很多困难,但我将问题归结为核心问题。

学生可以注册套餐。包是许多模块的组。

当学生注册包时,我需要为包中的每个模块自动生成一个 Extra_Data 表,链接到学生。这将保存一个模块和一个学生独有的数据。

class Student(models.Model):
    package = models.ManyToManyField(Package, blank=True)

class Module(models.Model):
    task_type = models.CharField(max_length=200)
    topic = models.CharField(max_length=200)

class Package(models.Model):
    individual_modules = models.ManyToManyField(Module, blank=True)
    name = models.CharField(max_length=200)

我如何显示包:

{% for package in user.student.module_packages.all %}
<table>
    <th>Module</th>
    <th>Task Type</th>
    <th>Topic</th>
    #<th>Complete</th> not yet implemented
    #<th>User Files</th> not yet implemented
    #<th>Teachers Files</th> not yet implemented

    <h3 class="account-heading">{{ package.name }}</h2>
    
    {% for module in package.individual_modules.all %}
    <tr>
        <td>{{ module.id }}</td>
        <td>{{ module.task_type }}</td>
        <td>{{ module.topic }}</td>
        #<td>{{ module.extra_data.module_complete }}</td> this is an example of 
        # how I would expect to be able to handle the extra_data tables contents, 
        # though its turning out to be a real challenge
    </tr>
    {% endfor %}

{% endfor %}

我尝试了很多事情,包括在 Student 和 Module 之间使用 Django through 关系,“通过”Extra_Data。这不起作用,因为它直接将学生与模块联系起来 - 当学生在 Django Admin 中获得一个包时,不会为包中的模块创建 Extra_Data 表。

-- 我认为这与我的主要问题无关,但学生也可以注册单独的模块--

非常感谢。

【问题讨论】:

  • use text, not images/links, for text--including tables & ERDs。只提供您需要的东西并将其与您的问题联系起来。仅将图像用于无法表达为文本或增强文本的内容。无法搜索或剪切和粘贴图像。在图像中包含图例/键和说明。使用编辑功能插入图片/链接。
  • 这很难理解 - 但让我试一试:当学生注册 ModulePackage 时,您试图为每个模块自动添加 ExtraModuleData?然后你想包括他们可以访问的文件上传?
  • 你好 :)。这实际上阻碍了我实施你帮助我的最后一件事 - ajax 复选框。是的,你说的是对的。每个学生的每个模块都需要一个 ExtraDataModule,包括单个模块和包中包含的每个模块。我最初包含一个指向我的 RDNM 的链接,但删除了它。再次感谢。
  • ExtraDataModule 将包含特定于该学生/模块的数据。一旦我开始工作,我应该能够创建另一个与 ExtraDataModule 表具有一对多关系的表,这个新表将保存学生为该特定模块上传的文件。

标签: django database-design relational-database database-schema


【解决方案1】:

不如将模块和包保存在Student 下,而是将此关系的所有数据保存在ExtraModuleData 或更好的名称StudentModule 下。这使学生的模块历史记录与学生模型分开。

所以,比如:

# a lot of this is short-hand
class StudentModule(models.Model):
    student = ForeignKey(Student)
    module = ForeignKey(BaseModule)
    package = ForeignKey(Package, required=False)
    files = ManyToMany(StudentFile, related_name='uploads')
    completed = Boolean()

您可以列出各个模块和包,然后使用StudentModule 的模块和包字段循环遍历它们以“选择”活动的。

在 Django Admin Student 上下文中,这意味着您只需为 StudentModule 添加一个内联,每一行都提供模块和包的选择框。 StudentModule 可以有一个空的 package 字段,如果它不在包下。无需单独保存学生包数据。

对于上传和其他多对多数据,我建议将它们保存为自己的模型,如下所示。这将更容易在管理员之外争吵,因为如果您没有模块 ID,您可以通过 student_module_id 甚至 student_module__student__id 进行查询。在管理员中,您可以通过内联添加它们。

class StudentFile(models.Model):
    file = FileField()
    student_module = ForeignKey(StudentModule)
    ..other data

只是为了添加额外的上下文,然后您的 HTML 可以是(假设您将 st_modules = StudentModule.objects.filter(student=user) 变量传递给上下文。)

{% for sm in st_modules %}
   {{ sm.module.id }}
   {{ sm.module.task }}
   {{ sm.module.topic }}
   {% if sm.package }} {{ sm.package.name }} {% endif %}
   {% for file in sm.uploads.all }} {{ file.name }} {% endfor %}
{% endfor %}

如果您需要按包对模块进行分组,Django 模板的一个有用标签是regroup。你可以这样使用:

{% regroup st_modules by package as package_list %}
{% for package, modules in package_list %}
  {{ package.grouper }} # package name if you need it
  {% for m in modules %}
     {{ m.module.id }} # etc
  {% endfor %}

希望对您有所帮助。

【讨论】:

  • 谢谢。这似乎可以工作。我现在/明天将尝试实施它,并让您知道我的进展情况。我唯一的问题是,如果学生注册一个包,我需要单独创建每个 StudentModule(包包含 12 个模块)。是否可以在一个包中注册一个学生而不必单独创建每个 StudentModule (你不必给我代码或太多细节,你已经给我的很棒,我只是想确保我能做到)。再次感谢:)
  • 包只是模块的容器。关系是模块和学生之间的关系,还有一些额外的关系数据。您可以在 Student 的管理器上编写一个名为 enroll_package 的自定义管理器方法,它接受一个包实例,然后迭代模块,为每个模块创建一个新关系。如果每个模块的额外数据不同,这会变得很麻烦,您可能需要引用 StudentModule 上处理额外数据的实例方法。如果额外数据是您不搜索/关联的数据,您可以选择使用 json/文本存储。
  • @Brenden 我并没有真正研究 StudentModule 的创建方式,但上面的 Melvyn 有一个很好的解决方案。它基本上归结为:“如果学生选择了一个包,则在保存时,循环遍历包的模块并创建一个 StudentModule 对象”。我不知道你的模块的限制,但如果你想避免有人注册同一个模块两次(作为一个包的一部分)你可以添加一个 UniqueConstraint:docs.djangoproject.com/en/3.0/ref/models/constraints/…
  • 谢谢。这很有意义。我唯一的问题是我在哪里打电话给enroll_package
  • 保存时调用,再看我上一条评论。您可以在 Package 模型中添加自定义函数,并在模型的 save() 中运行。
猜你喜欢
  • 2020-09-28
  • 1970-01-01
  • 1970-01-01
  • 2015-07-02
  • 1970-01-01
  • 2015-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多