IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 《Python编程从入门到实践 第二版》第十九章练习 -> 正文阅读

[Python知识库]《Python编程从入门到实践 第二版》第十九章练习

19-1 博客 新建一个Django项目,将其命名为Blog。在这个项目中,创建一个名为blogs 的应用程序,并在其中创建一个名为BlogPost 的模型。这个模型应包含title 、text 和date_added 等字段。为这个项目创建一个超级用户,并使用管理网站创建几个简短的帖子。创建一个主页,在其中按时间顺序显示所有的帖子。

创建两个表单,其中一个用于发布新帖子,另一个用于编辑既有的帖子。尝试填写这些表单,确认它们能够正确工作。

1 创建虚拟环境

Windows:

 'cmd' # 在该目录中运行终端
 python -m venv ll_env # ll是两个小写字母l

2 激活虚拟环境

ll_env\Scripts\activate

3 安装Django

(ll_env) Blog>pip install django

4 创建项目

(ll_env) Blog>django-admin startproject Blog .

5 创建数据库

(ll_env) Blog>python manage.py migrate

6 创建应用程序

(ll_env) Blog>python manage.py startapp blogs

7 创建模型

models.py

from django.db import models

# Create your models here.

class BlogPost(models.Modes):
	""" 博客页面 """
	title = models.CharField(max_length=200)
	text = models.TextField()
	date_added = models.DateTimeField(auto_now_add=True)

	class Meta:
		verbase_name_plural = 'BlogPost' # 让他显示为BlogPost

	def __str__(self):
		""" 返回模型字符串表示 """
		return self.text

8 激活模型

settings.py

# Application definition

INSTALLED_APPS = [
    # 我的应用程序
    'blogs',

    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
python manage.py makemigrations blogs
python manage.py migrate

9 创建超级用户

(ll_env) D:\Blog>python manage.py createsuperuser

admin.py

from django.contrib import admin
from .models import BlogPost

admin.site.register(BlogPost)

10 表单

forms.py

from django import forms

from .models import BlogPost

class BlogPostForm(forms.ModelForm):
	class Meta:
		model = BlogPost
		fields = ['title','text']  # 获取模型里的两个字段
		widgets = {'text': forms.Textarea(attrs={'cols':80})}

class BlogForm(forms.ModelForm):
	class Meta:
		model = BlogPost
		fields = ['title','text']  
		labels = {'text':'','title':''}
		widgets = {'text': forms.Textarea(attrs={'cols':80})}	

11 视图

views.py

from django.shortcuts import render,redirect

from .models import BlogPost

from .forms import BlogPostForm,BlogForm

def index(request):
	""" 主页,显示所有 """
	blogposts = BlogPost.objects.order_by('-date_added')
	context = {'blogposts':blogposts}
	return render(request,'blogs/index.html',context)

def new_blog(request):
	""" 添加新博客 """
	if request.method != 'POST':
		form = BlogPostForm()
	else:
		form = BlogPostForm(data=request.POST)
		if form.is_valid():
			form.save()
			return redirect('blogs:index')
	context = {'form':form}
	return render(request,'blogs/new_blog.html',context)

def edit_blog(request,blog_id):
	""" 编辑博客 """
	blogpost = BlogPost.objects.get(id=blog_id)
	title = blogpost.title

	if request.method != 'POST':
		form = BlogPostForm(instance=blogpost)
	else:
		form = BlogPostForm(instance=blogpost,data=request.POST)
		if form.is_valid():
			form.save()
			return redirect('blogs:index')
	context = {'blogpost':blogpost,'title':title,'form':form}
	return render(request,'blogs/edit_blog.html',context)

12 URL模式

  1. Blog -> urls.py
from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include(('blogs.urls','blogs'),namespace='blogs')),
]
  1. blogs -> urls.py
from django.urls import path

from . import views

app_name = 'blogs'

urlpatterns = [
	path('',views.index,name='index'),
	path('new_blog/',views.new_blog,name='new_blog'),
	path('edit_blog/<int:blog_id>/',views.edit_blog,name='edit_blog'),
]

13 base页面

Blog -> blogs -> templates -> blogs ->base.html

<p>
	<a href="{% url 'blogs:index' %}">BLOG</a>
	<a href="{% url 'blogs:new_blog' %}">发布新博客</a>
</p>

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

14 index页面

Blog -> blogs -> templates -> blogs -> index.html

