目录
前言
这里是《Python从入门到实践》的练习答案,如果有错误或者可以改进的地方欢迎在评论区指正
一、其他表单
下面是官方文档,大家有兴趣可以自行探索哦
new_topic 页面
{% extends "learning_logs/base.html" %}
{% load bootstrap4 %}
{% block content %}
<p><h2>Add a new topic:</h2></p>
<form action="{% url 'learning_logs:new_topic' %}" method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button name="submit" class="btn btn-primary">
Add topic</button>
{% endbuttons %}
</form>
{% endblock content %}
new_entry 页面
{% extends "learning_logs/base.html" %}
{% load bootstrap4 %}
{% block content %}
<p><a href="{% url 'learning_logs:topic' topic.id %}">
<h3>{{ topic }}</h3></a></p>
<p><h4>Add a new entry:</h4></p>
<div class="container">
<form action="{% url 'learning_logs:new_entry' topic.id %}" method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button name="submit" class="btn btn-primary">
Add topic</button>
{% endbuttons %}
</form>
</div>
{% endblock content %}
同理 edit_entry 页面
{% extends "learning_logs/base.html" %}
{% load bootstrap4 %}
{% block content %}
<p><h3><a href="{% url 'learning_logs:topic' topic.id %}">
{{ topic }}</a></h3></p>
<p><h5>Edit entry:</h5></p>
<form action="{% url 'learning_logs:edit_entry' entry.id %}" method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button name="submit" class="btn btn-primary">
Save changes</button>
{% endbuttons %}
</form>
{% endblock content %}
二、设置博客的格式
重写全部html文件
base.html
{% load bootstrap4 %}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1,
shrink-to-fit=no">
<title>BLOG</title>
{% bootstrap_css %}
{% bootstrap_javascript jquery='full' %}
</head>
<body>
<nav class="navbar navbar-expand-md navbar-light bg-light mb-4 border">
<a class="navbar-brand" href="{% url 'blogs:index' %}">BLOG</a>
<button class="navbar-toggler" type="button" data-toggle="collapse"
data-target="#navCollapse" aria-controls="navbarCollapse"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span></button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav mr-auto">
{% if user.is_authenticated %}
<li class="nav-item">
<a class="nav-item nav-link" href="{% url 'blogs:new_blog' %}">
Add new blog</a>
</li>
{% endif %}</ul>
<ul class="navbar-nav ml-auto">
{% if user.is_authenticated %}
<li class="nav-item">
<span class="navbar-text">Hello, {{ user.username }}.</span>
</li>
<li class="nav-item">
<a class="nav-item nav-link" href="{% url 'users:logout' %}">
Log out</a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-item nav-link" href="{% url 'users:register' %}">
Register</a>
</li>
<li class="nav-item">
<a class="nav-item nav-link" href="{% url 'users:login' %}">
Log in</a>
</li>
{% endif %}
</ul>
</div>
</nav>
<main role="main" class="container">
<div class="pb-2 mb-2 border-bottom">
{% block page_header %}{% endblock page_header %}
</div>
<div>
{% block content %}{% endblock content %}
</div>
</main>
</body>
</html>
edit_blog.html
{%extends 'blogs/base.html'%}
{% load bootstrap4 %}
{%block content%}
<p><h3>{{ title }}</h3></p>
<p><h5>Edit Blog:</h5></p>
<form action="{% url 'blogs:edit_blog' blogpost.id %}" method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button name="submit" class="btn btn-primary">
Save changes</button>
{% endbuttons %}
</form>
{%endblock content%}
new_blog.html
{{%extends 'blogs/base.html'%}
{% load bootstrap4 %}
{% block page_header %}
<h2>Add A New Blog</h2>
{% endblock page_header %}
{%block content%}
<form action="{% url 'blogs:new_blog'%}" method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button name="submit" class="btn btn-primary">
Add This Blog</button>
{% endbuttons %}
</form>
{%endblock content%}
index.html
{%extends 'blogs/base.html'%}
{% block page_header %}
<h1>BLOG 主页</h1>
{% endblock page_header %}
{%block content%}
<ul>
{%for blogpost in blogposts%}
<div class="card mb-3">
<h5 class="card-header">
{{ blogpost.date_added|date:'Y/m/d, H:i' }}
<default><a href="{%url 'blogs:edit_blog' blogpost.id%}">
Edit Blog</a></small>
</h5>
<div class="card-body">
<h4>{{blogpost.title}}</h4>
{{blogpost|linebreaks}}
</div>
</div>
{%empty%}
<p>No blogs have been added yet.</p>
{%endfor%}
</ul>
{%endblock content%}
login.html
{% extends 'blogs/base.html' %}
{% load bootstrap4 %}
{% block page_header %}
<h2>Log in to your account.</h2>
{% endblock page_header %}
{% block content %}
<form method="post" action="{% url 'users:login' %}" class="form">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button name="submit" class="btn btn-primary">Log in</button>
{% endbuttons %}
<input type="hidden" name="next"
value="{% url 'blogs:index' %}" />
</form>
{% endblock content %}
logged_out.html
{% extends 'blogs/base.html' %}
{% block content %}
<p><h3>You have been logged out. Thank you for visiting!</h3></p>
{% endblock content %}
register.html
{% extends 'blogs/base.html' %}
{% load bootstrap4 %}
{% block page_header %}
<h2>Register Here</h2>
{% endblock page_header %}
{% block content %}
<form method="post" action="{% url 'users:register' %}">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button name="submit" class="btn btn-primary">
Add This Blog</button>
{% endbuttons %}
<input type="hidden" name="next" value="{% url 'blogs:index' %}" />
</form>
{% endblock content %}
结果:
三、在线博客
部署到云服务器比较麻烦,这里给大家推荐几个博客
windows Git Heroku下载、Heroku注册问题
Heroku CLI 官方链接在此:
现在唯一的问题是注册heroku时需要翻墙才能获得验证码,如果有大佬有方法绕过或者有梯子可以在评论区分享
这一题步骤与书上代码应该一样,这里就不赘述了,上面的博客应该能解决大部分问题
四、在更多情况下显示404错误页面
修改views.py
--snip--
@login_required
def new_entry(request, topic_id):
"""在特定主题中添加新条目"""
topic = get_object_or_404(Topic, id=topic_id)
check_topic_owner(topic, request)
if request.method != 'POST':
# 未提交数据,创建一个空表单
form = EntryForm()
--snip--
@login_required
def edit_entry(request, entry_id):
"""编辑既有条目"""
entry = get_object_or_404(Entry, id=entry_id)
topic = entry.topic
check_topic_owner(topic, request)
if request.method != 'POST':
"""初次请求"""
--snip
效果:
五、扩展“学习笔记”
在主页中对项目做更详细的描述
修改index.html 添加一条中文描述
{% extends "learning_logs/base.html" %}
{% block page_header %}
<div class="jumbotron">
<hi class="display-3">Track your learning.</hi>
<p class="lead">Make your own Learning Log, and keep a list of the
topics you're learning about.Whenever you learn something new
about a topic, make an entry summarizing what you've learned.</p>
<p class="lead">
Learning Log 能让用户记录感兴趣的主题,并在学习每个主题的过程中添加
日志条目。</p>
<a class="btn btn-lg btn-primary" href="{% url 'users:register' %}"
role="button">Register »</a>
</div>
{% endblock page_header %}
效果:
添加将主题设置为公开的功能
1.修改模型
修改models.py中Topic模型 加一个public属性
class Topic(models.Model):
"""用户学习的主题"""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
public = models.BooleanField(default=False)
def __str__(self):
return self.text
2.添加页面
修改urls.py 增加一个新的页面显示公共的主题
"""定义 learning_logs 的 URL 模式"""
from django.urls import path
from . import views
app_name = 'learning_logs'
urlpatterns = [
# 主页
path('', views.index, name='index'),
# 显示所有主题
path('topics/', views.topics, name='topics'),
# 特定主题的详细页面
path('topics/<int:topic_id>/', views.topic, name='topic'),
# 用于添加新主题的页面
path('new_topic/', views.new_topic, name='new_topic'),
# 用于添加新条目的页面
path('new_entry/<int:topic_id>/', views.new_entry, name='new_entry'),
# 用于编辑条目的页面
path('edit_entry/<int:entry_id>/', views.edit_entry, name='edit_entry'),
# 显示公共主题
path('public_topics/', views.public_topics, name='public_topics'),
]
在view.py 中 新增视图函数public_topics,并修改一下topic函数的逻辑
def public_topics(request):
"""显示公开的主题"""
topics = list(Topic.objects.all().order_by('-date_added'))
for topic in topics[:]:
if topic.public == False:
topics.remove(topic)
context = {'topics': topics}
return render(request, 'learning_logs/public_topics.html', context)
--snip--
# @login_required
def topic(request, topic_id):
"""显示单个主题及其所有的条目"""
topic = get_object_or_404(Topic, id=topic_id)
if topic.public == False:
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)
在form.py中 修改TopicForm函数 新增一个表单元素
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text', 'public']
labels = {'text': '', 'public': ''}
3.修改html文件
我们希望所有人都能通过导航栏看见公共主题
修改base.html
--snip--
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="{% url 'learning_logs:topics'%}">
Topics</a></li> _
<li class="nav-item">
<a class="nav-link" href="{% url 'learning_logs:public_topics'%}">
Public Topics</a></li>
</ul>
--snip--
模仿topics.html 新建public.html
{% extends "learning_logs/base.html" %}
{% block page_header %}
<h1>Public Topics</h1>
{% endblock page_header %}
{% block content %}
<ul>
{% for topic in topics %}
<li><h3>
<a href="{% url 'learning_logs:topic' topic.id %}">
{{ topic }}</a>
<a>{{ topic.owner }}</a>
</h3></li>
{% empty %}
<li><h3>No public topics have been added yet.</h3></li>
{% endfor %}
</ul>
{% endblock content %}
非主题所有者不能修改主题
修改 topic.html 的逻辑
{% extends 'learning_logs/base.html' %}
{% block page_header %}
<h3>{{ topic }}</h3>
{% if user == topic.owner %}
<h5>Public: {{ topic.public }}</h5>{% endif %}
{% endblock page_header %}
{% block content %}
{% if user == topic.owner %}
<p>
<a href="{% url 'learning_logs:new_entry' topic.id %}">Add new entry</a>
</p>{% endif %}
{% for entry in entries %}
<div class="card mb-3">
<h4 class="card-header">
{{ entry.date_added|date:'M d, Y H:i' }}
{% if user == topic.owner %}
<small><a href="{% url 'learning_logs:edit_entry' entry.id %}">
edit entry</a></small>{% endif %}
</h4>
<div class="card-body">
{{ entry.text|linebreaks }}
</div>
</div>
{% empty %}
<p>There are no entries for this topic yet.</p>
{% endfor %}
{% endblock content %}
我们希望新建主题时,能提示用户是否将其设置为public
修改new_topic.html
{% extends "learning_logs/base.html" %}
{% load bootstrap4 %}
{% block content %}
<p><h2>Add a new topic:</h2></p>
<form action="{% url 'learning_logs:new_topic' %}" method="post">
{% csrf_token %}
{% bootstrap_form form %}
<div class="checkbox-row">
<label class="vCheckboxLabel" for="id_public">Public or not?</label>
</div>
{% buttons %}
<button name="submit" class="btn btn-primary">
Add topic</button>
{% endbuttons %}
</form>
{% endblock content %}
最后,迁移项目,迁移在线数据库
(ll_env) PS learning_log> git add .
(ll_env) PS learning_log> git commit -am "Add a new function."
(ll_env) PS learning_log> git push heroku master
(ll_env) PS learning_log> heroku run python manage.py migrate
最后,可以在主页解释一下新功能
这样就大功告成了!
都看到这里了不妨点个赞八~