django admin 使用 through= 和 filter_horizo​​ntal 的多对多中介模型 [英] django admin many-to-many intermediary models using through= and filter_horizontal

查看:18
本文介绍了django admin 使用 through= 和 filter_horizo​​ntal 的多对多中介模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的模型的外观:

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=) 而如果这意味着获得额外的时间戳功能.

All I really wanted to do was add a timestamp when a given manytomany relationship was created. It makes sense, but it also adds a bit of complexity. Apart from removing the .add() functionality [despite the fact that the only field I'm really adding is auto-created so it technically shouldn't interfere with this anymore]. But I can live with that, as I don't mind doing the extra QuestionTagM2M.objects.create(question=,tag=) instead if it means gaining the additional timestamp functionality.

我的问题是我真的很希望能够在管理员中保留我的 filter_horizo​​ntal javascript 小部件.我知道文档说我可以使用内联代替,但这太笨拙了,因为除了 Tag 的外键之外,实际上没有其他字段可以在内联中.

My issue is I really would love to be able to preserve my filter_horizontal javascript widget in the admin. I know the docs say I can use an inline instead, but this is just too unwieldy because there are no additional fields that would actually be in the inline apart from the foreign key to the Tag anyway.

此外,在我的数据库架构的更大方案中,我的 Question 对象已经在我的管理页面上显示为内联,并且因为 Django 不支持在管理中嵌套内联 [尚],我无法为给定的问题选择标签.

Also, in the larger scheme of my database schema, my Question objects are already displayed as an inline on my admin page, and since Django doesn't support nested inlines in the admin [yet], I have no way of selecting tags for a given question.

有什么方法可以覆盖 formfield_for_manytomany(self, db_field, request=None, **kwargs) 或类似的东西以允许我使用漂亮的 filter_horizo​​ntal 小部件以及将 date_ added 列自动创建到数据库中?

Is there any way to override formfield_for_manytomany(self, db_field, request=None, **kwargs) or something similar to allow for my usage of the nifty filter_horizontal widget and the auto creation of the date_added column to the database?

这似乎是 django 应该能够在本机上执行的操作,只要您指定可能使用 auto_created=True 自动创建中间中的所有列(外键除外)?或类似的东西

This seems like something that django should be able to do natively as long as you specify that all columns in the intermediate are automatically created (other than the foreign keys) perhaps with auto_created=True? or something of the like

推荐答案

方法可以做到这一点

  • 由@obsoleter 在 下面的评论:设置QuestionTagM2M._meta.auto_created = True并处理与syncdb有关的事项.
  • 动态添加date_ added字段到models.py中Question模型的M2M模型

  • As provided by @obsoleter in the comment below : set QuestionTagM2M._meta.auto_created = True and deal w/ syncdb matters.
  • Dynamically add date_added field to the M2M model of Question model in models.py

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.through 来引用 M2M 模型.

Then you could use it in admin as normal ManyToManyField.
In Python shell, use Question.tags.through to refer the M2M model.

注意,如果不用South,那么syncdb就够了;如果你这样做,South 不喜欢这种方式并不会冻结date_ added 字段,您需要手动编写迁移来添加/删除相应的列.

Note, If you don't use South, then syncdb is enough; If you do, South does not like this way and will not freeze date_added field, you need to manually write migration to add/remove the corresponding column.

自定义模型管理员:

  1. 不要在自定义的ModelAdmin中定义fields,只定义filter_horizo​​ntal.这将绕过 Irfan 的回答中提到的现场验证.
  2. 自定义formfield_for_dbfield()formfield_for_manytomany() 以使Django 管理员使用widgets.FilteredSelectMultiple 作为标签> 字段.
  3. 在 ModelAdmin 类中自定义 save_related() 方法,例如
  1. Don't define fields inside customized ModelAdmin, only define filter_horizontal. This will bypass the field validation mentioned in Irfan's answer.
  2. Customize formfield_for_dbfield() or formfield_for_manytomany() to make Django admin to use widgets.FilteredSelectMultiple for the tags field.
  3. Customize save_related() method inside your ModelAdmin class, like

def save_related(self, request, form, *args, **kwargs):
    tags = form.cleaned_data.pop('tags', ())
    question = form.instance
    for tag in tags:
        QuestionTagM2M.objects.create(tag=tag, question=question)
    super(QuestionAdmin, self).save_related(request, form, *args, **kwargs)

  • 此外,您可以为 date_ added 的 ManyToManyField 的 ReverseManyRelatedObjectsDescriptor 字段描述符修补 __set__() 以保存不引发异常的 M2M 实例.
    • Also, you could patch __set__() of the ReverseManyRelatedObjectsDescriptor field descriptor of ManyToManyField for date_added to save M2M instance w/o raise exception.
    • 这篇关于django admin 使用 through= 和 filter_horizo​​ntal 的多对多中介模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