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根据区号生成手机号码的方法
Jul 08 Python
浅谈Python浅拷贝、深拷贝及引用机制
Dec 15 Python
高质量Python代码编写的5个优化技巧
Nov 16 Python
hmac模块生成加入了密钥的消息摘要详解
Jan 11 Python
Python实现随机生成手机号及正则验证手机号的方法
Apr 25 Python
Python 给定的经纬度标注在地图上的实现方法
Jul 05 Python
python各层级目录下import方法代码实例
Jan 20 Python
快速解决jupyter启动卡死的问题
Apr 10 Python
Python 的 __str__ 和 __repr__ 方法对比
Sep 02 Python
Python+unittest+DDT实现数据驱动测试
Nov 30 Python
Python获取指定网段正在使用的IP
Dec 14 Python
深入理解python多线程编程
Apr 18 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
在PHP3中实现SESSION的功能(三)
2006/10/09 PHP
dedecms系统的广告设置代码 基础版本
2010/04/09 PHP
几种有用的变型 PHP中循环语句的用法介绍
2012/01/30 PHP
ThinkPHP自动完成中使用函数与回调方法实例
2014/11/29 PHP
Zend Framework框架中实现Ajax的方法示例
2017/06/27 PHP
JS 学习笔记 防止发生命名冲突
2009/07/30 Javascript
js ondocumentready onmouseover onclick onmouseout 样式
2010/07/22 Javascript
javascript怎么禁用浏览器后退按钮
2014/03/27 Javascript
JS中FRAME的操作问题实例分析
2014/10/21 Javascript
使用window.prompt()实现弹出用户输入的对话框
2015/04/13 Javascript
移动端使用localResizeIMG4压缩图片
2017/04/22 Javascript
Vue.js中轻松解决v-for执行出错的三个方案
2017/06/09 Javascript
使用JQuery实现图片轮播效果的实例(推荐)
2017/10/24 jQuery
Vue中对拿到的数据进行A-Z排序的实例
2018/09/25 Javascript
vue柱状进度条图像的完美实现方案
2019/08/26 Javascript
IE11下CKEditor在Bootstrap Modal中下拉问题的解决
2019/09/25 Javascript
[01:11:11]Alliance vs RNG 2019国际邀请赛淘汰赛 败者组BO1 8.20.mp4
2020/07/19 DOTA
[06:48]DOTA2-DPC中国联赛2月26日Recap集锦
2021/03/11 DOTA
Python 文件读写操作实例详解
2014/03/12 Python
Python解析excel文件存入sqlite数据库的方法
2016/11/15 Python
python如何获取服务器硬件信息
2017/05/11 Python
Python求两点之间的直线距离(2种实现方法)
2019/07/07 Python
虚拟机下载python是否需要联网
2020/07/27 Python
德国汽车零件和汽车配件网上商店:kfzteile24
2018/11/14 全球购物
护理职业应聘自荐书
2013/09/29 职场文书
生产厂厂长岗位职责
2013/12/25 职场文书
关于人生的感言
2014/01/17 职场文书
合伙协议书范本
2014/04/21 职场文书
超市理货员岗位职责
2014/07/04 职场文书
助人为乐好少年事迹材料
2014/08/18 职场文书
英语课前三分钟演讲稿(6篇)
2014/09/13 职场文书
2014年安全生产工作总结
2014/11/13 职场文书
雷峰塔导游词
2015/02/09 职场文书
机器人瓦力观后感
2015/06/12 职场文书
Mysql多层子查询示例代码(收藏夹案例)
2022/03/31 MySQL
前端使用svg图片改色实现示例
2022/07/23 HTML / CSS