Django Admin 实现外键过滤的方法


Posted in Python onSeptember 29, 2017

说明和 Model

环境:

➜ python

Python 3.6.3 |Anaconda custom (x86_64)| (default, Oct 6 2017, 12:04:38)
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> print(django.get_version())
2.0.1
>>>

2018年05月23日更新:

可以通过get_changeform_initial_data 函数来传递initial参数.

# admin.py
@admin.register(Score)
class ScoreConfigAdmin(FilterUserAdmin):
  # fields = ('id','name')
  form = ScoreConfigAdminForm

  def get_changeform_initial_data(self, request):
    initial = super().get_changeform_initial_data(request)
    initial.update({'uid': request.user.id})
    return initial

# forms.py
class ScoreConfigAdminForm(forms.ModelForm):
  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    if not kwargs.get('initial'):
      return
    self.uid = kwargs.get('initial').get('uid')

  class Meta:
    model = Score
    fields = '__all__'

有一个支持多用户(使用 django admin)的 Blog,每一篇 Post 都需要记录是谁发表的并且属于那个 Blog。

user 与 Blog 的关系、 Blog 与 Post 有2种定义方式,一种是使用独立关系表,另外一种是直接在 Model 中定义中使用外键。

后面一种的 model 定义如下:

from django.contrib.auth.models import User
from django.db import models

class Blog(models.Model):
  '''
  Blog
  '''
  id = models.AutoField(unique=True, primary_key = True, verbose_name="序号")
  name = models.CharField(max_length=255, blank=True, null=True, verbose_name="名称")
  user = models.ForeignKey(User, on_delete=models.CASCADE)
  create_time = models.DateTimeField(verbose_name='添加时间', auto_now_add=True, blank=True)

  class Meta:
    verbose_name = 'Blog'
    verbose_name_plural = 'Blog管理'

  def __str__(self):
    return self.name

class Post(models.Model):
  '''
  Post 内容
  '''
  id = models.AutoField(unique=True, primary_key = True, verbose_name="序号")
  title = models.CharField(max_length=255, blank=True, null=True, verbose_name="标题")
  content = models.TextField(max_length=1024, blank=True, null=True, verbose_name="内容")
  blog = models.ForeignKey(Blog, on_delete=models.CASCADE, verbose_name="所属Blog")
  user = models.ForeignKey(User, on_delete=models.CASCADE)
  create_time = models.DateTimeField(verbose_name='添加时间', auto_now_add=True, blank=True)

  class Meta:
    verbose_name = '文章'
    verbose_name_plural = '文章管理'

  def __str__(self):
    return self.title

Admin 中实现

admin 中有2处,一处是 Blog 和 Post 列表中按 user 过滤,另外一处是新增 Post 时需要按当前 user 过滤。完整代码如下:

from django.contrib import admin
from django import forms

# Register your models here.
from django_summernote.admin import SummernoteModelAdmin
from .models import Team, Member, Activity, Score



from .models import Blog, Post
class FilterUserAdmin(admin.ModelAdmin):
  '''
  按所属用户过滤的 base, class
  '''
  def save_model(self, request, obj, form, change):
    # TODO 需要考虑不同用户对同一数据进行修改。
    obj.user = request.user
    obj.save()

  def get_queryset(self, request):
    # For Django < 1.6, override queryset instead of get_queryset
    qs = super(FilterUserAdmin, self).get_queryset(request) 
    # 不能加这个,加了这个会导致 superuser 更新普通用户的数据。
    # if request.user.is_superuser:
    #   return qs
    return qs.filter(user=request.user)

  def has_change_permission(self, request, obj=None):
    has_class_permission = super(FilterUserAdmin, self).has_change_permission(request, obj)
    if not has_class_permission:
      return False
    if obj is not None and not request.user.is_superuser and request.user.id != obj.user.id:
      return False
    return True


class BlogConfigAdmin(FilterUserAdmin):
  list_display = ('id','name', 'create_time')
  exclude = ['user']
  list_per_page = 50

admin.site.register(Blog, BlogConfigAdmin)


class PostConfigAdmin(FilterUserAdmin):
  list_display = ('id','title', 'create_time')
  exclude = ['user']
  list_per_page = 50

  def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
    # 新增 Post 时,相关联的 Blog 需要过滤,关键就在下面这句。
    context['adminform'].form.fields['blog'].queryset = Team.objects.filter(user=request.user)
    return super(MemberConfigAdmin, self).render_change_form(request, context, add, change, form_url, obj)


