关于“Python”的核心知识点整理大全59

目录

19.3.2 将数据关联到用户

1. 修改模型Topic

models.py

2. 确定当前有哪些用户

3. 迁移数据库

注意

19.3.3 只允许用户访问自己的主题

views.py

19.3.4 保护用户的主题

views.py

views.py

19.3.6 将新主题关联到当前用户

views.py

往期快速传送门👆(在文章最后):

感谢大家的支持!欢迎订阅收藏!专栏将持续更新!


19.3.2 将数据关联到用户

现在,需要将数据关联到提交它们的用户。我们只需将最高层的数据关联到用户,这样更低 层的数据将自动关联到用户。例如,在项目“学习笔记”中,应用程序的最高层数据是主题,而 所有条目都与特定主题相关联。只要每个主题都归属于特定用户,我们就能确定数据库中每个条 目的所有者。

下面来修改模型Topic,在其中添加一个关联到用户的外键。这样做后,我们必须对数据库 进行迁移。最后,我们必须对有些视图进行修改,使其只显示与当前登录的用户相关联的数据。

1. 修改模型Topic

对models.py的修改只涉及两行代码:

models.py
from django.db import models
from django.contrib.auth.models import User
class Topic(models.Model):"""用户要学习的主题"""text = models.CharField(max_length=200)date_added = models.DateTimeField(auto_now_add=True)owner = models.ForeignKey(User)def __str__(self):"""返回模型的字符串表示"""return self.text
class Entry(models.Model):--snip-- 

我们首先导入了django.contrib.auth中的模型User,然后在Topic中添加了字段owner,它建 立到模型User的外键关系。

2. 确定当前有哪些用户

我们迁移数据库时,Django将对数据库进行修改,使其能够存储主题和用户之间的关联。为 执行迁移,Django需要知道该将各个既有主题关联到哪个用户。最简单的办法是,将既有主题都 关联到同一个用户,如超级用户。为此,我们需要知道该用户的ID。

下面来查看已创建的所有用户的ID。为此,启动一个Django shell会话,并执行如下命令:

(venv)learning_log$ python manage.py shell
1 >>> from django.contrib.auth.models import User
2 >>> User.objects.all()
[<User: ll_admin>, <User: eric>, <User: willie>]
3 >>> for user in User.objects.all():
... print(user.username, user.id)
...
ll_admin 1
eric 2
willie 3
>>> 

在1处,我们在shell会话中导入了模型User。然后,我们查看到目前为止都创建了哪些用户 (见2)。输出中列出了三个用户:ll_admin、eric和willie。

在3处,我们遍历用户列表,并打印每位用户的用户名和ID。Django询问要将既有主题关联 到哪个用户时,我们将指定其中的一个ID值。

3. 迁移数据库

知道用户ID后,就可以迁移数据库了。

1 (venv)learning_log$ python manage.py makemigrations learning_logs
2 You are trying to add a non-nullable field 'owner' to topic without a default;
we can't do that (the database needs something to populate existing rows).
3 Please select a fix:
1) Provide a one-off default now (will be set on all existing rows)
2) Quit, and let me add a default in models.py
4 Select an option: 1
5 Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now()
6 >>> 1
Migrations for 'learning_logs':0003_topic_owner.py:- Add field owner to topic 

我们首先执行了命令makemigrations(见1)。在2处的输出中,Django指出我们试图给既有 模型Topic添加一个必不可少(不可为空)的字段,而该字段没有默认值。在3处,Django给我 们提供了两种选择:要么现在提供默认值,要么退出并在models.py中添加默认值。在4处,我们 选择了第一个选项,因此Django让我们输入默认值(见5)。

为将所有既有主题都关联到管理用户ll_admin,我输入了用户ID值1(见6)。并非必须使用 超级用户,而可使用已创建的任何用户的ID。接下来,Django使用这个值来迁移数据库,并生成 了迁移文件0003_topic_owner.py,它在模型Topic中添加字段owner。

现在可以执行迁移了。为此,在活动的虚拟环境中执行下面的命令:

(venv)learning_log$ python manage.py migrate
Operations to perform:Synchronize unmigrated apps: messages, staticfilesApply all migrations: learning_logs, contenttypes, sessions, admin, auth
--snip--
Running migrations:Rendering model states... DONE
1 Applying learning_logs.0003_topic_owner... OK
(venv)learning_log$ 

