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程序代码片段
Jun 02 Python
横向对比分析Python解析XML的四种方式
Mar 30 Python
Python实现基于KNN算法的笔迹识别功能详解
Jul 09 Python
python简单操作excle的方法
Sep 12 Python
PyQt5的PyQtGraph实践系列3之实时数据更新绘制图形
May 13 Python
如何在VSCode上轻松舒适的配置Python的方法步骤
Oct 28 Python
python pprint模块中print()和pprint()两者的区别
Feb 10 Python
Spark处理数据排序问题如何避免OOM
May 21 Python
如何基于Django实现上下文章跳转
Sep 16 Python
Python paramiko使用方法代码汇总
Nov 20 Python
python基础详解之if循环语句
Apr 24 Python
Django+Celery实现定时任务的示例
Jun 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 自定义错误处理函数trigger_error()
2013/03/26 PHP
Joomla语言翻译类Jtext用法分析
2016/05/05 PHP
php简单构造json多维数组的方法示例
2017/06/08 PHP
php实现文件上传基本验证
2020/03/04 PHP
jQuery 学习 几种常用方法
2009/06/11 Javascript
常用Extjs工具:Extjs.util.Format使用方法
2012/03/22 Javascript
JavaScript从数组中删除指定值元素的方法
2015/03/18 Javascript
JavaScript入门基础
2015/08/12 Javascript
基于jQuery实现表格的查看修改删除
2016/08/01 Javascript
轮播图组件js代码
2016/08/08 Javascript
js 获取当前web应用的上下文路径实现方法
2016/08/19 Javascript
在网页中插入百度地图的步骤详解
2016/12/02 Javascript
Vue 页面状态保持页面间数据传输的一种方法(推荐)
2018/11/01 Javascript
JS中注入eval, Function等系统函数截获动态代码
2019/04/03 Javascript
Vue.js@2.6.10更新内置错误处机制Fundebug同步支持相应错误监控
2019/05/13 Javascript
[07:54]DOTA2 MV《我的动力鞋》 ImbaTV 出品
2014/11/21 DOTA
[04:48]DOTA2亚洲邀请赛林书豪为VGJ加油
2017/04/01 DOTA
[01:29:42]Liquid vs VP Supermajor决赛 BO 第一场 6.10
2018/07/05 DOTA
numpy返回array中元素的index方法
2018/06/27 Python
python字典值排序并取出前n个key值的方法
2018/10/17 Python
Python tkinter实现图片标注功能(完整代码)
2019/12/08 Python
tf.concat中axis的含义与使用详解
2020/02/07 Python
踩坑:pytorch中eval模式下结果远差于train模式介绍
2020/06/23 Python
Keras: model实现固定部分layer,训练部分layer操作
2020/06/28 Python
python中的split、rsplit、splitlines用法说明
2020/10/23 Python
详解通过focusout事件解决IOS键盘收起时界面不归位的问题
2019/07/18 HTML / CSS
师范生个人推荐信
2013/11/29 职场文书
大学生期末自我鉴定
2014/02/01 职场文书
国际贸易专业个人求职信格式
2014/02/02 职场文书
酒店爱岗敬业演讲稿
2014/09/02 职场文书
镇党委书记群众路线整改措施思想汇报
2014/10/13 职场文书
检查机关领导群众路线教育实践活动个人整改措施
2014/10/28 职场文书
离职报告格式
2014/11/04 职场文书
【超详细】八大排序算法的各项比较以及各自特点
2021/03/31 Python
Vue全家桶入门基础教程
2021/05/14 Vue.js
2022微信温控新功能上线
2022/05/09 数码科技