《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---
相关推荐
奋斗的小花生6 分钟前
c++ 多态性
开发语言·c++
魔道不误砍柴功9 分钟前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
闲晨12 分钟前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
_.Switch34 分钟前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops
老猿讲编程39 分钟前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk2 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*2 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue2 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man2 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
测开小菜鸟2 小时前
使用python向钉钉群聊发送消息
java·python·钉钉