目录
前言
一、博客
1.建立项目
2.创建应用程序
3.Django管理网站
?4.让用户输入数据
二、博客账户
1.应用程序users
2.登录页面
3.注销
4.注册页面
三、重构
四、保护页面new_entry
五、受保护的博客
1.使用@login_required限制访问
2.将数据关联到用户
3.保护页面
前言
这里是《Python从入门到实践》的练习答案,如果有错误或者可以改进的地方欢迎在评论区指正
一、博客
1.建立项目
每次新建项目时操作都相似:
建立虚拟环境
激活虚拟环境
安装django
在django中创建项目
创建数据库
这一部分操作与第18章基本相同
终端:?
PS Blog> python -m venv Blog_env
PS Blog> cd C:\softwaregongjv\Python\python_codes\Blog\Blog_env\Scripts
PS Blog\Blog_env\Scripts> .\activate
(Blog_env) PS Blog\Blog_env\Scripts> cd Blog
(Blog_env) PS Blog> pip install django
Collecting django
Using cached Django-4.0.6-py3-none-any.whl (8.0 MB)
Collecting tzdata
Using cached tzdata-2022.1-py2.py3-none-any.whl (339 kB)
--snip--
Installing collected packages: tzdata, sqlparse, asgiref, django
Successfully installed asgiref-3.5.2 django-4.0.6 sqlparse-0.4.2 tzdata-2022.1
(Blog_env) PS Blog> django-admin startproject Blog .
(Blog_env) PS Blog> python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
--snip--
(Blog_env) PS Blog>
2.创建应用程序
终端
(Blog_env) PS Blog> python manage.py startapp blogs
定义模型 Blog\blogs\models.py
from django.db import models
class BlogPost(models.Model):
"""a model of Blog page"""
title = models.CharField(max_length=200)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
# display simple information about the model
# return a string representation of the model
return self.title +'=='+ self.text
激活模型 Blog\Blog\settings.py
# Application definition
INSTALLED_APPS = [
# my apps
'blogs',
# the default applications
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
终端
(Blog_env) PS Blog> python manage.py makemigrations blogs
Migrations for 'blogs':
blogs\migrations\0001_initial.py
- Create model BlogPost
(Blog_env) PS Blog> python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, blogs, contenttypes, sessions
Running migrations:
Applying blogs.0001_initial... OK
(Blog_env) PS Blog>
3.Django管理网站
创建超级用户 终端
(Blog_env) PS Blog> python manage.py createsuperuser
Username (leave blank to use '--snip--'): 11-admin
Email address:
Password:
Password (again):
Superuser created successfully.
(Blog_env) PS Blog>
向管理网站注册模型 Blog\blogs\admin.py
from django.contrib import admin
from .models import BlogPost
admin.site.register(BlogPost)
使用管理网站创建几个简短的帖子,效果如下:
?4.让用户输入数据
这一步我借鉴了另一篇文章的答案,并略作修改,原文在此:
白桃提拉米苏的答案
表单 新建?Blog\blogs\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})}
视图 Blog\blogs\views.py
from django.shortcuts import render,redirect
from .models import BlogPost
from .forms import BlogPostForm
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)
URL模式
Blog\Blog\urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blogs.urls')),
]
?Blog\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'),
]
以下是所有html文件 路径 Blog\blogs\templates\blogs\--snip--.html
base.html
<p>
<a href="{% url 'blogs:index' %}">BLOG</a> -
<a href="{% url 'blogs:new_blog' %}">Add new blog</a>
</p>
{% block content %}{% endblock content%}
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><h4>{{blogpost.title}}</h4></p>
<p>{{blogpost|linebreaks}}</p>
<a href="{%url 'blogs:edit_blog' blogpost.id%}">Edit Blog</a>
{%empty%}
<p>No blogs have been added.</p>
{%endfor%}
</ul>
{%endblock content%}
new_blog.html
{%extends 'blogs/base.html'%}
{%block content%}
<p><h2>Add A New Blog</h2></p>
<form action="{% url 'blogs:new_blog'%}" method="post">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Add Blog</button>
</form>
{%endblock content%}
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">Save changes</button>
</form>
{%endblock content%}
效果:
二、博客账户
1.应用程序users
创建一个名为users的应用程序?终端
(Blog_env) PS Blog> python manage.py startapp users
(Blog_env) PS Blog> dir
目录: Blog
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2022/7/28 18:28 Blog
d----- 2022/7/29 16:44 blogs
d----- 2022/7/28 18:24 Blog_env
d----- 2022/7/30 9:56 users
-a---- 2022/7/29 13:47 135168 db.sqlite3
-a---- 2022/7/28 18:27 682 manage.py
(Blog_env) PS Blog>
将users添加到settings.py中 Blog\Blog\settings.py
# Application definition
INSTALLED_APPS = [
# my apps
'blogs',
'users',
# the default applications
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
包含users的URL?Blog\Blog\urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('',include('blogs.urls')),
path('users/',include('users.urls')),
]
2.登录页面
新建?Blog\users\urls.py
"""define the URL pattern for the Users application"""
from django.urls import path, include
app_name = 'users'
urlpatterns = [
# contain the default authentication URL
path('', include('django.contrib.auth.urls')),
]
模板login.html 新建 Blog\users\templates\registration\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">Log in</button>
<input type="hidden" name="next"
value="{% url 'blogs:index' %}" />
</form>
{% endblock content %}
在base.html中添加到登陆页面的链接?
<p>
<a href="{% url 'blogs:index' %}">BLOG</a> -
<a href="{% url 'blogs:new_blog' %}">Add new blog</a> -
{% if user.is_authenticated %}
Hello, {{ user.username }}.
{% else %}
<a href="{% url 'users:login' %}">Log in</a>
{% endif %}
</p>
{% block content %}{% endblock content%}
3.注销
现在需要向用户提交一个注销的途径
在 base.html中添加注销链接 Blog\blogs\templates\blogs\base.html
<p>
<a href="{% url 'blogs:index' %}">BLOG</a> -
<a href="{% url 'blogs:new_blog' %}">Add new blog</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%}
注销确认页面 新建Blog\users\templates\registration\logged_out.html
{% extends 'blogs/base.html' %}
{% block content %}
<p>You have been logged out.Thank you for visiting!</p>
{% endblock content %}
效果:
?
?
4.注册页面
注册页面的URL模式?
"""define the URL pattern for the Users application"""
from django.urls import path, include
from . import views
app_name = 'users'
urlpatterns = [
# contain the default authentication URL
path('', include('django.contrib.auth.urls')),
# register page
path('register/', views.register, name='register'),
]
注册页面的视图函数 Blog\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):
"""register a new user"""
if request.method != 'POST':
# display an empty registration form
form = UserCreationForm()
else:
# process completed forms
form = UserCreationForm(data=request.POST)
if form.is_valid():
new_user = form.save()
# let the user log in automatically and
# redirect to the home page
login(request, new_user)
return redirect('blogs:index')
# display an empty form and indicate that the form is invalid
context = {'form': form}
return render(request, 'registration/register.html', context)
注册页面的模板 Blog\users\templates\registration\register.html
{% extends 'blogs/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 'blogs:index' %}" />
</form>
{% endblock content %}
修改base.html
<p>
<a href="{% url 'blogs:index' %}">BLOG</a> -
<a href="{% url 'blogs:new_blog' %}">Add new blog</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%}
三、重构
注意: 3、4题是对learning_log项目进行修改
修改书中的项目 learning_log\learning_logs\views.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.http import Http404
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
# Create your views here.
def index(request):
"""学习笔记的主页"""
return render(request, 'learning_logs/index.html')
@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)
@login_required
def topic(request, topic_id):
"""显示单个主题及其所有的条目"""
topic = Topic.objects.get(id=topic_id)
# 确认请求的主题属于当前用户
check_topic_owner(topic, request)
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():
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)
@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
check_topic_owner(topic, request)
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)
def check_topic_owner(topic, request):
# 确认请求的主题属于当前用户
if topic.owner != request.user:
raise Http404
效果:
四、保护页面new_entry
?
修改书中的项目 learning_log\learning_logs\views.py
@login_required
def new_entry(request, topic_id):
"""在特定主题中添加新条目"""
topic = Topic.objects.get(id=topic_id)
check_topic_owner(topic, request)
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)
效果:
?
五、受保护的博客
? ? ? ? 我们将创建一个系统,确定各项博文所属的用户。已登录用户能发表、修改自己的博文,任何用户都能访问所有博文
1.使用@login_required限制访问
Blog\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
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
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)
在Blog\Blog\settings.py末尾添加
# my settings
LOGIN_URL = 'users:login'
2.将数据关联到用户
修改模型BlogPost? ?Blog\blogs\models.py
from django.db import models
from django.contrib.auth.models import User
class BlogPost(models.Model):
"""a model of Blog page"""
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)
def __str__(self):
# display simple information about the model
# return a string representation of the model
return self.text
迁移数据库 终端
(Blog_env) PS Blog> python manage.py shell
>>> from django.contrib.auth.models import User
>>> User.objects.all()
<QuerySet [<User: 11-admin>]>
>>> for user in User.objects.all():
... print(user.username, user.id)
...
11-admin 1
>>> exit()
(Blog_env) PS Blog> python manage.py makemigrations blogs
Select an option:1
>>> 1
(Blog_env) PS Blog> python manage.py migrate
(Blog_env) PS Blog> python manage.py shell
>>> from blogs.models import BlogPost
>>> for blog in BlogPost.objects.all():
... print(blog.title, blog.owner)
...
账单同 11-admin
徐梓蕊 11-admin
--snip--
>>> exit()
(Blog_env) PS Blog>
3.保护页面
edit_blog 修改?Blog\blogs\views.py 的部分方法
@login_required
def edit_blog(request,blog_id):
""" 编辑博客 """
blogpost = BlogPost.objects.get(id=blog_id)
title = blogpost.title
# protect the page
if blogpost.owner != request.user:
raise Http404
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)
将新主题关联到当前用户?修改?Blog\blogs\views.py 的部分方法
@login_required
def new_blog(request):
""" 添加新博客 """
if request.method != 'POST':
form = BlogPostForm()
else:
form = BlogPostForm(data=request.POST)
if form.is_valid():
new_blog = form.save(commit=False)
new_blog.owner = request.user
new_blog.save()
return redirect('blogs:index')
context = {'form':form}
return render(request,'blogs/new_blog.html',context)
都看到这里了,不妨点个赞八~
|