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运算π的值深入Python中科学计算的实现
Apr 17 Python
python虚拟环境virtualenv的安装与使用
Sep 21 Python
详解Python 定时框架 Apscheduler原理及安装过程
Jun 14 Python
python2爬取百度贴吧指定关键字和图片代码实例
Aug 14 Python
python数据持久存储 pickle模块的基本使用方法解析
Aug 30 Python
Python操作qml对象过程详解
Sep 26 Python
Python OpenCV图像指定区域裁剪的实现
Oct 30 Python
Python函数的返回值、匿名函数lambda、filter函数、map函数、reduce函数用法实例分析
Dec 26 Python
python怎么删除缓存文件
Jul 19 Python
Python txt文件如何转换成字典
Nov 03 Python
解决import tensorflow导致jupyter内核死亡的问题
Feb 06 Python
pandas进行数据输入和输出的方法详解
Mar 23 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回溯法解决0-1背包问题实例分析
2015/03/23 PHP
php实现多站点共用session实现单点登录的方法详解
2019/09/18 PHP
php使用gearman进行任务分发操作实例详解
2020/02/26 PHP
Prototype 工具函数 学习
2009/07/23 Javascript
jquery模拟按下回车实现代码
2011/09/20 Javascript
关于火狐(firefox)及ie下event获取的两种方法
2012/12/27 Javascript
关闭页面时window.location事件未执行的原因分析及解决方案
2014/09/01 Javascript
javascript搜索框点击文字消失失焦时文本出现
2014/09/18 Javascript
jQuery读取XML文件内容的方法
2015/03/09 Javascript
纯js模拟div层弹性运动的方法
2015/07/27 Javascript
jQuery中常用的遍历函数用法实例总结
2015/09/01 Javascript
javascript同步服务器时间和同步倒计时小技巧
2015/09/24 Javascript
JavaScript实现的SHA-1加密算法完整实例
2016/02/02 Javascript
jQuery Easyui加载表格出错时在表格中间显示自定义的提示内容
2016/12/08 Javascript
node.js+jQuery实现用户登录注册AJAX交互
2017/04/28 jQuery
微信小程序 获取javascript 里的数据
2017/08/17 Javascript
微信小程序 如何获取网络状态
2019/07/26 Javascript
vue学习笔记之给组件绑定原生事件操作示例
2020/02/27 Javascript
js实现全选和全不选功能
2020/07/28 Javascript
[02:14]完美“圣”典2016风云人物:xiao8专访
2016/12/01 DOTA
详解python之简单主机批量管理工具
2017/01/27 Python
Python Django框架单元测试之文件上传测试示例
2019/05/17 Python
Python实现搜索算法的实例代码
2020/01/02 Python
AUC计算方法与Python实现代码
2020/02/28 Python
AmazeUI的JS表单验证框架实战示例分享
2020/08/21 HTML / CSS
鱼油专家:Omegavia
2016/10/10 全球购物
巴西男士胡须和头发护理产品商店:Beard
2017/11/13 全球购物
英国团购网站:Groupon英国
2017/11/28 全球购物
SOKOLOV官网:俄罗斯珠宝首饰品牌
2021/01/02 全球购物
党章学习思想汇报
2014/01/14 职场文书
战友聚会邀请函
2014/01/18 职场文书
本科毕业生求职信
2014/06/15 职场文书
电子信息工程专业求职信
2014/06/28 职场文书
2015年体检中心工作总结
2015/05/27 职场文书
java后台调用接口及处理跨域问题的解决
2022/03/24 Java/Android
MySQL详解进行JDBC编程与增删改查方法
2022/06/16 MySQL