如何重写Django Admin的save_model方法和get_queryset方法

在Django基础(19): Django Admin管理后台详解(上)中小编我介绍了如何创建superuser,如何自定义数据表的显示选项(list_display, list_filter, list_per_page, list_editable, ordering),如何更好地显示单对多(raw_id_fields)和多对多关系(filter_horizontal),如何使用Inlines显示多张数据表在同一页面上。今天我们来看下django admin的一些高级技巧,比如如何重写django admin的save方法和get_queryset方法。

重写Django admin的save_model方法

 

很多时候,我们需要重写Django自带的save_model方法。比如在文章创建时我们希望在后台自动添加作者,而不是允许用户自己选择作者是谁,我们可以选择在创建文章的表单里把作者隐藏,而在后台添加作者。如下所示:

from django.contrib import admin

class ArticleAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.author = request.user
        super().save_model(request, obj, form, change)

在我们世界那么大,我想去看看。Django仿制微信朋友圈九宫格相册(1)一文中我们也展示了save_model方法的重写,该方法作用是允许用户在创建Album对象时,还上传一个zip文件包。上传后对zip文件包进行解压存储,并与每个Image对象想关联。

# album/forms.py

from django import forms
from .models import Album


class AlbumForm(forms.ModelForm):
    class Meta:
        model = Album
        exclude = []

    zip = forms.FileField(required=False)

# album/admin.py

import os
import uuid
import zipfile
from django.contrib import admin
from django.core.files.base import ContentFile
from .models import Album, AlbumImage
from .forms import AlbumForm


@admin.register(Album)
class AlbumModelAdmin(admin.ModelAdmin):
    form = AlbumForm
    prepopulated_fields = {'slug': ('title',)}
    list_display = ('title', 'thumb')
    list_filter = ('create_date',)

    def save_model(self, request, obj, form, change):
        if form.is_valid():
            album = form.save()

            if form.cleaned_data['zip'] is not None:
                zip = zipfile.ZipFile(form.cleaned_data['zip'])
                for filename in sorted(zip.namelist()):

                    file_name = os.path.basename(filename)
                    if not file_name:
                        continue

                    data = zip.read(filename)
                    contentfile = ContentFile(data)

                    img = AlbumImage()
                    img.album = album
                    filename = '{0}{1}.jpg'.format(album.slug[:8], str(uuid.uuid4())[-13:])
                    img.alt = filename
                    img.image.save(filename, contentfile)

                    img.thumb.save('thumb-{0}'.format(filename), contentfile)
                    img.save()
                zip.close()
            super().save_model(request, obj, form, change)

还记得我们Django 2.0 项目实战: 扩展Django自带User模型,实现用户注册与登录中对django的User模型做的扩展吗?我们新建了一个UserProfile模型,其与User是一对一的关系。我们现在希望在admin中创建一个User对象时,也同时创建一个UserProfile对象,这时我们就需要用到save_model方法的重写了。代码如下所示:

#myaccount/admin.py

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from .models import UserProfile

admin.site.unregister(User)


class UserProfileInline(admin.StackedInline):
    model = UserProfile
    exclude = ["uid", "join_date", "mod_date"]


class UserAdmin(UserAdmin):
    inlines = [UserProfileInline, ]

    def save_model(self, request, obj, form, change):
        if form.is_valid():
            user = form.save()
            user_profile = UserProfile()
            user_profile.user = user
            user_profile.save()

        super().save_model(request, obj, form, change)


class UserProfileAdmin(admin.ModelAdmin):
    list_display = ('user', 'avatar', 'org', 'join_date')
    exclude = []
    ordering = ('-join_date',)


admin.site.register(User, UserAdmin)
admin.site.register(UserProfile, UserProfileAdmin)

展示效果如下。我们使用了Inlines使UserProfile与User展示在同一页面上。由于我们重写了save_model方法,这样可以自动在创建User时也创建UserProfile,避免了只创建User而未创建UserProfile的错误,这对1对1的关系非常重要。

如何重写Django Admin的save_model方法和get_queryset方法_第1张图片

重写Django admin的get_queryset方法

 

Django的admin默认会展示所有对象。通过重写get_queryset方法,我们可以控制所需要获取的对象。比如下例中,我们先对用户进行判定,如果用户是超级用户就展示所有文章,如果不是超级用户,我们仅展示用户自己所发表的文章。

class ArticleAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(author=request.user)

 

小结

本文总结了django admin的一些高级技巧,比如如何自定义list_display和list_filter, 以及如何重写django admin的save方法和get_queryset方法。这些方法和技巧都非常有用,要熟练掌握哦。下文将是django admin介绍的最后一篇,小编我将介绍下如何美化django-admin,欢迎关注。

 

大江狗

2018.11.3

Django Web开发核心基础知识

Django网站开发四件套是如何遵循MVC软件设计模式的?

Django基础核心技术介绍(1): Model模型的介绍与设计

