用Django 写学习笔记程序第二章.3让用户拥有自己的数据

文章目录

往期回顾

学习Django编写"学习笔记"程序

用Django 写学习笔记程序第二章.1 让用户能够输入数据

用Django 写学习笔记程序第二章.2 创建用户账户

详细内容请移步主页查看

让用户拥有自己的数据

用户应该能输入其专有的数据,为此,我们创建一个系统,确定各项数据据所属的用户,再限制对页面的访问,让用户只能使用自己的数据。

本期内容中,我们将修改Topic模型,让每个主题都归属于特定的用户。这一改动也会影响条目,因为每个条目都属于特定的主题。我们先限制对一些页面的访问。

使用@login_required 限制访问

Django 提供了装饰器 @login_required,让我们能够实现限制访问,对于某些页面,只允许已登录的用户访问。

装饰器(decorator) 是放在函数定义前面的指令。

限制对 topics 页面的访问

因为每个主题都归属于特定用户所有,因此只允许已登录的用户访问 topics页面。

python 复制代码
from django.contrib.auth.decorators import login_required

# 显示所有的主题
@login_required
def topics(request):
    topics = Topic.objects.order_by('date_added')
    content = {'topics': topics}
    return render(request, 'learning_logs/topics.html', content)
复制代码
code 说明:
我们导入了函数 login_required,将它作为装饰器用于视图函数 topics()。
在 topics() 之前加上@login_required,让python在运行 topics() 之前先运行它
login_required() 检查用户是否已登录,仅当用户已登录时,Django才运行topics()

当用户未登录时,就重定向到页面:

修改 settings.py 让Django知道哪里去找登录页面。

python 复制代码
LOGIN_URL = '/users/login/'

将数据关联到用户

将数据关联到提交他们的用户,我们只需将最高层的数据关联到用户,这样更低层的数据将自动关联到用户。

修改 Topic模型,在其中添加一个关联到用户的外键。

python 复制代码
# models.py 的修改
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

确定当前有哪些用户

迁移数据库时,Django将对数据库进行修改,使其能够存储主题和用户之间的关联。为了执行迁移,Django需要知道该将各个既有主题关联到哪个用户。

我们将既有主题都关联到同一个用户,即:超级用户

python 复制代码
# 激活虚拟环境
ll_env\Scripts\activate

# 打开 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)

用户名 1
用户名 2
用户名 3

迁移数据库

python 复制代码
#迁移命令
python manage.py makemigrations learning_logs

# 之后会出现两个选项,两个选项皆选1
python 复制代码
python manage.py migrate

# 迁移成功后会报告 ..OK
# 或者用 shell 查验
python manage.py shell

from learning_logs.models import Topic

for topic in Topic.objects.all():
	print(topic, topic.owner)

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

当前,不管以哪个账号登录,都可以看到所有主题。

修改 views.py中 函数topics()

python 复制代码
# 显示所有的主题
@login_required
def topics(request):
    topics = Topic.objects.filter(owner=request.user).order_by('date_added')
    content = {'topics': topics}
    return render(request, 'learning_logs/topics.html', content)
复制代码
request 对象有一个 user属性,该属性存储了有关用户的信息
Topic.objects.filter(owner=request.user)让Django只从数据
库中获取 owner属性为当前用户的Topic对象

保护用户的主题

python 复制代码
from django.http import HttpResponseRedirect, Http404

# 显示单个主题及其所有的条目
@login_required()
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')
    content = {'topic': topic, 'entries': entries}
    return render(request,'learning_logs/topic.html', content)

保护页面 edit_entry

python 复制代码
# 编辑既有条目
@login_required
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()
    else:
        form = EntryForm(instance=entry, data=request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse('learning_logs:topic', args=[topic.id]))
    content = {'entry': entry, 'topic': topic, 'form': form}
    return render(request, 'learning_logs/edit_entry.html', content)

将新主题关联到当前用户

用于添加新主题的页面存在问题,因此它没有将新主题关联到特定用户。如果尝试添加新的主题,就会出现错误消息 InterityError 的报错信息。指出learning_logs_topic.user_id 不能为NULL

Django的意思是说,添加新的主题时 必须指定其 owner字段的值,

由于我们可通过 request 获悉当前对象,所以直接添加下述代码解决该问题:

python 复制代码
# views.py

# 添加新主题
@login_required
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
            new_topic.save()
          # form.save()
            return HttpResponseRedirect(reverse('learning_logs:topics'))

    context = {'form': form}
    return render(request, 'learning_logs/new_topic.html', context)
相关推荐
risc12345624 分钟前
如何认识结构?结构 = 要素 + 关系 + 动态
笔记
PPPPPaPeR.25 分钟前
光学算法实战:深度解析镜片厚度对前后表面折射/反射的影响(纯Python实现)
开发语言·python·数码相机·算法
JaydenAI29 分钟前
[拆解LangChain执行引擎] ManagedValue——一种特殊的只读虚拟通道
python·langchain
骇城迷影33 分钟前
Makemore 核心面试题大汇总
人工智能·pytorch·python·深度学习·线性回归
长安牧笛36 分钟前
反传统学习APP,摒弃固定课程顺序,根据用户做题正确性,学习速度,动态调整课程难度,比如某知识点学不会,自动推荐基础讲解和练习题,学习后再进阶,不搞一刀切。
python·编程语言
wxin_VXbishe1 小时前
C#(asp.net)学员竞赛信息管理系统-计算机毕业设计源码28790
java·vue.js·spring boot·spring·django·c#·php
码界筑梦坊1 小时前
330-基于Python的社交媒体舆情监控系统
python·mysql·信息可视化·数据分析·django·毕业设计·echarts
试着1 小时前
【huawei】机考整理
学习·华为·面试·机试
風清掦1 小时前
【江科大STM32学习笔记-05】EXTI外部中断11
笔记·stm32·学习