我有一个问题,它是否可以使用通用的UpdateView类编辑的许多一对多的关系“两面人”。 我在models.py定义以下类:
class SomeCategory(models.Model):
code = models.CharField(max_length=5)
name = models.CharField(max_length=40)
class SomeClass(models.Model):
code = models.CharField(max_length=3, unique=True)
name = models.CharField(max_length=30, unique=False)
age = models.IntegerField(null=False)
allowed_categories = models.ManyToManyField(SomeCategory)
这些是存储组的配置数据为我的应用程序都字典类型表。 为了让编辑我用简单的更新视图的字典:
class SomeClassUpdate(UpdateView):
model = SomeClass
template_name = 'admin/edit_class.html'
fields = ['code', 'name', 'age', 'allowed_categories']
ordering = ['code']
这工作得很好,我得到一个不错的多选,一切都是完美的。 不过,我想有编辑从SomeCategory表侧的关系的可能性,所以我可以选择SomeClass的元素被链接到一定SomeCategory:
class SomeCategoryUpdate(UpdateView):
model = SomeCategory
template_name = 'admin/edit_category.html'
fields = ['code', 'name', ??????? ]
ordering = ['code']
我曾尝试加入related_name
属性的SomeCategory模式,但没有奏效。
如果任何想法可以在不使用自定义的ModelForm做些什么呢?
重点库的版本:
Django==1.11.8
psycopg2==2.7.4
PS:这是我问的计算器的第一个问题,所以请让我知道,如果我的帖子缺少任何强制性内容。
你的问题是在models.py文件。 你有两个班,但其中只有一个提到了另外一个。 你可能会认为,这应该是足够的,因为你正在使用ManyToManyField
毕竟并假定它会自动创建每个连接龙头左右逢源......可惜,这是不正确的。 在数据库级别上它确实创建既原始表中的对象引用一个独立的中介表,但这并不意味着他们都将在Django管理或类似的自动可见。
如果你想尝试简单地创建另一个someclass = models.ManyToManyField(SomeClass)
在SomeCategory
类会失败。 Django的将尝试创建通过建立两个主表之间的连接另一个单独的中介表。 但由于中介表的名称取决于您定义ManyToManyField
连接,第二个表将用不同的名称创建,一切都只是逻辑上崩溃(有两个单独的默认方式有一个多对多连接的两个表是没有意义的) 。
解决的办法是增加一个ManyToManyField
连接SomeCategory
同时还引用该中介/通过最初在创建表SomeClass
类。
一对夫妇约Django的/ Python的/命名/编程约定事项:
- 用你所引用的表的名称,因为这是包含有关该连接的信息字段的名称。 这意味着
SomeClass
的一个链接到现场SomeCategory
应该被命名为somecategory
而不是allowed_categories
。 - 如果连接是一个一对多的 - 用单数形式; 如果连接是多到很多 - 用复数。 这意味着在这种情况下,我们应该用复数和使用
somecategories
代替somecategory
。 - Django的可以自动以复数的名字,但它确实很糟糕-它只是增加了
s
字母到最后。 Mouse
- > Mouses
, Category
- > Categorys
。 在这些类型的情况下,你必须通过定义,以帮助它verbose_name_plural
在特殊Meta
类。 - 使用而无需额外的其他类引用
'
只有当阶级已经在代码中预先定义的作品。 在两个类称呼对方说的情况是真的只有一个办法。 解决的办法是在像引号把称为类的名称'SomeCategory'
,而不是SomeCategory
。 这种参考,被称为lazy relationship
两个应用程序之间拆分圆形导入依赖关系的情况下,可能是有用的。 而且,由于默认情况下它是更好地保持风格相同,避免“我将决定是否要使用引号取决于类已组织了数量级上不必要的脑能量消耗;我将不得不重做这个引号的thingie每次我决定要走动一些代码段时间”,我建议你只是每次都使用引号。 刚学开车时喜欢 - 这是更好地学习,始终使用,而不是先环顾四周,制作人是否会从这些信息中获益单独决定转向信号。 - “字符串化”(延迟加载)模型/类/表名是很容易-只需添加
'
S为中心。 你会认为字符串化的“穿越”表引用将工作同样简单的方式。 而你就错了-它会给你的ValueError: Invalid model reference. String model references must be of the form 'app_label.ModelName'.
ValueError: Invalid model reference. String model references must be of the form 'app_label.ModelName'.
错误。 为了“通过”引用字符串化的表,你需要:(1)增加'
S为中心; (二)取代所有点( .
用下划线() _
); (三)删除该参考through
!所以SomeClass.somecategories.through
变成'SomeClass_somecategories'
。
因此,解决方案是这样的:
class SomeCategory(models.Model):
code = models.CharField(max_length=5)
name = models.CharField(max_length=40)
someclasses = models.ManyToManyField('SomeClass', through='SomeClass_somecategories', blank=True)
class Meta:
verbose_name_plural = 'SomeCategories'
class SomeClass(models.Model):
code = models.CharField(max_length=3, unique=True)
name = models.CharField(max_length=30, unique=False)
age = models.IntegerField(null=False)
somecategories = models.ManyToManyField('SomeCategory')
这之后,它应该是显而易见的,对您有什么样的最终修改UpdateView
类。
文章来源: Django - edit both sides of a many-to-many relation with generic UpdateView