Django应用新的迁移,结果一切顺利(见1)。

为验证迁移符合预期,可在shell会话中像下面这样做:

1 >>> from learning_logs.models import Topic
2 >>> for topic in Topic.objects.all():
... print(topic, topic.owner)
...
Chess ll_admin
Rock Climbing ll_admin
>>>

我们从learning_logs.models中导入Topic(见1),再遍历所有的既有主题,并打印每个主 题及其所属的用户(见2)。正如你看到的,现在每个主题都属于用户ll_admin。


注意

你可以重置数据库而不是迁移它,但如果这样做,既有的数据都将丢失。一种不错的做 法是,学习如何在迁移数据库的同时确保用户数据的完整性。如果你确实想要一个全新 的数据库,可执行命令python manage.py flush,这将重建数据库的结构。如果你这样做, 就必须重新创建超级用户,且原来的所有数据都将丢失。


19.3.3 只允许用户访问自己的主题

当前,不管你以哪个用户的身份登录,都能够看到所有的主题。我们来改变这种情况,只向 用户显示属于自己的主题。 在views.py中,对函数topics()做如下修改:

views.py
--snip--
@login_required
def topics(request):"""显示所有的主题"""topics = Topic.objects.filter(owner=request.user).order_by('date_added')context = {'topics': topics}return render(request, 'learning_logs/topics.html', context)
--snip--

用户登录后,request对象将有一个user属性,这个属性存储了有关该用户的信息。代码 Topic.objects.filter(owner=request.user)让Django只从数据库中获取owner属性为当前用户的 Topic对象。由于我们没有修改主题的显示方式,因此无需对页面topics的模板做任何修改。 要查看结果,以所有既有主题关联到的用户的身份登录,并访问topics页面,你将看到所有 的主题。然后,注销并以另一个用户的身份登录,topics页面将不会列出任何主题。

19.3.4 保护用户的主题

我们还没有限制对显示单个主题的页面的访问,因此任何已登录的用户都可输入类似于 http://localhost:8000/topics/1/的URL,来访问显示相应主题的页面。

你自己试一试就明白了。以拥有所有主题的用户的身份登录,访问特定的主题,并复制该页 面的URL,或将其中的ID记录下来。然后,注销并以另一个用户的身份登录,再输入显示前述主 题的页面的URL。虽然你是以另一个用户登录的,但依然能够查看该主题中的条目。 为修复这种问题,我们在视图函数topic()获取请求的条目前执行检查:

views.py
from django.shortcuts import render
1 from django.http import HttpResponseRedirect, Http404
from django.core.urlresolvers import reverse
--snip--
@login_required
def topic(request, topic_id):"""显示单个主题及其所有的条目"""topic = Topic.objects.get(id=topic_id)# 确认请求的主题属于当前用户
2 if topic.owner != request.user:raise Http404 
entries = topic.entry_set.order_by('-date_added')context = {'topic': topic, 'entries': entries}return render(request, 'learning_logs/topic.html', context)
--snip--

服务器上没有请求的资源时,标准的做法是返回404响应。在这里,我们导入了异常Http404 (见1),并在用户请求它不能查看的主题时引发这个异常。收到主题请求后,我们在渲染网页前 检查该主题是否属于当前登录的用户。如果请求的主题不归当前用户所有,我们就引发Http404 异常(见2),让Django返回一个404错误页面。

现在,如果你试图查看其他用户的主题条目,将看到Django发送的消息Page Not Found。在 第20章,我们将对这个项目进行配置,让用户看到更合适的错误页面。

19.3.5 保护页面 edit_entry

页面edit_entry的URL为http://localhost:8000/edit_entry/entry_id/,其中entry_id是一 个数字。下面来保护这个页面,禁止用户通过输入类似于前面的URL来访问其他用户的条目:

views.py
--snip--
@login_required
def edit_entry(request, entry_id):"""编辑既有条目"""entry = Entry.objects.get(id=entry_id)topic = entry.topicif topic.owner != request.user:raise Http404if request.method != 'POST':# 初次请求,使用当前条目的内容填充表单--snip-- 

我们获取指定的条目以及与之相关联的主题,然后检查主题的所有者是否是当前登录的用 户,如果不是,就引发Http404异常。

