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 相关文章推荐
Perl中著名的Schwartzian转换问题解决实现
Jun 02 Python
Python中实现变量赋值传递时的引用和拷贝方法
Apr 29 Python
mac PyCharm添加Python解释器及添加package路径的方法
Oct 29 Python
Python实现代码统计工具
Sep 19 Python
PyTorch 随机数生成占用 CPU 过高的解决方法
Jan 13 Python
python GUI库图形界面开发之PyQt5切换按钮控件QPushButton详细使用方法与实例
Feb 28 Python
pycharm激活码快速激活及使用步骤
Mar 12 Python
jupyter notebook 多行输出实例
Apr 09 Python
简述python Scrapy框架
Aug 17 Python
Python+OpenCV图像处理——实现直线检测
Oct 23 Python
python使用scapy模块实现ping扫描的过程详解
Jan 21 Python
python中 .npy文件的读写操作实例
Apr 14 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
DC动画很好看?新作烂得令人发指,名叫《红色之子》
2020/04/09 欧美动漫
PHP中使用gettext来支持多语言的方法
2011/05/02 PHP
如何突破PHP程序员的技术瓶颈分析
2011/07/17 PHP
PHP动态创建Web站点的方法
2011/08/14 PHP
Yii Framework框架获取分类下面的所有子类方法
2014/06/20 PHP
php使用pack处理二进制文件的方法
2014/07/03 PHP
php控制文件下载速度的方法
2015/03/24 PHP
php表单加入Token防止重复提交的方法分析
2016/10/10 PHP
兼容FF和IE的动态table示例自写
2013/10/21 Javascript
AngularJs Javascript MVC 框架
2016/06/20 Javascript
JavaScript lodash常见用法系列小结
2016/08/24 Javascript
JS实现中文汉字按拼音排序的方法
2017/10/09 Javascript
解决vue页面刷新或者后退参数丢失的问题
2018/03/13 Javascript
Vue使用localStorage存储数据的方法
2019/05/27 Javascript
微信小程序转化为uni-app项目的方法示例
2020/05/22 Javascript
不依任何赖第三方,单纯用vue实现Tree 树形控件的案例
2020/09/21 Javascript
python实现搜索指定目录下文件及文件内搜索指定关键词的方法
2015/06/28 Python
python socket多线程通讯实例分析(聊天室)
2016/04/06 Python
Python实现压缩和解压缩ZIP文件的方法分析
2017/09/28 Python
python中format()函数的简单使用教程
2018/03/14 Python
python turtle 绘制太极图的实例
2019/12/18 Python
Python3常见函数range()用法详解
2019/12/30 Python
python使用pymongo与MongoDB基本交互操作示例
2020/04/09 Python
python的pip有什么用
2020/06/17 Python
英国领先的在线高尔夫设备零售商:Golfgeardirect
2020/12/11 全球购物
托管代码(Managed Code)和非托管代码(Unmanaged Code)有什么区别
2014/09/29 面试题
中专生的个人自我评价
2013/12/11 职场文书
创业计划书——互联网商机
2014/01/12 职场文书
八一建军节感言
2014/02/28 职场文书
春风行动实施方案
2014/03/28 职场文书
林肯就职演讲稿
2014/05/19 职场文书
机关作风建设自查报告
2014/10/22 职场文书
2015年政风行风工作总结
2015/04/21 职场文书
《初涉尘世》读后感3篇
2020/01/10 职场文书
分享7个 Python 实战项目练习
2022/03/03 Python
python超详细实现完整学生成绩管理系统
2022/03/17 Python