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 os模块中的isfile()和isdir()函数均返回false问题解决方法
Feb 04 Python
node.js获取参数的常用方法(总结)
May 29 Python
Python实现matplotlib显示中文的方法详解
Feb 06 Python
Python中循环后使用list.append()数据被覆盖问题的解决
Jul 01 Python
Django中日期处理注意事项与自定义时间格式转换详解
Aug 06 Python
对python中词典的values值的修改或新增KEY详解
Jan 20 Python
python找出一个列表中相同元素的多个索引实例
Jun 11 Python
python3安装crypto出错及解决方法
Jul 30 Python
Python整数与Numpy数据溢出问题解决
Sep 11 Python
解决Python3下map函数的显示问题
Dec 04 Python
使用OpenCV对车道进行实时检测的实现示例代码
Jun 19 Python
call在Python中改进数列的实例讲解
Dec 09 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邮件专题
2006/10/09 PHP
php基于Fleaphp框架实现cvs数据导入MySQL的方法
2016/02/23 PHP
PHP实现求连续子数组最大和问题2种解决方法
2017/12/26 PHP
JQuery 无废话系列教程(一) jquery入门 [推荐]
2009/06/23 Javascript
jQuery 数据缓存data(name, value)详解及实现
2010/01/04 Javascript
div层的移动及性能优化
2010/11/16 Javascript
js内存泄露的几种情况详细探讨
2013/05/31 Javascript
jquery操作下拉列表、文本框、复选框、单选框集合(收藏)
2014/01/08 Javascript
JavaScript中的正则表达式简明总结
2014/04/04 Javascript
JavaScript实现判断图片是否加载完成的3种方法整理
2015/03/13 Javascript
js鼠标点击按钮切换图片-图片自动切换-点击左右按钮切换特效代码
2015/09/02 Javascript
用vue和node写的简易购物车实现
2017/04/25 Javascript
vue.js移动端tab组件的封装实践实例
2017/06/30 Javascript
VSCode中如何利用d.ts文件进行js智能提示
2018/04/13 Javascript
JavaScript格式化json和xml的方法示例
2019/01/22 Javascript
vue实现评价星星功能
2020/06/30 Javascript
vue打包通过image-webpack-loader插件对图片压缩优化操作
2020/11/12 Javascript
JQuery绑定事件四种实现方法解析
2020/12/02 jQuery
Python的消息队列包SnakeMQ使用初探
2016/06/29 Python
Flask-Mail用法实例分析
2018/07/21 Python
搞定这套Python爬虫面试题(面试会so easy)
2019/04/03 Python
Linux下远程连接Jupyter+pyspark部署教程
2019/06/21 Python
python高阶函数map()和reduce()实例解析
2020/03/16 Python
CSS3属性 line-clamp控制文本行数的使用
2020/03/19 HTML / CSS
web页面录屏实现
2019/02/12 HTML / CSS
Rakuten Kobo台湾:电子书、eReaders和Reading应用程式
2017/11/24 全球购物
意大利奢侈品综合电商网站:MODES
2019/12/14 全球购物
STRATHBERRY苏贝瑞包包官网:西班牙高级工匠手工打造
2020/11/10 全球购物
党校学习思想汇报
2014/01/06 职场文书
试用期员工考核制度
2014/01/22 职场文书
学习十八大标语
2014/10/09 职场文书
2014教师年度工作总结
2014/11/10 职场文书
毕业论文答辩开场白
2015/05/27 职场文书
三好学生主要事迹材料
2015/11/03 职场文书
2016元旦晚会主持人开场白和结束语
2015/12/03 职场文书
apache虚拟主机配置的三种方式(小结)
2022/07/23 Servers