19.3.6 将新主题关联到当前用户

当前,用于添加新主题的页面存在问题,因此它没有将新主题关联到特定用户。如果你尝试 添加新主题,将看到错误消息IntegrityError,指出learning_logs_topic.user_id不能为NULL。 Django的意思是说,创建新主题时,你必须指定其owner字段的值。

由于我们可以通过request对象获悉当前用户,因此存在一个修复这种问题的简单方案。请 添加下面的代码,将新主题关联到当前用户:

views.py

关于“Python”的核心知识点整理大全37-CSDN博客

关于“Python”的核心知识点整理大全25-CSDN博客

关于“Python”的核心知识点整理大全12-CSDN博客

往期快速传送门👆(在文章最后):

感谢大家的支持!欢迎订阅收藏!专栏将持续更新!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/594984.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

是否还在 Docker 中跑 MySQL?

容器的定义&#xff1a;容器是为了解决“在切换运行环境时&#xff0c;如何保证软件能够正常运行”这一问题。 目前&#xff0c;容器和 Docker 依旧是技术领域最热门的词语&#xff0c;无状态的服务容器化已经是大势所趋&#xff0c;同时也带来了一个热点问题被大家所争论不以…

[DevOps-02] Code编码阶段工具

一、简要说明 在code阶段,我们需要将不同版本的代码存储到一个仓库中,常见的版本控制工具就是SVN或者Git,这里我们采用Git作为版本控制工具,GitLab作为远程仓库。 Git安装安装GitLab配置GitLab登录账户二、Git安装 Git官网 Githttps://git-scm.com/

卫星互联网与MEC融合方案研究

卫星互联网与MEC融合方案研究 作者&#xff1a;温特、王立中、司鹏、颜明明、马恬、郭伊蒙 中国卫通集团股份有限公司 本文首发&#xff1a;第十九届卫星通信学术年会 摘 要&#xff1a;在卫星互联网中引入移动边缘计算(MEC)技术可有效提高用户体验质量&#xff0c;降低运营成…

jQuery文件下载方法及引入HTML语法

jQuery下载 去jQuery网站下载文件包&#xff0c;点击主页的“Download”之后&#xff0c;进入下载页面&#xff0c;可以选择production版本的进行下载&#xff0c;但是点击进去之后&#xff0c;浏览器并不会直接下载相关的文件&#xff0c;而是跳转到一个“密密麻麻”都是jQue…

15.bash shell中自定义命令行选项与getopt/getopts

文章目录 linux shell 命令行选项1.命令行选项的手动实现简单选项分离命令行参数和选项带值的选项合并选项 2.使用 getopt 命令getopts命令选项标准化 欢迎访问个人网络日志&#x1f339;&#x1f339;知行空间&#x1f339;&#x1f339; linux shell 命令行选项 选项是跟在单…

MySQL基础篇(一)SQL

视频地址: 黑马程序员 MySQL数据库入门到精通&#xff0c;从mysql安装到mysql高级、mysql优化全囊括 SQL&#xff0c;全称 Structured Query Language&#xff0c;结构化查询语言。操作关系型数据库的编程语言&#xff0c;定义了一套操作关系型数据库统一 标准。 一、SQL通用语…

整数的阶乘(英语:factorial)是所有小于及等于

整数的阶乘&#xff08;英语&#xff1a;factorial&#xff09;是所有小于及等于该数的正整数的积&#xff0c;0的阶乘为1。即&#xff1a;n!123...n。 实例 #!/usr/bin/python3 # Filename : test.py # author by : www.dida100.com # 通过用户输入数字计算阶乘 # 获…

electron自定义菜单

