【问题标题】:Django admin select m2m items based on their tags (item's m2m field)Django 管理员根据标签选择 m2m 项目(项目的 m2m 字段)
【发布时间】:2019-09-18 03:41:17
【问题描述】:

考虑以下模型:

class Library(models.Model):
    name = models.CharField(max_length=64)
    books = models.ManyToManyField(Book)

class Book(models.Model):
    name = models.CharField(max_length=64)
    tags = models.ManyToManyField(Tag)

class Tag(models.Model):
    name = models.CharField(max_length=64)

图书馆管理中,我想根据图书的标签添加图书,同时保留添加/删除单本图书的选项。

现有选项:

  1. Filter_horizo​​ntal - 按__str__ 过滤,有没有办法按tags__name 过滤?
  2. Raw_id_fields - 适用于为 Book 指定的任何过滤器,但您只能选择 1 个项目。有没有办法允许选择更多项目? (表格中的复选框)

【问题讨论】:

    标签: django django-admin filtering admin m2m


    【解决方案1】:

    我最终使用了Django-fsm 小部件并在views.py 中覆盖了它的apply_filter_val 方法。现在我可以过滤一个键tag:tag_name,然后选择所有项目。我还添加了一个选项来过滤以逗号分隔的多个单词。

    def apply_filter_val(self, filter_val, queryset):
    
        if filter_val and 'tag:' in filter_val:
    
            tag_tuple = filter_val.split(':')
            _, name = tag_tuple
    
            params = {'tags__name': name}
    
            new_base = queryset.filter(**params)
    
        elif filter_val and ',' in filter_val:
            new_base = queryset.filter(id__in=filter_val.split(','))
    
        elif filter_val:
            q = [Q(**{f'{field}__icontains': filter_val}) for field in self.fields]
            if filter_val and q:
                new_base = queryset.filter(reduce(self.default_operator, q))
        else:
            # Return everything if no filter_val or fields are specified.
            # This allows for a very straightforward async request, but will
            # probably not behave as expected if no fields are specified.
            new_base = queryset
    
        if self.obj_limit:
            new_base = new_base[:self.obj_limit]
    
        return new_base
    

    【讨论】: