2011-09-19 104 views
1

我有DB应该有一个类型多对多的字段,但它不是,我不能改变这一点。Django。多对多字段的形式,但不适用于模型

例如,我有一个学生列表和一个主题列表。主题应该是学生表中的多对多字段,但正如我所说的那样。学生桌根本没有这个领域。但还有另一个表格学生 - 包含subject_id-student_id项目的科目。

我如何在学生表单中嵌入某种可以改变学生 - 科目数据的主题字段?问题是我不能改变数据库结构,所以只需要在Django的帮助下完成。

回答

1

对于数据库表来说,没有像'外部关键字'那样的'多对多'字段。在数据库表示中,多对多的关系是通过使用一个额外的表来实现的,这个额外的表链接你想要在关系中设置的记录的主键(通常是ids)。在你的情况下,这是表学生 - 科目。当您在模型中定义多对多关系时,Django使用此表。你根本不需要改变你的数据库结构,它会像现在一样完美地工作。

参见文档:ManyToManyField

你必须设置你的中介表(即学生为对象)的名称db_table选项。那么一切都应该正常工作。

编辑:
考虑到你的评论,问题是Django需要一个特定的命名约定(即MODELNAME_id),它不是由你的表提供的。既然你说你不能改变桌子本身,你必须尝试别的。
您必须为您的中介表(学生 - 科目)创建一个额外的模型,并将字段“学生”定义为学生模型的外键,将字段“主题”定义为主题模型的外键。然后,对于多对多字段,您可以使用中间表的名称指定“通过”选项。设置选项“db_column”让Django知道你想用哪些名称来存放数据库列。需要元类中的'db_table'来指定数据库表名。

你喜欢的东西:

class StudentsSubjects(models.Model): 
    student = models.ForeignKey(Student, db_column='student') 
    subject = models.ForeignKey(Subject, db_column='subject') 

    class Meta: 
     db_table = 'students-subjects'  

class Student(models.Model): 
    ... 
    subjects = models.ManyToManyField(Subject, through='StudentsSubjects') 
    ... 

class Subject(models.Model): 
    ... 

我希望这将帮助你。
详情请参阅:Extra fields on many-to-many relationship

+0

我做到了,得到了sql错误。无效的列名称'subject_id'。中间表中没有'subject_id'字段。中间表中有'主题'字段和'学生'字段。 Django试图向他们添加'_id'后缀。主题表有ID字段,而不是subject_id。我错过了什么? – sunprophit

+0

我编辑了我的答案指向这方面。 – j0ker

+0

是的,谢谢。我看到了这篇文章。但是当我通过'through'参数帮助完成时,'Subject'字段不能包含在StudentAdmin表单中:不能包含ManyToManyField字段'subject',因为'subject'手动指定'through'模型。 – sunprophit