第19章_用户账号——【3.让用户拥有自己的数据】

26 篇文章 1 订阅

《Python编程从入门到实践》学习笔记——Django
内容包括【7.让用户拥有自己的数据】

目标:修改模型Topic,让每个主题属于特定的用户,这将影响条目,因为条目属于特定主题

[准备工作]

1.Blog里打开命令行
2.激活虚拟环境:
ll_env\Scripts\activate
3.运行服务器:
python manage.py runserver
4.浏览器查看:
http://localhost:8000
5.Blog里再次打开命令行
6.激活虚拟环境:
ll_env\Scripts\activate

[使用@login_required限制访问]

注:@login_required是装饰器(decorators)

1.限制对topics页面的访问

因为主题属于特定用户,所以只允许已登录的用户请求topics页面

(1)给views.py添加检查登录

打开F:\learning_log\learning_logs\views.py,添加

from django.contrib.auth.decorators import login_required

在def topics(request):前面添加

@login_required

注:login_required检查用户是否已登录,当登录时,才运行topics()

(2)给settings.py添加重定向

为实现用户未登录,则重定向到登录页面,需修改settings.py
打开F:\learning_log\learning_log\settings.py,在其末尾添加

#我的设置
LOGIN_URL='/users/login/'

(3)测验限制效果

浏览器打开http://localhost:8000,尝试不登录和登录查看Topics的结果

2.全面限制对项目“学习笔记”的访问

要求实现:不限制对主页、注册页面和注销页面的访问,限制对其他所有页面的访问

(1)给除index()外的每个视图添加@login_required

打开F:\learning_log\learning_logs\views.py,修改为

@login_required	
def topics(request):
……
@login_required	
def topic(request,topic_id):
……
@login_required	
def new_topic(request):
……
@login_required	
def new_entry(request,topic_id):
……
@login_required		
def edit_entry(request,entry_id):

[将数据关联到用户]

注意:只要将最高层的数据关联到用户,本项目是“主题”归属于特定用户就能确定“条目”归属

1.修改模型Topic

打开F:\learning_log\learning_logs\models.py
添加

from django.contrib.auth.models import User  #导入django.contrib.auth中的模型User

将Topic模型修改为

class Topic(models.Model):
	"""用户学习的主题"""
	text = models.CharField(max_length=200)
	date_added = models.DateTimeField(auto_now_add=True)
	owner=models.ForeignKey(User,on_delete=models.CASCADE)    #新加的,建立到模型User的外键关系
	def __str__(self):
		"""返回模型的字符串表示"""
		return self.text

2.确定当前有哪些用户

查看已创建的所有用户的ID:
启动Django shell会话:python manage.py shell
from django.contrib.auth.models import User
User.objects.all()
for user in User.objects.all():
print(user.username,user.id)
可查看到用户ll_admin 1 guest 2

3.迁移数据库

(1)迁移数据库

确认数据:python manage.py makemigrations learning_logs
根据提示:选择1(现在提供默认值)(注:2是退出后在models.py里添加默认值)
由于ll_admin的ID是1,这里为了让所有既有主题都关联到管理用户ll_admin,选1
执行迁移:python manage.py migrate
注:如果想要一个全新的数据库,可以执行命令python manage.py flush,此时会重建数据库的结构,此时必须重新创建超级用户且原来的数据都将丢失

(2)验证迁移效果

启动Django shell会话:python manage.py shell
from learning_logs.models import Topic
for topic in Topic.objects.all():
print(topic,topic.owner)
此时会显示ll_admin下的所有主题

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

(1)实现只向用户显示属于自己的主题

打开F:\learning_log\learning_logs\views.py,修改函数topics()为

def topics(request):
	"""显示所有的主题"""
	#用户登录后,request对象将有一个user属性,这里让Django只从并数据库获取owner属性为当前用户的Topic对象
	topics=Topic.objects.filter(owner=request.user).order_by('date_added') 
	context={'topics':topics}
	return render(request,'learning_logs/topics.html',context)

(2)测试效果

在浏览器里分别登录两个用户,查看Topics,此时只有ll_admin下有主题

[保护用户的主题]views.py

