【Django框架】学习笔记

  • 什么是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">&laquo;</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">&raquo;</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">&laquo;</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">&raquo;</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 %}
  • 知识点总结
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349