admin.site.register(Post, PostConfigAdmin)

说2句

在render_change_form中下断点,直接调试下会发现更多有趣的内容。

以上这篇Django Admin 实现外键过滤的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python 列表(List) 的三种遍历方法实例 详解
Apr 15 Python
Python基于回溯法子集树模板解决0-1背包问题实例
Sep 02 Python
Django 2.0版本的新特性抢先看!
Jan 05 Python
在PyCharm环境中使用Jupyter Notebook的两种方法总结
May 24 Python
完美解决Python 2.7不能正常使用pip install的问题
Jun 12 Python
Python中xml和json格式相互转换操作示例
Dec 05 Python
python+pyqt5实现图片批量缩放工具
Mar 18 Python
详解Python locals()的陷阱
Mar 26 Python
详解爬虫被封的问题
Apr 23 Python
浅谈Python type的使用
Nov 19 Python
Python基于yield遍历多个可迭代对象
Mar 12 Python
深入了解Python 变量作用域
Jul 24 Python
python 调用c语言函数的方法
Sep 29 #Python
python文件名和文件路径操作实例
Sep 29 #Python
Python 实现简单的shell sed替换功能(实例讲解)
Sep 29 #Python
Python 基础教程之闭包的使用方法
Sep 29 #Python
python下实现二叉堆以及堆排序的示例
Sep 29 #Python
Python数据结构与算法之链表定义与用法实例详解【单链表、循环链表】
Sep 28 #Python
Python实现压缩和解压缩ZIP文件的方法分析
Sep 28 #Python
You might like
Mysql的常用命令
2006/10/09 PHP
经典的PHPer为什么被认为是草根?
2007/04/02 PHP
JavaScript 入门·JavaScript 具有全范围的运算符
2007/10/01 Javascript
javascript sudoku 数独智力游戏生成代码
2010/03/27 Javascript
解决Extjs4中form表单提交后无法进入success函数问题
2013/11/26 Javascript
Javascript中setTimeOut和setInterval的定时器用法
2015/06/12 Javascript
浅谈node.js中async异步编程
2015/10/22 Javascript
JavaScript中函数表达式和函数声明及函数声明与函数表达式的不同
2015/11/15 Javascript
JavaScript获取对象在页面中位置坐标的方法
2016/02/03 Javascript
JS组件Bootstrap Select2使用方法解析
2016/05/30 Javascript
JS+HTML5手机开发之滚动和惯性缓动实现方法分析
2016/06/12 Javascript
AngularJS 工作原理详解
2016/08/18 Javascript
详解vue-cli 接口代理配置
2017/12/13 Javascript
浅谈使用React.setState需要注意的三点
2017/12/18 Javascript
解决vue 更改计算属性后select选中值不更改的问题
2018/03/02 Javascript
Vue-CLI3.x 设置反向代理的方法
2018/12/06 Javascript
简单易扩展可控性强的Jquery转盘抽奖程序
2019/03/16 jQuery
在vue中实现echarts随窗体变化
2020/07/27 Javascript
[53:15]2018DOTA2亚洲邀请赛3月29日 小组赛A组 LGD VS TNC
2018/03/30 DOTA
Python基于sftp及rsa密匙实现远程拷贝文件的方法
2016/09/21 Python
pycharm配置当鼠标悬停时快速提示方法参数
2019/07/31 Python
python通过txt文件批量安装依赖包的实现步骤
2019/08/13 Python
Python二元赋值实用技巧解析
2019/10/25 Python
浅谈tensorflow模型保存为pb的各种姿势
2020/05/25 Python
Virtualenv 搭建 Py项目运行环境的教程详解
2020/06/22 Python
python读取excel进行遍历/xlrd模块操作
2020/07/12 Python
如何让PyQt5中QWebEngineView与JavaScript交互
2020/10/21 Python
canvas使用注意点总结
2013/07/19 HTML / CSS
html5中svg canvas和图片之间相互转化思路代码
2014/01/24 HTML / CSS
2014年学习部工作总结
2014/11/12 职场文书
2015年小学生国庆节演讲稿
2015/07/30 职场文书
大学优秀学生主要事迹材料
2015/11/04 职场文书
只用20行Python代码实现屏幕录制功能
2021/06/02 Python
pytorch fine-tune 预训练的模型操作
2021/06/03 Python
你需要掌握的20个Python常用技巧
2022/02/28 Python
安装harbor作为docker镜像仓库的问题
2022/06/14 Servers