创建menu.js const { app, Menu } require("electron"); const createMenu () > {const menu [{label: "菜单",submenu: [{label: "新增",click: () > {},}, ],},{label: "关于",submenu: [{label: "新增",click:…

Java数据结构:1. 数据结构前置知识

文章目录 一、初识数据结构二、初识集合框架1. 什么是集合框架2. 集合框架的重要性3. 背后所涉及的数据结构以及算法 三、时间复杂度空间复杂度1. 算法效率2. 时间复杂度&#xff08;1&#xff09;概念&#xff08;2&#xff09;大O的渐进表示法&#xff08;3&#xff09;推导大…

MySQL5.7用于控制副本服务器的 SQL 语句

官网地址&#xff1a;MySQL :: MySQL 5.7 Reference Manual :: 13.4.2 SQL Statements for Controlling Replica Servers 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;工具翻译&#xff0c;仅供参考&#xff0c;笔芯笔芯. MySQL 5.7 参考手册 / ... / CHANGE M…

C语言多线程编程-线程间通信

介绍 在C语言中&#xff0c;采用多线程编程&#xff0c;我们经常会遇到&#xff0c;线程之前需要同步数据&#xff0c;或者一个线程处理后的的数据&#xff0c;需要给另外一个线程进行处理&#xff0c;这就需要线程之间进行通讯&#xff0c;多线程间的通信和同步是通过操作系统…

计算机系统基础

C 语言相关内容省略&#xff0c;复习自用&#xff0c;仅供参考~ 概述 冯诺伊曼结构 存储程序工作方式&#xff1a;将事先编好的程序和原始数据送入主存后才能执行程序&#xff0c;程序被启动执行后&#xff0c;计算机能在不需要操作人员干预下自动完成逐条指令取出和执行的任…

Toast.makeText()的使用方法

Toast.makeText()的使用方法 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;在今天的文章中&#xff0c;我们将深入讨论Android开发中一个常用而且便捷的UI组件——…

奋楫扬帆,奔赴新程 | 2023 年图扑大事记回顾,与您携手共迎 2024

2023.01 工信部公示了 2022 年度智能制造示范工厂揭榜单位和优秀场景名单。图扑软件和上海洲邦合作建设的宁波甬友数字孪生工厂被评为优秀场景&#xff0c;全国共有 369 个智能制造典型场景入选。 2023.01 在第十一届中国创新创业大赛全国赛&#xff08;新一代信息技术&#…

RabbitMQ(八)消息的序列化

目录 一、为什么需要消息序列化&#xff1f;二、常用的消息序列化方式1&#xff09;Java原生序列化&#xff08;默认&#xff09;2&#xff09;JSON格式3&#xff09;Protobuf 格式4&#xff09;Avro 格式5&#xff09;MessagePack 格式 三、总结 RabbitMQ 是一个强大的消息中间…

Hadoop分布式文件系统(二)

一、Hadoop 1、文件系统 1.1、文件系统定义 文件系统是一种存储和组织数据的方法&#xff0c;实现了数据的存储、分级组织、访问和获取等操作&#xff0c;使得用户对文件访问和查找变得容易。 文件系统使用树形目录的抽象逻辑概念代替了硬盘等物理设备使用数据块的概念&#…

通信基础——带宽

随着信息社会的发展和数字化进程的加速&#xff0c;通信技术已经成为现代社会最为重要的基础设施之一。而在通信技术中&#xff0c;带宽作为一个重要的概念&#xff0c;对于我们理解和应用现代通信技术具有至关重要的意义。本文将以“通信基础——带宽”为主题&#xff0c;对带…

高性能NVMe Host Controller IP

NVMe Host Controller IP 介绍 NVMe Host Controller IP可以连接高速存储PCIe SSD&#xff0c;无需CPU和外部存储器&#xff0c;自动加速处理所有的NVMe协议命令&#xff0c;具备独立的数据写入AXI4-Stream/FIFO接口和数据读取AXI4-Stream/FIFO接口&#xff0c;非常适合于超高…

华芯微特MCU之TIMER触发ADC

01 TIMER定时器之脉冲发送功能 我们今天详细讲解一下TIMER的ADC触发功能。 SWM190的TIMER2/3支持SAR ADC触发功能&#xff0c;此功能配置为定时器或脉冲发送均有效&#xff0c;可通过配置相应寄存器实现。 将SAR ADC CTRL寄存器中TRIG设置为TIMER2触发或TIMER3触发。TIMER可作…

技术旅程分享:收获与成长的探索

2023年对我而言是充满挑战和机遇的一年&#xff0c;我在这段时间里积累了丰富的技术经验和个人成长。通过不懈努力和持续学习&#xff0c;我在技术领域迈出了一系列坚实的步伐。在这篇文章中&#xff0c;我将分享我在这段时间中的收获和技术成长经历&#xff0c;与CSDN的朋友们…