Python 现代开发学习笔记

(十九)操作权限与对象归属分别判断

Book 的 Meta.permissions 增加 library.export_book。迁移后 Django 建立这条权限,用户或组取得它后,has_perm 可以检查。书架页面按 perms.library.export_book 显示导出按钮,入口也执行同一权限要求:

# 续写同一文件:reading_project/src/library/views.py
@login_required
@permission_required("library.export_book", raise_exception=True)
def export_books(request):
    # 全局操作权限通过后,仍然只查询当前用户的记录。
    response = HttpResponse(content_type="text/csv; charset=utf-8")
    response["Content-Disposition"] = 'attachment; filename="books.csv"'
    response.write("\ufeff")
    writer = csv.writer(response)
    writer.writerow(["title", "finished", "tags"])
    for book in Book.objects.filter(owner=request.user).prefetch_related("tags"):
        writer.writerow(
            [
                book.title,
                int(book.finished),
                json.dumps([tag.name for tag in book.tags.all()], ensure_ascii=False),
            ]
        )
    return response

permission_required(..., raise_exception=True) 对已登录但没有该操作权限的用户返回 403。通过后仍只查 owner=request.user,所以“可以导出”并没有变成“可以导出其他人的书”。

CSV 响应设置内容类型与下载文件名,csv.writer 把普通列表逐行写进响应,开头的 BOM 帮助常用表格程序识别 UTF-8。导出可以接回第十一章的数据分析。

# 项目文件:demos/permission_steps.py
# 比较普通账户、持有权限的账户和管理员,让同一操作展示不同权限结果。
from lab import lab

with lab():
    from django.contrib.auth import get_user_model
    from django.test import Client

    User = get_user_model()
    for name in ["alice", "bob", "manager"]:
        user = User.objects.get(username=name)
        client = Client()
        client.force_login(user)
        print(
            name,
            "后台标记",
            user.is_staff,
            "导出权限",
            user.has_perm("library.export_book"),
            "导出响应",
            client.get("/export.csv").status_code,
        )
    manager = User.objects.get(username="manager")
    print("manager 模型修改权限", manager.has_perm("library.change_book"))
    print("manager 书架条数", manager.books.count())

alice 获得导出权限,bob 没有,manager 获得后台书籍模型维护权限但没有导出权限。is_staff 负责后台入口,模型操作权限、用户组和记录归属继续分别判断。

先验证是否登录,再检查 export_book 操作权限,通过后继续按当前 owner 查询,bob 在权限处停止,alice 只能导出自己的书

笔记正文与全部题解 · Ctrl / ⌘ K