django管理多对多中间模型使用through=和filter_
这就是我的模型的外观:django管理多对多中间模型使用through=和filter_,django,django-models,django-admin,Django,Django Models,Django Admin,这就是我的模型的外观: class QuestionTagM2M(models.Model): tag = models.ForeignKey('Tag') question = models.ForeignKey('Question') date_added = models.DateTimeField(auto_now_add=True) class Tag(models.Model): description = models.CharField(max_
class QuestionTagM2M(models.Model):
tag = models.ForeignKey('Tag')
question = models.ForeignKey('Question')
date_added = models.DateTimeField(auto_now_add=True)
class Tag(models.Model):
description = models.CharField(max_length=100, unique=True)
class Question(models.Model):
tags = models.ManyToManyField(Tag, through=QuestionTagM2M, related_name='questions')
我真正想做的就是在创建给定的多个关系时添加一个时间戳。这是有道理的,但也增加了一点复杂性。除了删除.add()功能之外[尽管我真正要添加的唯一字段是自动创建的,所以从技术上讲,它不应该再干扰这一点]。但是我可以接受这一点,因为我不介意做额外的QuestionTagM2M.objects.create(question=,tag=)
,如果这意味着获得额外的时间戳功能的话
我的问题是,我真的希望能够在管理中保留我的filter\u水平
javascript小部件。我知道文档说我可以使用内联,但这太难了,因为除了标记的外键之外,内联中没有其他字段
此外,在我的数据库模式的更大方案中,我的问题对象在我的管理页面上已经显示为内联,而且由于Django不支持管理中的嵌套内联,我无法为给定的问题选择标记
是否有任何方法可以覆盖许多(self、db\u field、request=None、**kwargs)的formfield\u
或类似内容,以允许我使用漂亮的filter\u horizontal
小部件并自动创建添加到数据库中的日期列
这似乎是django应该能够以本机方式完成的事情,只要您指定中间层中的所有列都是自动创建的(外键除外),可能是使用auto_created=True
?或者类似的东西
当您使用ManyToManyField的through参数指定中间模型时,管理员默认情况下不会显示小部件。这是因为该中间模型的每个实例都需要比单个小部件中显示的信息更多的信息,并且多个小部件所需的布局将根据中间模型的不同而有所不同
但是,您可以通过在admin中使用fields=('tags',)
来尝试显式包含tags字段。这将导致此验证异常
“QuestionAdmin.fields”不能包含ManyToManyField字段“tags”,因为“tags”手动指定“through”模型
此验证在中实现
我认为,除非实现自己的自定义字段用作ManyToManyField,否则无法绕过此验证 有很多方法可以做到这一点
- 由@obsoleter提供:set
QuestionTagM2M.\u meta.auto\u created=True
和交易w/syncdb事项
- 动态添加
date\u将添加的字段添加到models.py中Question
模型的M2M模型中
class Question(models.Model):
# use auto-created M2M model
tags = models.ManyToMany(Tag, related_name='questions')
# add date_added field to the M2M model
models.DateTimeField(auto_now_add=True).contribute_to_class(
Question.tags.through, 'date_added')
然后,您可以在管理中正常使用它ManyToManyField
在Python shell中,使用Question.tags.to
引用M2M模型
注意,如果您不使用South
,那么syncdb
就足够了;如果你这样做,South
不喜欢
这样就不会冻结date\u added
字段,您需要手动编写迁移来添加/删除相应的列
- 自定义模型管理员:
- 不要在自定义模型管理员中定义
字段
,只定义水平过滤器
。这将绕过Irfan回答中提到的现场验证
- 自定义
formfield\u for_dbfield()
或formfield\u for_manytomy()
以使Django admin使用小部件。FilteredSelectMultiple
用于标记
字段
- 在ModelAdmin类中自定义
save_related()
方法,如
- 此外,您还可以为添加的
日期对多个M2M字段的ReverseManyRelatedObjectsDescriptor
字段描述符的进行修补,以保存M2M实例而不引发异常
自先前的答案发布以来,文档可能已更改。我看了一下@Irfan提到的链接,它似乎比以前更直截了当了
将内联类添加到admin.py
并将模型设置为M2M模型
class QuestionTagM2MInline(admin.TabularInline):
model = QuestionTagM2M
extra = 1
在admin类中设置内联线
,以包含刚才定义的内联线
class QuestionAdmin(admin.ModelAdmin):
#...other stuff here
inlines = (QuestionTagM2MInline,)
别忘了注册这个管理类
admin.site.register(Question, QuestionAdmin)
完成上述操作后,当我点击一个问题时,我有一个表单可以对其进行所有常规编辑,下面是m2m关系中的元素列表,我可以在其中添加条目或编辑现有条目。另一种可能是将添加日期字段标记为只读,这将允许ModelAdmin
通过验证。显然,如果您希望在以后修改添加的日期,则不能使用此选项,但从您的逻辑来看,似乎不必这样做。此答案不再正确-文档已更新。请参见下面的@Daniel Rucci的答案。tag\u set
和question\u set
仅为一个例子。您可以扩展django.db.models.Manager
,并向其中添加您想要的所有超级功能。如果您在模型上用默认名称声明它们,它们不会被默认名称覆盖,Django也不会妨碍您。我用它来改变一些模型的.objects.
管理器的行为。我通过阅读django/contrib/admin/options.py
中的BaseModelAdmin.formfield\u for_manytomy
方法的源代码找到了另一个选项。您可以通过设置QuestionTagM2M.\u meta.auto\u created=True
@obsoleter使ModelAdmin使用自定义多对多表进行水平/垂直筛选。这会中断syncdb,但是您可以通过在meta类的sys.argv:中执行“syncdb”来解决此问题。还是很黑但是最好的
class QuestionAdmin(admin.ModelAdmin):
#...other stuff here
inlines = (QuestionTagM2MInline,)
admin.site.register(Question, QuestionAdmin)