- 什么是Django
- 浏览器上网的基本原理
- 环境配置
Python3.7安装
https://www.python.org/ftp/python/3.7.8/python-3.7.8-amd64.exe
Django安装
python37 -m pip install Django
Conda安装
https://blog.csdn.net/ITLearnHall/article/details/81708148
PyCharm IDE安装与激活
https://docs.qq.com/doc/DR3Z3aXlxYUZMRFFp
- Django命令
启动一个项目:startproject
启动一个应用:startapp
检查项目完整:check
本地运行项目:runserver
执行用例测试:test
创建迁移文件:makemigrations
执行迁移文件:migrate
进入Python Shell环境:shell
把数据库数据导出到文件:dumpdata
把文件数据导入到数据库:loaddata
- 初识项目
django-admin startproject django_introduction
settings.py:项目配置文件
urls.py:路由配置文件
wsgi.py:wsgi应用的文件内容
python37 manage.py runserver
- 初识应用
Django应用 vs Django项目
python37 manage.py startapp blog
应用目录
- Django视图 & Django路由
设置解释器为python3.7
views.py
from django.http import HttpResponse
def hello_world(request):
return HttpResponse("hello world")
blog.urls.py
from django.urls import path, include
import blog.views
urlpatterns = [
path('hello_world', blog.views.hello_world)
]
django_introduction.urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include('blog.urls'))
]
settings.py
INSTALLED_APPS = [
...
'blog.apps.BlogConfig'
]
- 模型层
- 创建博客文章模型
models.py
from django.db import models
class Article(models.Model):
# 文章ID
article_id = models.AutoField(primary_key=True)
# 文章标题
title = models.TextField()
# 文章摘要
brief_content = models.TextField()
# 文章内容
content = models.TextField()
# 文章日期
publish_date = models.DateTimeField(auto_now=True)
python37 manage.py makemigrations
python37 manage.py migrate
- 初识Django Shell
python37 manage.py shell
>>> from blog.models import Article
>>> a =Article()
>>> a.title = 'Django Test Shell'
>>> a.digest = 'Giao'
>>> a.content = 'Django Test Main content'
>>> a.save()
>>> print(a)
Article object (1)
>>> print(a.title)
Django Test Shell
>>> all = Article.objects.all()
>>> x = all[0]
>>> print(a.content)
Django Test Main content
- 初识Django Admin模块
创建管理员
python37 manage.py createsuperuser
Username (leave blank to use 'yydl'): Du1in9
Email address:
Password:
Password (again):
Superuser created successfully.
admin.py
from django.contrib import admin
from blog.models import Article
admin.site.register(Article)
python37 manage.py runserver
访问登录:http://127.0.0.1:8000/admin/
为了看到标题,models.py新增语句
def __str__(self):
return self.title
新建文章,Ctrl+C关闭,重启
- 实现博客数据返回页面
views.py
from blog.models import Article
...
def article_content(request):
article = Article.objects.all()[0]
title = article.title
brief_content = article.brief_content
content = article.content
article_id = article.article_id
publish_date = article.publish_date
return_str = 'title: %s, brief_content: %s, content: %s, article_id: %s, publish_date: %s' % (title, brief_content, content, article_id, publish_date)
return HttpResponse(return_str)
blog.urls.py
path('content', blog.views.article_content)
python37 manage.py runserver
访问:http://127.0.0.1:8000/blog/content
- 使用Bootstrap实现静态博客页面
Bootstrap官网:https://v3.bootcss.com/
templates.index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>一给我里GiaoGiao</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</head>
<body>
<div class="container page-header">
<h1>
BootCDN简介 <small> —— by Du1in9 </small>
</h1>
</div>
<div class="container page-body">
<div class="col-md-9" role="main">
<div class="body-main">
<div>
<h2>文章标题1</h2>
<p>
Vue 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。
Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。
</p>
<p>
jQuery 是一个高效、精简并且功能丰富的 JavaScript 工具库。它提供的 API 易于使用且兼容众多浏览器,
这让诸如 HTML 文档遍历和操作、事件处理、动画和 Ajax 操作更加简单。
</p>
</div>
<div>
<h2>文章标题2</h2>
<p>
ECharts 是一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,
兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等),底层依赖轻量级的矢量图形库 ZRender,
提供直观,交互丰富,可高度个性化定制的数据可视化图表。
</p>
<p>
Backbone 为复杂 Javascript 应用程序提供模型(models)、集合(collections)、视图(views)的结构。
其中模型用于绑定键值数据和自定义事件;集合附有可枚举函数的丰富 API;
视图可以声明事件处理函数,并通过 RESTful JSON 接口连接到应用程序。
</p>
</div>
</div>
</div>
<div class="col-lg-3" role="complementary">
<h2>最新新闻</h2>
<h4><a href="#">最新新闻1</a> </h4>
<h4><a href="#">最新新闻2</a> </h4>
<h4><a href="#">最新新闻3</a> </h4>
<h4><a href="#">最新新闻4</a> </h4>
<h4><a href="#">最新新闻5</a> </h4>
<h4><a href="#">最新新闻6</a> </h4>
<h4><a href="#">最新新闻7</a> </h4>
<h4><a href="#">最新新闻8</a> </h4>
<h4><a href="#">最新新闻9</a> </h4>
<h4><a href="#">最新新闻10</a> </h4>
</div>
</div>
</body>
</html>
templates.detail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Django Web框架入门</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
</head>
<body>
<div class="container page-header">
<h1>文章标题1
</h1>
</div>
<div class="container body-main">
<div>
<p>
在有些场合,需要对Django处理的每个request都执行某段代码。 这类代码可能是在view处理之前修改传入的request,或者记录日志信息以便于调试,等等。2
这类功能可以用Django的中间件框架来实现,该框架由切入到Django的request/response处理过程中的钩子集合组成。
每个中间件组件都用于某个特定的功能。 如果你是顺着这本书读下来的话,你应该已经多次见到“中间件”了
第12章中所有的session和user工具都籍由一小簇中间件实现(例如,由中间件设定view中可见的 request.session 和 request.user )。
第13章讨论的站点范围cache实际上也是由一个中间件实现,一旦该中间件发现与view相应的response已在缓存中,就不再调用对应的view函数。
第14章所介绍的 flatpages , redirects , 和 csrf
等应用也都是通过中间件组件来完成其魔法般的功能。这个轻量级低层次的plug-in系统,能用于全面的修改Django的输入和输出。1
</p>
<p>
每个中间件组件都用于某个特定的功能。 如果你是顺着这本书读下来的话,你应该已经多次见到“中间件”了
第12章中所有的session和user工具都籍由一小簇中间件实现(例如,由中间件设定view中可见的 request.session 和 request.user )。
第13章讨论的站点范围cache实际上也是由一个中间件实现,一旦该中间件发现与view相应的response已在缓存中,就不再调用对应的view函数。
第14章所介绍的 flatpages , redirects , 和 csrf 等应用也都是通过中间件组件来完成其魔法般的功能。
</p>
</div>
</div>
</body>
</html>
- 模板系统基本语法
变量标签:{{ x }}
for循环标签:{% for x in list %},{% endfor %}
if-else分支标签:{% if %},{% else %},{% endif %}
templates.template.html
<html>
<head><title>Ordering notice</title></head>
<body>
<h1>Ordering notice</h1>
<p>Dear {{ person_name }},</p>
<p>Thanks for placing an order from {{ company }}. It's scheduled to
ship on {{ ship_date|date:"F j, Y" }}.</p>
<p>Here are the items you've ordered:</p>
<ul>
{% for item in item_list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% if ordered_warranty %}
<p>Your warranty information will be included in the packaging.</p>
{% else %}
<p>You didn't order a warranty, so you're on your own when
the products inevitably stop working.</p>
{% endif %}
<p>Sincerely,<br/>{{ company }}</p>
</body>
</html>
- 模板系统渲染页面
使用以下脚本导入data.article的多篇文章
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_introduction.settings')
django.setup()
from blog.models import Article
data_path = '../data/article'
def main():
content_list = []
files = os.listdir(data_path)
for name in files:
f = os.path.join(data_path, name)
with open(f, 'r', encoding='utf-8') as f:
content = f.read()
item = (name[:-4], content[:100], content)
content_list.append(item)
# Article.objects.all().delete()
for item in content_list:
print('saving article: %s' % item[0])
article = Article()
article.title = item[0]
article.brief_content = item[1]
article.content = item[2]
article.save()
if __name__ == '__main__':
main()
templates.index.html
<div class="container page-body">
<div class="col-md-9" role="main">
<div class="body-main">
{% for article in article_list %}
<div>
<h2><a href="#">{{ article.title }}</a></h2>
<p>{{article.digest}}</p>
</div>
{% endfor %}
</div>
</div>
<div class="col-md-3" role="complementary">
<div>
<h2>最新文章</h2>
{% for article in article_list %}
<h4><a href="#">{{ article.title }}</a></h4>
{% endfor %}
</div>
</div>
</div>
templates.detail.html
<div class="container page-header">
<h1>{{ curr_article.title }}
</h1>
</div>
<div class="container body-main">
<div>
{% for section in section_list %}
<p>{{ section }}</p>
{% endfor %}
</div>
</div>
views.py
from django.shortcuts import render
...
def get_index_page(request):
all_article = Article.objects.all()
return render(request, 'blog/index.html',
{
'article_list':all_article
}
)
def get_detail_page(request):
curr_article = Article.objects.all()[1]
section_list = curr_article.content.split('\n')
return render(request, 'blog/detail.html',
{
'curr_article': curr_article,
'section_list': section_list
}
)
blog.urls.py
path('index', blog.views.get_index_page),
path('detail', blog.views.get_detail_page)
- 实现页面的跳转
1)指定id跳转文章详情页
urls.py
# path('detail', blog.views.get_detail_page),
path('detail/<int:article_id>', blog.views.get_detail_page)
views.py
def get_detail_page(request, id):
all_article = Article.objects.all()
curr_article = None
for article in all_article:
if article.article_id == article_id:
curr_article = article
break
2)主页跳转文章详情页
index.html
<h2><a href="/blog/detail/{{article.article_id}}">{{ article.title }}</a></h2>
...
<h4><a href="/blog/detail/{{article.article_id}}">{{ article.title }}</a></h4>
- 实现上下篇文章跳转
detail.html
<div>
<nav aria-label="...">
<ul class="pager">
<li><a href="/blog/detail/{{ previous_article.article_id }}">上一篇:{{ previous_article.title }}</a></li>
<li><a href="/blog/detail/{{ next_article.article_id }}">下一篇:{{ next_article.title }}</a></li>
</ul>
</nav>
</div>
views.py
def get_detail_page(request, article_id):
all_article = Article.objects.all()
curr_article = None
previous_article = None
next_article = None
previous_index = 0
next_index = 0
for index, article in enumerate(all_article):
# 前面
if index == 0:
previous_index = 0
next_index = index + 1
# 后面
elif index == len(all_article) - 1:
previous_index = index - 1
next_index = index
# 中间
else:
previous_index = index - 1
next_index = index + 1
# article
if article.article_id == article_id:
curr_article = article
previous_article = all_article[previous_index]
next_article = all_article[next_index]
break
...
'previous_article': previous_article,
'next_article': next_article
- 实现分页功能
1)主页按钮
index.html
<div class="body-footer">
<div class="col-md-4 col-md-offset-3">
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
2)设计分页的url
views.py
def get_index_page(request):
page = request.GET.get('page')
if page:
page = int(page)
else:
page = 1
print('page param: ', page)
访问http://127.0.0.1:8000/blog/index?page=2,再看终端
用shell调试Django分页功能
>>> from django.core.paginator import Paginator
>>> l = [1,2,3,4,5]
>>> p = Paginator(l,2)
>>> p.num_pages
3
>>> p.count
5
>>> p1 = p.page(1)
>>> p2 = p.page(2)
>>> p1.object_list
[1, 2]
>>> p2.object_list
[3, 4]
>>> p2.has_next()
True
>>> p1.has_previous()
False
>>>
views.py
def get_index_page(request):
# 获得参数
page = request.GET.get('page')
if page:
page = int(page)
else:
page = 1
print('page param: ', page)
all_article = Article.objects.all()
# 生成页面
paginator = Paginator(all_article, 6)
page_num = paginator.num_pages
print('page num:', page_num)
# 页面列表
page_article_list = paginator.page(page)
if page_article_list.has_next():
next_page = page + 1
# 最后
else:
next_page = page
if page_article_list.has_previous():
previous_page = page - 1
# 最前
else:
previous_page = page
return render(request, 'blog/index.html',
{
'article_list': page_article_list,
'page_num': range(1, page_num + 1),
'curr_page': page,
'next_page': next_page,
'previous_page': previous_page
}
)
index.html
<div class="body-footer">
<div class="col-md-4 col-md-offset-3">
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a href="/blog/index?page={{previous_page}}" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% for num in page_num %}
<li><a href="/blog/index?page={{num}}">{{ num }}</a></li>
{% endfor %}
<li>
<a href="/blog/index?page={{next_page}}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
- 实现最近文章列表
views.py
top10_article_list = Article.objects.order_by('-publish_date')[:10]
...
'top10_article_list': top10_article_list
index.py
{% for article in top10_article_list %}
<h4><a href="/blog/detail/{{article.article_id}}">{{ article.title }}</a></h4>
{% endfor %}
- 知识点总结