限制对显示单个主题的页面的访问,防止已登录用户输入http://localhost:8000/topics/1(该内容不属于这个用户)
方法:在视图函数topic()获取请求的条目前执行检查
打开F:\learning_log\learning_logs\views.py,将

from django.http import HttpResponseRedirect

修改为

from django.http import HttpResponseRedirect, Http404

def topic(request,topic_id):
	"""显示单个主题及其所有的条目"""
	topic=Topic.objects.get(id=topic_id)
	entries=topic.entry_set.order_by('-date_added')
	context={'topic':topic,'entries':entries}
	return render(request,'learning_logs/topic.html',context)

修改为

def topic(request,topic_id):
	"""显示单个主题及其所有的条目"""
	topic=Topic.objects.get(id=topic_id)
	#确认请求的主题属于当前用户
	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)

[保护修改主题页面]views.py

防止已登录用户输入http://localhost:8000/edit_entry/6(该内容不属于这个用户)
打开F:\learning_log\learning_logs\views.py,将edit_entry()修改为

def edit_entry(request,entry_id):
	"""编辑既有条目"""
	entry=Entry.objects.get(id=entry_id)
	topic=entry.topic
	if topic.owner !=request.user:
		raise Http404
	if request.method !='POST':
		#初次请求,使用当前条目填充表单
		form=EntryForm(instance=entry)
	else:
		#POST提交的数据,对数据进行处理
		form=EntryForm(instance=entry,data=request.POST)
		if form.is_valid():
			form.save()
			return HttpResponseRedirect(reverse('learning_logs:topic',args=[topic.id]))
	context={'entry':entry,'topic':topic,'form':form}
	return render(request,'learning_logs/edit_entry.html',context)

[将新主题关联到当前用户]

此时添加新主题有问题,需要创建新主题时,指定其owner字段的值
打开F:\learning_log\learning_logs\views.py,将new_topic()修改为

def new_topic(request):
	"""用户添加新主题"""
	if request.method !='POST':
		#未提交数据:创建一个新表单
		form=TopicForm
	else:
		#POST提交的数据,对数据进行处理
		form =TopicForm(request.POST)
		if form.is_valid():
			new_topic=form.save(commit=False)  #修改主题保存到数据库
			new_topic.owner=request.user  #设置新主题的owner属性为当前用户
			new_topic.save()   #保存到数据库
			return HttpResponseRedirect(reverse('learning_logs:topics'))
	context={'form':form}
	return render(request,'learning_logs/new_topic.html',context)

写在最后的作业:

1.在view.py中,核实当前主题关联到的用户为当前登录的用户。请将执行这种检查的代码放在一个名为check_topic_owner()的函数中,并在恰当的地方调用这个函数
打开F:\learning_log\learning_logs\views.py,添加

def check_topic_owner(request,topic_id):
	"""检查是否是当前登录用户的主题"""
	topic=Topic.objects.get(id=topic_id)
	if topic.owner != request.user:
		raise Http404

修改topic()、new_entry()、edit_entry()中的

if topic.owner != request.user:
	raise Http404

check_topic_owner(request,topic.id)

2.保护页面new_entry:现在一个用户可在另一个用户的学习笔记中添加条目,防止发生这种事
打开F:\learning_log\learning_logs\views.py,将函数new_entry()修改为

def new_entry(request,topic_id):
	"""用户添加特定新主题的新条目"""
	topic=Topic.objects.get(id=topic_id)
	#确认请求的主题属于当前用户
	if topic.owner != request.user:   #这里多加一个判断
		raise Http404
	if request.method !='POST':
		#未提交数据,创建一个空表单
		form=EntryForm()
	else:
		#POST提交的数据,对数据进行处理
		form=EntryForm(data=request.POST)

		if form.is_valid():
			new_entry=form.save(commit=False)
			new_entry.topic=topic
			new_entry.save()
			return HttpResponseRedirect(reverse('learning_logs:topic',args=[topic_id]))
	context={'topic':topic,'form':form}
	return render(request,'learning_logs/new_entry.html',context)

3.Blog项目:确保每篇博文和特定用户相关联,确保任何用户都可访问所有的博文,确保只有已登录的用户能发表博文以及编辑既有博文。在让用户能够编辑其博文的视图中,在处理表单前确认用户编辑的是他自己发表的博文。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值