Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
django管理多对多中间模型使用through=和filter__Django_Django Models_Django Admin - Fatal编程技术网

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)