《python编程从入门到实践》day40

昨日知识点回顾

编辑条目及创建用户账户

暂没能解决bug:

复制代码
The view learning_logs.views.edit_entry didn't return an HttpResponse object. It returned None instead.

今日知识点学习

19.2.5 注销

提供让用户注销的途径

1.在base.html中添加注销链接

python 复制代码
# base.html
<p>
	<a href = "{% url 'learning_logs:index' %}">Learning Log</a> -
	<a href = "{% url 'learning_logs:topics' %}">Topics</a> -
	{% if user.is_authenticated %}
		Hello, {{ user.username }}.
		<a href="{% url 'users:logout' %}">Log out</a>
	{% else %}
		<a href="{% url 'users:login' %}">Log in </a>
	{% endif %}
</p>

{% block content %}{% endblock content %}

2.注销确认页面

python 复制代码
# learning_log\users\templates\registration\logged_out.html
{% extends "learning_logs/base.html" %}

{% block content %}
	<p>You have been logged out. Thank you for visiting!</p>
{% endblock content %}

19.2.6 注册页面

1.注册页面的URL模式

python 复制代码
# users\urls.py
"""为应用程序users定义URL模式"""

from django.urls import path, include

from . import views

app_name = 'users'
urlpatterns = [
    # 包含默认的身份验证URL
    path('', include('django.contrib.auth.urls')),
    # 注册页面
    path('register/', views.register, name='register')
]

2.视图函数register()

python 复制代码
# # users\views.py
from django.shortcuts import render, redirect
from django.contrib.auth import login
from django.contrib.auth.forms import UserCreationForm

# Create your views here.
def register(request):
    """注册新用户"""
    if request.method != 'POST':
        # 显示空的注册表单
        form = UserCreationForm()
    else:
        # 处理填写好的表单
        form = UserCreationForm(data=request.POST)
        
        if form.is_valid():
            new_user = form.save()
            # 让用户自动登录,再重定向主页
            login(request, new_user)
            return redirect('learning_logs:index')
        
        # 显示空表单或指出表单无效
        context = {'form': form}
        return render(request, 'registration/register.html', context)
        

3.注册模版

python 复制代码
# users\templates\registration\register.html
{% extends "learning_logs/base.html" %}

{% block content %}

	<form method='post' action="{% url 'users:register' %}" >
		{% csrf_token %}
		{{  form.as_p  }}

		<button name="submit">Register</button>
		<input type="hidden" name="next"
			value="{% url 'learning_logs:index' %}"  />		
	</form>

{% endblock content %}

4.链接到注册页面

python 复制代码
# base.html
<p>
	<a href = "{% url 'learning_logs:index' %}">Learning Log</a> -
	<a href = "{% url 'learning_logs:topics' %}">Topics</a> -
	{% if user.is_authenticated %}
		Hello, {{ user.username }}.
		<a href="{% url 'users:logout' %}">Log out</a>
	{% else %}
		<a href="{% url 'users:register' %}">Register </a>-
		<a href="{% url 'users:login' %}">Log in </a>
	{% endif %}
</p>

{% block content %}{% endblock content %}

19.3 让用户拥有自己的数据

19.3.1 使用@login_required限制访问

装饰器:放在函数定义前面的指令,能在函数运行前修改函数代码

1.限制访问显示所有主题的页面

python 复制代码
# learning_logs/views.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required

# 导入所需数据相关联的模型
from .models import Topic, Entry
from .forms import TopicForm, EntryForm

# Create your views here.
def index(request):
    """学习笔记的主页"""
    # 传递两个实参:对象request以及一个可用于创建页面的模版
    return render(request, 'learning_logs/index.html')

@login_required
def topics(request):
    """显示所有的主题"""
    topics = Topic.objects.order_by('date_added')
---snip---
python 复制代码
# settings.py
---snip(直到末尾)---

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

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

python 复制代码
# learning_logs\views.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required

# 导入所需数据相关联的模型
from .models import Topic, Entry
from .forms import TopicForm, EntryForm

# Create your views here.
def index(request):
    """学习笔记的主页"""
    # 传递两个实参:对象request以及一个可用于创建页面的模版
    return render(request, 'learning_logs/index.html')

@login_required
def topics(request):
    """显示所有的主题"""
    topics = Topic.objects.order_by('date_added')
    # 定义一个将要发送模版的上下文
    context = {'topics': topics}
    return render(request, 'learning_logs/topics.html', context)

@login_required
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)

