《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---
相关推荐
我曾经是个程序员2 分钟前
C#File文件基础操作大全
开发语言·c#
林浔09067 分钟前
QT信号槽
开发语言·qt
重生之绝世牛码11 分钟前
Java设计模式 —— 【结构型模式】享元模式(Flyweight Pattern) 详解
java·大数据·开发语言·设计模式·享元模式·设计原则
Allen Bright25 分钟前
【Java基础-26.1】Java中的方法重载与方法重写:区别与使用场景
java·开发语言
执着的小火车27 分钟前
02-18.python入门基础一基础算法
数据结构·python·算法·排序算法
梦茹^_^28 分钟前
排序算法(系列)
数据结构·python·算法·排序算法·希尔排序·基数排序·计数排序和桶排序
秀儿y30 分钟前
单机服务和微服务
java·开发语言·微服务·云原生·架构
ybq1951334543131 分钟前
javaEE-多线程案例-单例模式
java·开发语言
kiiila42 分钟前
【Qt】编辑框/按钮控件---实现HelloWorld
开发语言·qt