前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Django admin 多对多字段 过滤方法 及 保持横向显示(穿梭框)

Django admin 多对多字段 过滤方法 及 保持横向显示(穿梭框)

作者头像
卓越笔记
发布2023-02-18 14:02:07
1.3K0
发布2023-02-18 14:02:07
举报
文章被收录于专栏:卓越笔记

两个模型

文章(Article) 和 标签(Tag),多对多

代码语言:javascript
复制
class Tag(models.Model):
    """
    文章标签
    """
    name = models.CharField(max_length=50, verbose_name="标签", unique=True)
    slug = models.SlugField(max_length=128, verbose_name="url标识符", unique=True, blank=True, null=True)
    show_status = models.BooleanField(verbose_name="显示状态", default=True)
    time_create = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    time_update = models.DateTimeField(blank=True, null=True, auto_now=True, verbose_name="更新时间")

    class Meta:
        verbose_name = "文章标签"
        verbose_name_plural = "文章标签列表"
        ordering = ("name",)

    def __str__(self):
        return self.name


class Article(models.Model):
    """
    文章表
    """
    title = models.CharField(max_length=200, verbose_name="标题")
    content = RichTextUploadingField(verbose_name="内容", config_name='awesome_ckeditor')
    keywords = models.CharField(verbose_name="SEO 关键词", max_length=200, blank=True, null=True, help_text="关键词之间用,隔开")

    node = models.ForeignKey(Node, verbose_name="所属节点", related_name="nods_set", on_delete=models.DO_NOTHING)
    author = models.ForeignKey(User, related_name="author_set", verbose_name="作者", on_delete=models.DO_NOTHING)
    source = models.ForeignKey(Source, verbose_name="来源", blank=True, null=True, on_delete=models.DO_NOTHING)
    tags = models.ManyToManyField(Tag, verbose_name="标签", related_name="tags_set", blank=True)

想要达到的效果

在 admin 中,文章的 tags 字段选择的时候可以按 Tag 的 show_status 过滤,并且保持横向展示

修改 Article Admin

这里主要是在 admin.py 的 ArticleAdmin 里重写 formfield_for_manytomany

formfield_for_manytomany 源码路径:../lib/python3.6/site-packages/django/contrib/admin/options.py

代码语言:javascript
复制
# 摘选 formfield_for_manytomany
class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
    """Functionality common to both ModelAdmin and InlineAdmin."""

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        """
        Get a form Field for a ManyToManyField.
        """
        # If it uses an intermediary model that isn't auto created, don't show
        # a field in admin.
        if not db_field.remote_field.through._meta.auto_created:
            return None
        db = kwargs.get('using')

        if db_field.name in self.raw_id_fields:
            kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.remote_field, self.admin_site, using=db)
        elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)):
            kwargs['widget'] = widgets.FilteredSelectMultiple(
                db_field.verbose_name,
                db_field.name in self.filter_vertical
            )

        if 'queryset' not in kwargs:
            queryset = self.get_field_queryset(db, db_field, request)
            if queryset is not None:
                kwargs['queryset'] = queryset

        form_field = db_field.formfield(**kwargs)
        if isinstance(form_field.widget, SelectMultiple) and not isinstance(form_field.widget, CheckboxSelectMultiple):
            msg = _('Hold down "Control", or "Command" on a Mac, to select more than one.')
            help_text = form_field.help_text
            form_field.help_text = format_lazy('{} {}', help_text, msg) if help_text else msg
        return form_field

admin.py ArticleAdmin 增加的内容:

代码语言:javascript
复制
# Register your models here.
class ArticleAdmin(admin.ModelAdmin):

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        """
        Get a form Field for a ManyToManyField.
        """
        # db_field.name 本模型下的字段名称
        if db_field.name == "tags":
            # 过滤
            kwargs["queryset"] = Tag.objects.filter(show_status=True)
            # filter_horizontal 保持横向展示
            from django.contrib.admin import widgets
            kwargs['widget'] = widgets.FilteredSelectMultiple(
                db_field.verbose_name,
                db_field.name in self.filter_vertical
            )
        return super(ArticleAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

    filter_horizontal = ('tags',)  # 多对多,穿梭框(横向双排,左边选到右边)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-3-1 22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 两个模型
  • 想要达到的效果
  • 修改 Article Admin
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档