Django基础核心技术介绍(2): URL的设计与配置

Django基础核心技术介绍(3): View视图详解与通用视图

Django基础核心技术介绍(4): Template模板的编写及过滤器

Django基础核心结束介绍(5): Forms表单的使用与设计

Django基础(6): 模型Models高级进阶必读。

Django基础(7): cookie和session应用场景及如何使用

Django基础(8): 缓存Cache应用场景及工作原理,Cache设置及如何使用

Django基础(9): 表单Forms的高级使用技巧

Django基础(10): URL重定向的HttpResponseDirect, redirect和reverse的用法

Django基础(11): 表单集合Formset的高级用法

Django基础(12): Request对象详解及开发显示用户IP地址和浏览器APP

Django基础(13): 深夜放干货。QuerySet特性及高级使用技巧,如何减少数据库的访问,节省内存,提升网站性能。

Django基础(14): 通过next参数实现登录后跳转回到前一页的3种方法

Django基础(15): 模板过滤器(filter)的工作原理及如何自定义模板过滤器

Django基础(16): 模板标签(tags)的分类及如何自定义模板标签

Django基础(17): 如何上传处理文件及Ajax文件上传示范(附GitHub源码)

Django基础(18): 实现文件下载的3种方法及文件私有化

Django基础(19): Django Admin管理后台详解(上)

Django基础(20): Django admin管理后台详解(中)如何自定义list_display和list_filter

Django基础(21): Django admin管理后台详解(下)如何自定义actions, 表单和美化admin

Django基础(22): 数据库的设计之自定义表名,建立索引和使用多数据库主从配置

Django基础(23): 权限管理(permissions)与用户组(group)详解

Django基础(24): aggregate和annotate方法使用详解与示例

Django基础(25):settings.py设置选项深入解读。大江狗精品原创。

Django基础(26): 常用装饰器应用场景及正确使用方法

Django基础(27): 快捷函数(shortcut function)模块详解Django基础(28): 如何设计充满陷阱的优美URL

Django基础(28): 如何设计充满陷阱的优美URL

 

Django Web开发实战案例

Django 2.0 项目实战(1): 扩展Django自带User模型,实现用户注册与登录

Django 2.0 项目实战(2): 编辑用户个人资料,扩展Django后台UserAdmin

Django 2.0项目实战(3): 密码重置与退出登录

Django 2.0 项目实战: 图片上传与显示

Django 2.0 项目实战: PDF文件页面提取

Django 2.0 项目实战: PDF文件合并

Django 2.0 项目实战:输出树形分类目录

Django 2.0 项目实战: 网页计数器统计浏览次数

Django 2.0 项目实战:  利用AJAX实现博文实时搜索

Django 1.X和2.0下利用自带分页Paginator类实现分页功能

Django实战: 利用Ajax生成联动下拉菜单

世界那么大,我想去看看。Django仿制微信朋友圈九宫格相册(1)

世界那么大,我想去看看。Django仿制微信朋友圈九宫格相册(2)

django-allauth教程(1): 安装,用户注册,登录,邮箱验证和密码重置(更新)

django-allauth教程(2): 用户个人资料UserProfile扩展与编辑

django-allauth教程(3): 第三方账户授权登录(以百度账号为例)

django-allauth教程(4): 美化模板,自定义邮件和消息内容

Django+jQuery cropper实现用户头像裁剪, 预览和上传[原创]

Django实战教程: 开发餐厅在线点评网站(1)

Django实战教程: 开发餐厅在线点评网站(2)

Django实战教程: 开发企业级应用智能文档管理系统smartdoc(1)

Django实战教程: 开发企业级应用智能文档管理系统smartdoc(2)之权限管理

Django实战教程: 开发企业级应用智能文档管理系统smartdoc(3)附GitHub代码地址

Django实战专题: 开发专业博客(1)之内容管理后台开发

Django实战专题: 开发专业博客(2)之母子类别导航和添加富文本编辑器CKEditor

Django实战专题: 开发专业博客(3)之仿微信评论点赞功能

Django实战: Python爬取链家上海二手房信息,存入数据库并在前端显示

Django应用实战: 编写你自己的PDF编辑器, 实现PDF页面提取, 页面合并与替换。

如何在阿里云Ubuntu服务器通过uWSGI和Nginx部署Django项目教程-大江狗原创出品

 

Django Web开发学习笔记

浅谈Django Model创建对象的save与create方法

Django模板设置全局变量(默认变量)

Django常用命令django-admin.py和manage.py用法详解

Django自定义图片和文件上传路径(upload_to)的2种方式

Django ContentTypes框架详解及使用场景介绍

Django更改模型过程中易出现的问题及解决方案

2019新年第一篇: SQLite的优缺点及Django配置MySQL数据库

如何重写Django Admin的save_model方法和get_queryset方法_第2张图片

你可能感兴趣的:(Django)