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天气预报采集器实现代码(网页爬虫)
Oct 07 Python
跟老齐学Python之编写类之三子类
Oct 11 Python
python通过apply使用元祖和列表调用函数实例
May 26 Python
尝试使用Python多线程抓取代理服务器IP地址的示例
Nov 09 Python
深入理解Python单元测试unittest的使用示例
Nov 18 Python
python中返回矩阵的行列方法
Apr 04 Python
利用Python实现Shp格式向GeoJSON的转换方法
Jul 09 Python
python pandas 时间日期的处理实现
Jul 30 Python
浅谈Python中(&amp;,|)和(and,or)之间的区别
Aug 07 Python
python飞机大战pygame碰撞检测实现方法分析
Dec 17 Python
python实现批量修改文件名
Mar 23 Python
解决python和pycharm安装gmpy2 出现ERROR的问题
Aug 28 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
PHP $_FILES中error返回值详解
2014/01/30 PHP
php_imagick实现图片剪切、旋转、锐化、减色或增加特效的方法
2014/12/15 PHP
PHP框架Laravel学习心得体会
2015/10/28 PHP
基于PHP实现商品成交时发送短信功能
2016/05/11 PHP
中高级PHP程序员应该掌握哪些技术?
2016/09/23 PHP
php函数mkdir实现递归创建层级目录
2016/10/27 PHP
麦鸡的TAB切换功能结合了javascript和css
2007/12/17 Javascript
学习ExtJS border布局
2009/10/08 Javascript
JavaScript中数据结构与算法(一):栈
2015/06/19 Javascript
Underscore.js 1.3.3 中文注释翻译说明
2015/06/25 Javascript
jQuery实现点击按钮文字变成input框点击保存变成文字
2016/05/09 Javascript
BootStrap使用file-input插件上传图片的方法
2016/09/05 Javascript
iOS和Android用同一个二维码实现跳转下载链接的方法
2016/09/28 Javascript
jQuery日期范围选择器附源码下载
2017/05/23 jQuery
Angular 4依赖注入学习教程之简介(一)
2017/06/04 Javascript
js判断用户是输入的地址请求的路径(实例讲解)
2017/07/18 Javascript
详解webpack与SPA实践之开发环境搭建
2017/12/18 Javascript
详解vue组件开发脚手架
2018/06/15 Javascript
angularjs $http调用接口的方式详解
2018/08/13 Javascript
基于vue实现一个神奇的动态按钮效果
2019/05/15 Javascript
Vue结合路由配置递归实现菜单栏功能
2020/06/16 Javascript
[01:45]绝对公平!DOTA2队长征召模式详解
2014/04/25 DOTA
Python 正则表达式(转义问题)
2014/12/15 Python
python使用自定义user-agent抓取网页的方法
2015/04/15 Python
python脚本实现数据导出excel格式的简单方法(推荐)
2016/12/30 Python
基于Python列表解析(列表推导式)
2018/06/23 Python
解决json中ensure_ascii=False的问题
2020/04/03 Python
HTML+CSS3模拟心的跳动实例代码
2017/09/05 HTML / CSS
C,C++的几个面试题小集
2013/07/13 面试题
Linux管理员面试经常问道的相关命令
2014/12/12 面试题
初二学习计划书范文
2014/04/27 职场文书
公司承诺书怎么写
2014/05/24 职场文书
乡文化站暑期培训方案
2014/08/28 职场文书
关于拾金不昧的感谢信
2015/01/21 职场文书
高二数学教学反思
2016/02/18 职场文书
MySQL数据库 任意ip连接方法
2022/05/20 MySQL