{%extends 'blogs/base.html'%}
{%block content%}
  <p><h1>Blog 主页</h1></p>
  <ul>
  {%for blogpost in blogposts%}
    <li>
      <p>{{blogpost.date_added|date:'Y m d,H:i'}}</p>
    </li>
    <p>{{blogpost.title}}</p>
    <p>{{blogpost|linebreaks}}</p>
    <a href="{%url 'blogs:edit_blog' blogpost.id%}">修改博客</a>
  {%empty%}
    <p>Add</p>    
  {%endfor%}
  </ul>
  
{%endblock content%}

15 new_blog页面

Blog -> blogs -> templates -> blogs -> new_blog.html

{%extends 'blogs/base.html'%}
{%block content%}
	<p>发布一篇新博客:</p>
	<form action="{% url 'blogs:new_blog'%}" method="post">
		{% csrf_token %}
		{{ form.as_p }}
		<button  name="submit">发布</button>
	</form>

{%endblock content%}

16 edit_blog页面

Blog -> blogs -> templates -> blogs -> edit_blog.html

{%extends 'blogs/base.html'%}
{%block content%}
	<p>{{ title }}</p>
	<form action="{% url 'blogs:edit_blog' blogpost.id %}" method="post">
		{% csrf_token %}
		{{ form.as_p }}
		<button  name="submit">修改</button>
	</form>

{%endblock content%}

19-2 博客账户 在为完成练习19-1而开发的项目Blog中,添加用户身份验证和注册系统。向已登录的用户显示其用户名,向未注册的用户显示到注册页面的链接。

17 创建应用程序users

(ll_env) Blog>python manage.py startapp users

settings.py

INSTALLED_APPS = [
    # 我的应用程序
    'blogs',
    'users',

    ...
]

Blog -> Blog -> urls.py

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('user/',include('users.urls')),
    path('',include(('blogs.urls','blogs'),namespace='blogs')),
]

Blog -> users-> 创建urls.py

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'),
]

users -> views.py

from django.shortcuts import render,redirect

from django.contrib.auth import login
from django.contrib.auth.forms import UserCreationForm

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('blogs:index')

	# 显示空表单或指出表单无效
	context = {'form': form}
	return render(request,'registration/register.html',context)

blogs -> templates -> blogs -> base.html

<p>
	<a href="{% url 'blogs:index' %}">BLOG</a>
	<a href="{% url 'blogs:new_blog' %}">发布新博客</a>
	{% if user.is_authenticated %}
		Hello,{{ user.username }}.
		<a href="{% url 'users:logout' %}">注销</a>
	{% else %}
		<a href="{% url 'users:register' %}">注册</a> -
		<a href="{% url 'users:login' %}">登录</a>
	{% endif %}
</p>

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

18 登录页面

login.html

{% extends "blogs/base.html" %}

{% block content %}

{% if form.errors %}
	<p>Your username and password didn't match.Please try again.</p>

{% endif %}

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

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

{% endblock content %}

19 注销页面

logged_out.html

{% extends "blogs/base.html" %}

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

20 注册页面

register.html

{% extends "blogs/base.html" %}

{% block content %}

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

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

{% endblock content %}

19-3 重构 在views.py中,我们在两个地方核实了主题关联到的用户为当前登录的用户。请将执行这种检查的代码放在函数check_topic_owner()中,并在这两个地方调用该函数。
blogs -> views.py,此处因为没有写更多功能,所以只调用一次

from django.shortcuts import render,redirect

from .models import BlogPost

from .forms import BlogPostForm,BlogForm

def index(request):
	""" 主页,显示所有 """
	blogposts = BlogPost.objects.order_by('-date_added')
	context = {'blogposts':blogposts}
	return render(request,'blogs/index.html',context)

def new_blog(request):
	""" 添加新博客 """
	if request.method != 'POST':
		form = BlogPostForm()
	else:
		form = BlogPostForm(data=request.POST)
		if form.is_valid():
			form.save()
			return redirect('blogs:index')
	context = {'form':form}
	return render(request,'blogs/new_blog.html',context)

def edit_blog(request,blog_id):
	""" 编辑博客 """
	blogpost = BlogPost.objects.get(id=blog_id)
	title = blogpost.title

	check_topic_owner(blogpost,request)
	if request.method != 'POST':
		form = BlogPostForm(instance=blogpost)
	else:
		form = BlogPostForm(instance=blogpost,data=request.POST)
		if form.is_valid():
			form.save()
			return redirect('blogs:index')
	context = {'blogpost':blogpost,'title':title,'form':form}
	return render(request,'blogs/edit_blog.html',context)


def check_topic_owner(blogpost,request):
	if blogpost.owner != request.user:
		raise Http404

