在Django Admin中将ManyToManyWidget添加到ManyToManyField的反向

Ror*_*ory 30 python django django-models django-admin

假设我在Django 1.4中有一个简单的博客应用程序:

class Post(models.Model):
    title = …
    published_on = …
    tags = models.ManyToManyField('Tag')

class Tag(models.Model):
    name = …
Run Code Online (Sandbox Code Playgroud)

即帖子有很多标签.在Django管理,我得到一个不错的<select multi>,如果我包括tagsfieldsPostAdmin.有没有一种简单的方法可以包含帖子列表(简单<select multi>)TagAdmin?我试图把fields = ['name', 'posts']TagAdmin,就有了一个ImproperlyConfigured错误.(结果相同post_set).

我对Django很好,所以可以提供一个合适的AdminForm和Admin对象,但我希望有一个Right Way™来做.

Mat*_*kel 29

这可以使用自定义表单.

from django.contrib import admin
from django import forms

from models import Post, Tag

class PostAdminForm(forms.ModelForm):
    tags = forms.ModelMultipleChoiceField(
        Tag.objects.all(),
        widget=admin.widgets.FilteredSelectMultiple('Tags', False),
        required=False,
    )

    def __init__(self, *args, **kwargs):
        super(PostAdminForm, self).__init__(*args, **kwargs)
        if self.instance.pk:
            self.initial['tags'] = self.instance.tags.values_list('pk', flat=True)

    def save(self, *args, **kwargs):
        instance = super(PostAdminForm, self).save(*args, **kwargs)
        if instance.pk:
            instance.tags.clear()
            instance.tags.add(*self.cleaned_data['tags'])
        return instance

class PostAdmin(admin.ModelAdmin):
    form = PostAdminForm

admin.site.register(Post, PostAdmin)
Run Code Online (Sandbox Code Playgroud)

如果你想要垂直堆叠的小部件,那False里面可以替换为True.


dyv*_*yve 11

派对有点晚了,但这是适合我的解决方案(没有魔法):

# admin.py

from django.contrib import admin
from models import Post

class TagPostInline(admin.TabularInline):
    model = Post.tags.through
    extra = 1

class PostAdmin(admin.ModelAdmin):
    inlines = [TagPostInline]

admin.site.register(Post, PostAdmin)
Run Code Online (Sandbox Code Playgroud)

参考:https://docs.djangoproject.com/en/dev/ref/contrib/admin/#working-with-many-to-many-models

  • 是的,但这并没有真正解决问题所针对的问题,即选择[多个]小部件. (3认同)

Ada*_*awy 8

修改您的模型以添加反向字段:

# models.py
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)
    published_on = models.DateTimeField()
    tags = models.ManyToManyField('Tag')

class Tag(models.Model):
    name = models.CharField(max_length=10)
    posts = models.ManyToManyField('blog.Post', through='blog.post_tags')
Run Code Online (Sandbox Code Playgroud)

然后以标准方式向 ModelAdmin 添加字段:

#admin.py
from django.contrib import admin

class TagAdmin(admin.ModelAdmin):
    list_filter = ('posts', )

admin.site.register(Tag, TagAdmin)
Run Code Online (Sandbox Code Playgroud)