@login_required
def new_topic(request):
    """添加新主题"""
    if request.method != 'POST':
        # 未提交数据:创建一个新表单
        form = TopicForm()
    else:
        # POST提交的数据:对数据进行处理
        form = TopicForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topics')

    # 显示空表单后指出表单数据无效
    context = {'form': form}
    return render(request, 'learning_logs/new_topic.html', context)

@login_required
def new_entry(request, topic_id):
    """在特定主题中添加新条目"""
    topic = Topic.objects.get(id=topic_id)

    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 redirect('learning_logs:topic', topic_id=topic_id)

    # 显示空表单或支出表单数据无效
    context = {'topic': topic, 'form': form}
    return render(request, 'learning_logs/new_entry.html', context)

@login_required
def edit_entry(request, entry_id):
    """编辑既有条目"""
    entry = Entry.objects.get(id=entry_id)
    topic = entry.topic

    if request.method != 'POST':
        # 初次请求:使用当前条目填充表单
        form =EntryForm(instance=entry)
    else:
        # POST提交的数据:对数据进行处理
        form = EntryForm(instance=entry, data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topic', topic_id=topic.id)

        context = {'entry': entry, 'topic': topic, 'form': form}
        return render(request, 'learning_logs/edit_entry.html', context)

19.3.2 将数据关联到用户

1.修改模型Topic

python 复制代码
# models.py
from django.db import models
from django.contrib.auth.models import User


# Create your models here.
class Topic(models.Model):
    """用户学习的主题"""
    # 存储少量文本如名称、标题或城市,预留200字符空间
    text = models.CharField(max_length=200)
    # 记录日期和时间的数据,为True自动设置为当前日期和时间
    date_added = models.DateTimeField(auto_now_add=True)
    owner = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        """返回模型的字符串表示"""
        # 只显示条目前50字符,省略号指出显示的并非整个条目
        return f"{self.text[:50]}..."
    
    
class Entry(models.Model):
    """学到某个主题的具体知识"""
    topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
    # 外键(foreign key)是一个数据库术语,它指向数据库另一条记录。
    # 次联删除:on_delete=models.CASCADE让Django在删除主题的同时删除所有与之相关联的条目
    text = models.TextField()
    date_added = models.DateTimeField(auto_now_add=True)

    class Meta:
        # 存储用于管理模型的额外信息
        verbose_name_plural = 'entries'
  1. 确定当前有哪些用户

3.迁移数据库

重建数据库:python manage.py flush

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

php 复制代码
# 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---

19.3.4 保护用户的主体

python 复制代码
# views.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.http import Http404

---snip---

@login_required
def topic(request, topic_id):
    """显示单个主题"及所有的条目"""
    topic = Topic.objects.get(id=topic_id)
    # 确认请求的主题属于当前用户
    if topic.owner != request.user:
        raise Http404

---snip---

19.3.5 保护页面edit_entry

python 复制代码
# views.py
---snip---
@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
    
---snip---

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

python 复制代码
# views.py
---snip---
@login_required
def new_topic(request):
    """添加新主题"""
    if request.method != 'POST':
        # 未提交数据:创建一个新表单
        form = TopicForm()
    else:
        # POST提交的数据:对数据进行处理
        form = TopicForm(data=request.POST)
        if form.is_valid():
            new_topic = form.save(commit=False)
            new_topic.owner = request.user
            new_topic.save()            
            return redirect('learning_logs:topics')

    # 显示空表单后指出表单数据无效
    context = {'form': form}
    return render(request, 'learning_logs/new_topic.html', context)

---snip---
相关推荐
用户8356290780512 小时前
Python 实现 PDF 文件加密与解密方法
后端·python
用户8356290780512 小时前
使用 Python 冻结与拆分 Excel 窗格教程
后端·python
你好潘先生10 小时前
别再记命令了,用 yeero do 说句人话就能跑脚本,而且不烧 token
服务器·python·命令行
Agent_大师11 小时前
WebSocket 行情重连成功,K线缺口不会自动消失
python
荣码11 小时前
LLM结构化输出:让AI返回JSON而不是废话,我踩了4个坑
java·python
copyer_xyf11 小时前
FastAPI 如何连接 MySQL
后端·python
apocelipes1 天前
常用编程语言和库的正则表达式性能对比
c语言·c++·python·性能优化·golang·开发工具和环境
用户8356290780511 天前
使用 Python 在 PDF 中创建与管理书签
后端·python
MeixianAgent1 天前
Python 回测数据入口怎么验?历史 K 线入库前先做 5 个检查
后端·python
咕白m6251 天前
用 Python 实现一键批量查找与替换 Excel 数据
后端·python