19-4 保护页面new_entry 一个用户可在另一个用户的学习笔记中添加条目,方法是在URL中指定属于另一个用户的主题的ID。为防范这种攻击,请在保存新条目之前,核实它所属的主题归属于当前用户。

注意:先把19-5的代码写完才能运行19-4的步骤

  • 修改模型 BlogPost
    blogs -> models.py
from django.db import models
from django.contrib.auth.models import User

# Create your models here.

class BlogPost(models.Model):
	""" 博客页面 """
	title = models.CharField(max_length=200)
	text = models.TextField()
	date_added = models.DateTimeField(auto_now_add=True)
	owner = models.ForeignKey(User,on_delete=models.CASCADE)

	class Meta:
		verbose_name_plural = 'BlogPost' # 让他显示为BlogPost

	def __str__(self):
		""" 返回模型字符串表示 """
		return self.text
  • 查找当前所有用户,使其数据关联到超级用户
(ll_env) D:\Blog>python manage.py shell
Python 3.9.6 (tags/v3.9.6:db3ff76, Jun 28 2021, 15:26:21) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.contrib.auth.models import User
>>> User.objects.all()
<QuerySet [<User: ll_admin>, <User: aaa>]>
>>> for user in User.objects.all():
...     print(user.username,user.id)
...
ll_admin 1
>>>
  • 迁移数据库
(ll_env) D:\Blog>python manage.py makemigrations blogs
It is impossible to add a non-nullable field 'owner' to blogpost without specifying a default. This is because the database needs something to populate existing rows.
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
 2) Quit and manually define a default value in models.py.
Select an option: 1
Please enter the default value as valid Python.
The datetime and django.utils.timezone modules are available, so it is possible to provide e.g. timezone.now as a value.
Type 'exit' to exit this prompt
>>> 1
Migrations for 'blogs':
  blogs\migrations\0002_blogpost_owner.py
    - Add field owner to blogpost

(ll_env) D:\Sublime Text\python_test\Blog>
  1. 执行迁移
(ll_env) D:\Sublime Text\python_test\Blog>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, blogs, contenttypes, sessions
Running migrations:
  Applying blogs.0002_blogpost_owner... OK

(ll_env) D:\Sublime Text\python_test\Blog>
  1. 验证迁移符合预期
(ll_env) D:\Sublime Text\python_test\Blog>python manage.py shell
Python 3.9.6 (tags/v3.9.6:db3ff76, Jun 28 2021, 15:26:21) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from blogs.models import BlogPost
>>> for blogpost in BlogPost.objects.all():
...     print(blogpost,blogpost.owner)
...
123 ll_admin
In the morning,I'm having eaten egg.
OK!!! ll_admin

19-5 受保护的博客 在你创建的项目Blog中,确保每篇博文都与特定用户相关联。确保任何用户都可访问所有的博文,但只有已登录的用户能够发表博文和编辑既有博文。在让用户编辑博文的视图中,在处理表单前确认用户编辑的是其自己发表的博文。

  • Blog -> settings.py 最后一行加上
# 我的设置
LOGIN_URL = 'users:login'
  • blogs -> views.py
from django.shortcuts import render,redirect

from django.contrib.auth.decorators import login_required

from .models import BlogPost

from .forms import BlogPostForm,BlogForm

def index(request):
	""" 主页,显示所有 """
	blogposts = BlogPost.objects.order_by('-date_added')
	context = {'blogposts':blogposts}
	return render(request,'blogs/index.html',context)

@login_required
def new_blog(request):
	""" 添加新博客 """
	if request.method != 'POST':
		form = BlogPostForm()
	else:
		form = BlogPostForm(data=request.POST)
		if form.is_valid():
			form.save()
			return redirect('blogs:index')
	context = {'form':form}
	return render(request,'blogs/new_blog.html',context)

@login_required
def edit_blog(request,blog_id):
	""" 编辑博客 """
	blogpost = BlogPost.objects.get(id=blog_id)
	title = blogpost.title

	check_topic_owner(blogpost,request)
	if request.method != 'POST':
		form = BlogPostForm(instance=blogpost)
	else:
		form = BlogPostForm(instance=blogpost,data=request.POST)
		if form.is_valid():
			form.save()
			return redirect('blogs:index')
	context = {'blogpost':blogpost,'title':title,'form':form}
	return render(request,'blogs/edit_blog.html',context)


def check_topic_owner(blogpost,request):
	if blogpost.owner != request.user:
		raise Http404
  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-05-18 17:35:34  更:2022-05-18 17:37:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 13:39:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码