这是我的模型的外观:
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')
我真正希望做的是增加一个时间戳创建一个给定的多对多关系时。 这是有道理的,但同时也增加了一点复杂性。 除了[尽管只有场我真的是添加自动创建的,因此在技术上不应该干涉这个再也]取出。新增()功能。 但我可以忍受,因为我不介意做额外的QuestionTagM2M.objects.create(question=,tag=)
,而不是它是否意味着获得了另外的时间戳功能。 我的问题是,我真的很想能够保持自己的filter_horizontal
的JavaScript小部件的管理。 我知道文档说我可以用内联代替,但因为没有其他字段实际上是内联除了外键,这是太笨重Tag
反正。 此外,在我的数据库架构的更大的计划,我的Question
对象已经显示为我的管理页面上内联,由于Django不支持嵌套的内嵌在admin [但]我没有选择标签的方式给定的问题。 有没有什么办法来覆盖formfield_for_manytomany(self, db_field, request=None, **kwargs)
或类似允许我对漂亮的东西使用filter_horizontal
配件和自动创建的date_added
列到数据库? 这似乎像Django的应该是能够做到本身,只要你指定在中间的所有列自动创建的(而不是外键等)的东西也许auto_created=True
? 或类似的东西
有办法做到这一点
- 正如@obsoleter中提供下面的评论 :设定
QuestionTagM2M._meta.auto_created = True
和交易W /执行syncdb事项。 动态添加date_added
领域的M2M模型Question
模型在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外壳,使用Question.tags.through
指的M2M模型。
请注意 ,如果你不使用South
,然后syncdb
就够了; 如果你这样做, South
不喜欢这种方式,也不会冻结date_added
领域,你需要手动编写迁移到添加/删除相应的列。
自定义的ModelAdmin:
- 不要定义
fields
定制的ModelAdmin内,只定义filter_horizontal
。 这将绕过在伊尔凡的回答中提到的现场验证。 - 自
formfield_for_dbfield()
或formfield_for_manytomany()
使Django管理使用widgets.FilteredSelectMultiple
的tags
领域。 - 自
save_related()
方法您的ModelAdmin类中,像
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)
- 此外,您可以修补
__set__()
的ReverseManyRelatedObjectsDescriptor
ManyToManyField领域描述符date_added
节省M2M例如W / O引发异常。
该文档可能已经改变,因为以前的答案被张贴。 我接过一看Django文档链接@Irfan提到,它似乎是一个更直接的则曾经是。
内嵌类添加到您的admin.py
和模型设置为您的M2M模型
class QuestionTagM2MInline(admin.TabularInline):
model = QuestionTagM2M
extra = 1
组inlines
在你的管理类包含内嵌刚刚定义
class QuestionAdmin(admin.ModelAdmin):
#...other stuff here
inlines = (QuestionTagM2MInline,)
不要忘记注册该管理类
admin.site.register(Question, QuestionAdmin)
做好以上后,当我一个问题,我有如下形式做在我的m2m关系的元素列表上它和下面的所有普通编辑,请点击这里,我可以添加条目或编辑现有的。
从https://docs.djangoproject.com/en/dev/ref/contrib/admin/#working-with-many-to-many-intermediary-models
当你使用一个ManyToManyField的通过参数指定的中介模式,管理员不会默认显示的Widget。 这是因为,中间模型的每个实例需要比在单个窗口小部件可以显示更多的信息,并且将根据所述中间模型变化所需的多个部件的布局。
但是,您可以尝试使用包括标签领域明确fields = ('tags',)
在管理。 这将导致该验证异常
“QuestionAdmin.fields”可以不包括ManyToManyField字段“标签”,因为“代码”手动指定a“到”模型。
此验证实现https://github.com/django/django/blob/master/django/contrib/admin/validation.py#L256
if isinstance(f, models.ManyToManyField) and not f.rel.through._meta.auto_created:
raise ImproperlyConfigured("'%s.%s' "
"can't include the ManyToManyField field '%s' because "
"'%s' manually specifies a 'through' model." % (
cls.__name__, label, field, field))
我不认为,除非你实现自己的自定义字段作为ManyToManyField就可以绕过这个验证。
文章来源: django admin many-to-many intermediary models using through= and filter_horizontal