栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

《Python编程从入门到实践 第二版》第十九章练习

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

《Python编程从入门到实践 第二版》第十九章练习

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

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

1 创建虚拟环境

Windows:

 'cmd' # 在该目录中运行终端
 python -m venv ll_env # ll是两个小写字母l
2 激活虚拟环境
ll_envScriptsactivate
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//',views.edit_blog,name='edit_blog'),
]
13 base页面

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

BLOG 发布新博客

{% block content %}{% endblock content%}
14 index页面

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

{%extends 'blogs/base.html'%}
{%block content%}
  

Blog 主页

    {%for blogpost in blogposts%}
  • {{blogpost.date_added|date:'Y m d,H:i'}}

  • {{blogpost.title}}

    {{blogpost|linebreaks}}

    修改博客 {%empty%}

    Add

    {%endfor%}
{%endblock content%}
15 new_blog页面

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

{%extends 'blogs/base.html'%}
{%block content%}
	

发布一篇新博客:

{% csrf_token %} {{ form.as_p }}
{%endblock content%}
16 edit_blog页面

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

{%extends 'blogs/base.html'%}
{%block content%}
	

{{ title }}

{% csrf_token %} {{ form.as_p }}
{%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

BLOG 发布新博客 {% if user.is_authenticated %} Hello,{{ user.username }}. 注销 {% else %} 注册 - 登录 {% endif %}

{% block content %}{% endblock content%}
18 登录页面

login.html

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

{% block content %}

{% if form.errors %}
	

Your username and password didn't match.Please try again.

{% endif %}
{% csrf_token %} {{ form.as_p }}
{% endblock content %}
19 注销页面

logged_out.html

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

{% block content %}
	

You have been logged out.Thank you for visiting!

{% endblock content %}
20 注册页面

register.html

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

{% block content %}

{% csrf_token %} {{ form.as_p }}
{% 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()
, ]>
>>> 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':
  blogsmigrations002_blogpost_owner.py
    - Add field owner to blogpost

(ll_env) D:Sublime Textpython_testBlog>
  1. 执行迁移
(ll_env) D:Sublime Textpython_testBlog>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 Textpython_testBlog>
  1. 验证迁移符合预期
(ll_env) D:Sublime Textpython_testBlog>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
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/879043.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号