美文网首页大数据 爬虫Python AI Sql
十五分钟包你学会Python Django框架实现web开发!

十五分钟包你学会Python Django框架实现web开发!

作者: 1a076099f916 | 来源:发表于2018-12-24 15:40 被阅读7次

    入门Python其实很容易,但是我们要去坚持学习,每一天坚持很困难,我相信很多人学了一个星期就放弃了,为什么呢?其实没有好的学习资料给你去学习,你们是很难坚持的,这是小编收集的Python入门学习资料,加小编QQ群:943752371可以获取!希望对你们有帮助!

    十五分钟包你学会Python Django框架实现web开发!

    1、安装python环境

    1.1 安装python包管理器:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">wget https://bootstrap.pypa.io/get-pip.py
    sudo python get-pip.py
    </pre>

    1.2 安装python虚拟环境virtualenv virtualenvwrapper

    首先说明下为什么要装这两个包:

    First, it’s important to understand that a virtual environment is a special tool used to keep the dependencies required by different projects in separate places by creating isolated, independent Python environments for each of them.

    In short, it solves the “Project X depends on version 1.x, but Project Y needs 4.x” dilemma. It also keeps your global site-packages neat, tidy, and free from clutter.

    If you would like a full explanation on why Python virtual environments are good practice, absolutely give this excellent blog post on RealPython a read.

    用虚拟开发环境可以为每个工程提供独立的python开发环境、独立的包、独立的版本,每个独立的环境会在~/.virtualenvs/下形成资源包~

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">sudo pip install virtualenv virtualenvwrapper
    sudo rm -rf ~/.cache/pip
    </pre>

    之后在~/.profile文件最后添加下面几行:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);"># virtualenv and virtualenvwrapper
    export WORKON_HOME=$HOME/.virtualenvs
    source /usr/local/bin/virtualenvwrapper.sh
    </pre>

    之后如果想用python虚拟环境,在每次打开一个新的terminal就要执行一次source ~/.profile

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">source ~/.profile
    </pre>

    接下来我们生成一个python虚拟环境来用于python-web的开发提供环境:(这里用的是python2.7)

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">mkvirtualenv python_web -p python2
    </pre>

    注:再次说明python虚拟环境是完全独立的,也就是说在python_web的环境下安装的python包,步适用于全局;在全局安装的包,不适合python_web。

    如何验证你如何将python_web环境生成好了呢?——新开一个terminal,执行下列命令:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">source ~/.profile
    workon python_web
    </pre>

    如果terminal前面的文字变成了(python_web)表明成功创建了名为cv的python虚拟环境;

    2、安装Django

    从官网上得知2.7版本的python可使用最高1.11版本的Django,因此在python_web环境中安装:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">pip install Django==1.11
    </pre>

    测试Django有没有安装成功,进入python命令交互模式:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">import django
    django.VERSION
    </pre>

    3、第一个例子hello world

    找到你的django-admin.py文件,并把它加入系统路径。如果用的是setup.py工具安装的Django,django-admin.py应该已被加入了系统路径中。我的django-admin.py的目录为:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">/root/.virtualenvs/python_web/lib/python2.7/site-packages/django/bin
    </pre>

    进入该目录下,运行如下命令,新建一个项目:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">python django-admin.py startproject mysite
    </pre>

    startproject命令创建一个目录,包含一个名为mysite的文件夹和一个名为manage.py的文件。其中mysite文件夹下包含有四个文件,分别为:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">(python_web) ➜ mysite tree
    .
    ├── db.sqlite3
    ├── manage.py
    └── mysite
    ├── init.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py
    </pre>

    为了安装后更多的体验,让我们运行一下django开发服务器看看我们的准系统。django开发服务是可用在开发期间的,一个内建的,轻量的web服务。 我们提供这个服务器是为了让你快速开发站点,也就是说在准备发布产品之前,无需进行产品级 Web 服务器(比如 Apache)的配置工作。 开发服务器监测你的代码并自动加载它,这样你会很容易修改代码而不用重启动服务。如果你还没启动服务器的话,请切换到你的项目目录里 (cd mysite),运行下面的命令:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">python manage.py runserver
    </pre>

    你会看到如下内容:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">Django version 1.11, using settings 'mysite.settings'
    Starting development server at http://127.0.0.1:3000/
    Quit the server with CTRL-BREAK
    </pre>

    这将会在端口3000启动一个本地服务器, 并且只能从你的这台电脑连接和访问。 既然服务器已经运行起来了,现在用网页浏览器访问 http://127.0.0.1:8000/ 。 你应该可以看到一个令人赏心悦目的淡蓝色Django欢迎页面。 表明它开始工作了。

    但是我的服务器搭在阿里云上,并且绑定了phage.cc的域名,因此可以通过这样的方式使之能访问:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">python manage.py runserver 0.0.0.0:3000
    </pre>

    注:0.0.0.0”这个IP地址,告诉服务器去侦听任意的网络接口。

    注:采用phage.cc:3000去访问会报错误 alid HTTP_HOST header: 'www.phage.cc:3000'. You may need to add u'www.phage.cc' to ALLOWED_HOSTS. 可以通过添加允许来实现通过:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">settings.py : ALLOWED_HOSTS = [u'www.phage.cc']
    </pre>

    4、自己建视图

    4.1 静态视图hello world

    在文件夹mysite中新建一个views.py的文件:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">from django.http import HttpResponse
    def hello(request):
    return HttpResponse("Hello world")
    </pre>

    在这段代码中:我们定义一个叫做hello 的视图函数,这个函数只有简单的一行代码: 它仅仅返回一个HttpResponse对象,这个对象包含了文本“Hello world”。

    注:每个视图函数至少要有一个参数,通常被叫作request。 这是一个触发这个视图、包含当前Web请求信息的对象,是类django.http.HttpRequest的一个实例。在这个示例中,我们虽然不用request做任何事情,然而它仍必须是这个视图的第一个参数。

    注:视图函数的名称并不重要;并不一定非得以某种特定的方式命名才能让 Django 识别它。 在这里我们把它命名为:hello,是因为这个名称清晰的显示了视图的用意。

    4.2 URLconf将视图和URL绑定(类似nodejs中的路由)

    URLconf 就像是 Django 所支撑网站的目录。 它的本质是 URL 模式以及要为该 URL 模式调用的视图函数之间的映射表。 你就是以这种方式告诉 Django,对于这个 URL 调用这段代码,对于那个 URL 调用那段代码。

    这个映射表在urls.py中,我们想要实现访问/hello/调用hello视图,返回hello world需要做下面样子修改:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">from django.conf.urls import url
    urlpatterns = [
    url(r'^hello//pre>, hello),
    ]
    </pre>

    注:这里的^hello/$是正则表达式,匹配所有/hello/形式的请求。

    之后我们运行该服务器,在浏览器中可以访问hello视图: http://www.phage.cc:3000/hello/

    4.3 动态内容视图请求当前时间

    在views.py中添加一个新视图current_datatime:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">from django.http import HttpResponse
    import datetime
    def hello(request):
    return HttpResponse("Hello world")
    def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)
    </pre>

    类似hello视图,这里用了python的datetime工具,获取时间并合成一个html字符串,作为视图返回。

    同理,我们也需要在urls.py中做url映射:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">from django.conf.urls import url
    from mysite.views import hello, current_datetime
    urlpatterns = [
    url(r'^hello//pre>, hello),
    url(r'^time//pre>, current_datetime),
    ]
    </pre>

    这样我们通过访问 http://www.phage.cc:3000/time/ 可以获取time视图返回。

    4.4 动态URL视图

    在我们的 current_datetime 视图范例中,尽管内容是动态的,但是URL ( /time/ )是静态的。 在 大多数动态web应用程序,URL通常都包含有相关的参数。 举个例子,一家在线书店会为每一本书提供一个URL,如:/books/243/、/books/81196/。

    让我们创建第三个视图来显示当前时间和加上时间偏差量的时间,设计是这样的: /time/plus/1/ 显示当前时间+1个小时的页面 /time/plus/2/ 显示当前时间+2个小时的页面 /time/plus/3/ 显示当前时间+3个小时的页面,以此类推。

    注:在java或php中有可能见到这样的实现:/time/plus?hours=3,但这样被认为不漂亮

    之前我们已经看到url是以正则表达式的形式出现,因此想要实现/time/plus/xxx/也就比较容易了:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">from django.conf.urls import url
    from mysite.views import hello, current_datetime, hours_ahead
    urlpatterns = [
    url(r'^hello//pre>, hello),
    url(r'^time//pre>, current_datetime),
    url(r'^time/plus/(d{1,2})//pre>, hours_ahead),
    ]
    </pre>

    那么我们如是实现hours_ahead来接收请求中的xxx数字呢?

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">from django.http import Http404, HttpResponse
    import datetime
    ...
    def hours_ahead(request, offset):
    try:
    offset = int(offset)
    except ValueError:
    raise Http404()
    dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
    html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt)
    return HttpResponse(html)
    </pre>

    hours_ahead 和我们以前写的 current_datetime 很象,关键的区别在于: 它多了一个额外参数,时间差。

    注:offset 是从匹配的URL里提取出来的。 例如:如果请求URL是/time/plus/3/,那么offset将会是3;如果请求URL是/time/plus/21/,那么offset将会是21。请注意:捕获值永远都是字符串(string)类型,而不会是整数(integer)类型,即使这个字符串全由数字构成(如:“21”)。

    注:在这里我们命名变量为 offset ,你也可以任意命名它,只要符合Python 的语法。 变量名是无关紧要的,重要的是它的位置,它是这个函数的第二个 参数 (在 request 的后面)。 你还可以使用关键字来定义它,而不是用 位置。

    5、模板

    5.1 最简单的模板DEMO

    模板的好处是将python和html分开,下面是一个最简单的例子:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">def template_test(request):
    now = datetime.datetime.now()
    t = Template("<html><body>It is now {{ current_date }}.</body></html>");
    html = t.render(Context({'current_date': now}))
    return HttpResponse(html)
    </pre>

    上面的例子在html中嵌入一个 current_date 变量,通过context给变量赋值,通过render来渲染。除了双大括号表示的变量,还有循环、条件等各种玩法: https://docs.djangoproject.com/en/2.1/ref/templates/builtins/

    5.2 将html和python彻底分离

    但是上面我们并没有真正将html和python分离,更进一步的做法是将html单独放置:

    1. 在mysite下新建一个文件夹:templates,并在其中新建一个template_test1.html:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);"><html><body>It is now {{ current_date }}.</body></html>
    </pre>

    1. 而我们的template_test就能改造成:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">def template_test1(request):
    now = datetime.datetime.now()
    t = get_template('template_test1.html');
    html = t.render({'current_date': now})
    return HttpResponse(html)
    </pre>

    1. 最后我们得通过下面方法让get_template的输入参数不用写完整路径:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">TEMPLATES = [
    {
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [os.path.join(os.path.dirname(file), 'templates').replace('','/'),],
    'APP_DIRS': True,
    'OPTIONS': {
    </pre>

    注:我们还可以用render_to_response来简化template_test操作:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">def template_test2(request):
    now = datetime.datetime.now()
    return render_to_response('template_test1.html', {'current_date': now})
    </pre>

    5.3 模板继承

    一个多页面的网站,其每个页面可能会有相同的头部、尾部的结构,主页面的内容存在更新变动。如果我们为每个页面单独创建一个独立的html将会产生大量冗余,此外如果我们想要对所有页面的头部做一个修改,也将比较麻烦。此时我们可以采用模板的思想来完美解决这个问题:

    1)新建一个母版html(base.html)

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">(python_web) ➜ templates git:(master) cat base.html
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
    <html lang="en">
    <head>
    <title>{% block title %}{% endblock %}</title>
    </head>
    <body>
    <h1>My helpful timestamp site</h1>
    {% block content %}{% endblock %}
    {% block footer %}



    <p>Thanks for visiting my site.</p>
    {% endblock %}
    </body>
    </html>
    </pre>
    1. 创建一个继承base.html的template_test2_use_base_1.html:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">(python_web) ➜ templates git:(master) cat template_test2_use_base_1.html
    {% extends "base.html" %}
    {% block title %}The current time{% endblock %}
    {% block content %}
    <p>It is now {{ current_date }}.</p>
    {% endblock %}
    </pre>

    1. 再创建一个继承base.html的template_test2_use_base_2.html:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">(python_web) ➜ templates git:(master) cat template_test2_use_base_2.html
    {% extends "base.html" %}
    {% block title %}Future time{% endblock %}
    {% block content %}
    <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>
    {% endblock %}
    </pre>

    可见base.html中的{% block title %}{% endblock %} 、{% block content %}{% endblock %} 、{% block footer %}{% endblock %} 都可以被继承者们重新实现!

    注:当然,如果继承者没有实现,则不会显示。

    6、python django的数据库操作

    6.1 安装MYSQL数据库

    我们先在linux上安装数据库:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">sudo apt-get install mysql-server
    sudo apt-get install libmysqlclient-dev
    </pre>

    安装过程中会提示设置密码什么的,注意设置了不要忘了,安装完成之后可以使用如下命令来检查是否安装成功:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">sudo netstat -tap | grep mysql
    </pre>

    通过上述命令检查之后,如果看到有mysql 的socket处于 listen 状态则表示安装成功。

    登陆mysql数据库可以通过如下命令:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">mysql -u root -p
    </pre>

    -u 表示选择登陆的用户名, -p 表示登陆的用户密码,上面命令输入之后会提示输入密码,此时输入密码就可以登录到mysql。

    下面是一些命令行中操作的DEMO,可做今后参考:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">mysqladmin -u root -p create blog
    mysql mysql -u root -p
    show databases;
    use blog;
    CREATE TABLE IF NOT EXISTS blog_table(
    blogId BIGINT UNSIGNED,
    url VARCHAR(100) NOT NULL,
    title VARCHAR(1000) NOT NULL,
    support INT UNSIGNED,
    pageView INT UNSIGNED,
    PRIMARY KEY ( blogId )
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;
    CREATE TABLE IF NOT EXISTS tag_table(
    tagId INT UNSIGNED AUTO_INCREMENT,
    tagName VARCHAR(100) NOT NULL,
    PRIMARY KEY ( tagId )
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;
    CREATE TABLE IF NOT EXISTS blog_tag_relation_table(
    relationId INT UNSIGNED AUTO_INCREMENT,
    blogId BIGINT UNSIGNED,
    tagId INT UNSIGNED,
    PRIMARY KEY ( relationId )
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;
    show tables;
    desc blog_table;
    desc tag_table;
    desc blog_tag_relation_table;
    //change blogId int 2 bigint
    alter table blog_table change blogId blogId BIGINT UNSIGNED;
    //show data
    select * from blog_table;
    //delete data
    delete from blog_table where blogId=201801021423;
    INSERT INTO blog_table(blogId,url,title,support,pageView)
    VALUES(201801021423,'http://106.14.226.191:3000/blog/201607281658.html','[商业法务] 1、公司一款新消费类电子产品如何快速全面的专利保护',0,0);
    //too short
    alter table blog_table change title title VARCHAR(1000) NOT NULL;
    INSERT INTO tag_table(tagId,tagName)
    VALUES(0,'硬件
    模拟电路');
    select * from blog_table;
    select * from tag_table;
    select * from blog_tag_relation_table;
    delete from blog_table where blogId>0;
    delete from tag_table where tagId>=0;
    delete from blog_tag_relation_table where relationId >= 0;
    select a.title , a.url, b.tagName from blog_table a, tag_table b, blog_tag_relation_table c WHERE a.blogId = c.blogId AND a.blogId = 201602021408 AND b.tagId = c.tagId;
    select a.title , a.url, b.tagName from blog_table a, tag_table b, blog_tag_relation_table c WHERE a.blogId = c.blogId AND b.tagId = c.tagId ORDER BY b.tagId;
    </pre>

    为了python操作mysql需要执行下面命令:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">pip install MySQL-python
    </pre>

    6.2 配置及测试数据库

    在settings.py中下面几项是对数据库的配置:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'pyserver',
    'USER': 'root',
    'PASSWORD': '123456',
    }
    }
    </pre>

    一旦在输入了那些设置并保存之后应当测试一下你的配置。 我们可以在 mysite 项目目录下执行 python manage.py shell 来进行测试(没有错误表示成功):

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">from django.db import connection
    cursor = connection.cursor()
    </pre>

    6.3 创建books app

    在 mysite 项目文件下输入下面的命令来创建 books app:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">python manage.py startapp books
    </pre>

    这个命令并没有输出什么,它只在 mysite 的目录里创建了一个 books 目录。 让我们来看看这个目录的内容:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">(python_web) ➜ books tree
    .
    ├── admin.py
    ├── apps.py
    ├── init.py
    ├── migrations
    │ └── init.py
    ├── models.py
    ├── tests.py
    └── views.py
    </pre>

    这个目录包含了这个app的模型和视图。

    6.4 编写模型

    编辑 models.py :

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">from django.db import models
    class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()
    class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField()
    class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()
    </pre>

    Publisher 模块相当于SQL语句:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">CREATE TABLE "books_publisher" (
    "id" serial NOT NULL PRIMARY KEY,
    "name" varchar(30) NOT NULL,
    "address" varchar(50) NOT NULL,
    "city" varchar(60) NOT NULL,
    "state_province" varchar(30) NOT NULL,
    "country" varchar(50) NOT NULL,
    "website" varchar(200) NOT NULL
    );
    </pre>

    6.5 由模型自动生成创建表SQL

    再次编辑settings.py,将下面列出选项加 # 注释掉,并添加 ‘mysite.books’ 到 INSTALLED_APPS 的末尾:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">INSTALLED_APPS = [

    'django.contrib.admin',

    'django.contrib.auth',

    'django.contrib.contenttypes',

    'django.contrib.sessions',

    'django.contrib.messages',

    'django.contrib.staticfiles',

    'books',
    ]
    MIDDLEWARE = [

    'django.middleware.security.SecurityMiddleware',

    'django.contrib.sessions.middleware.SessionMiddleware',

    'django.middleware.common.CommonMiddleware',

    'django.middleware.csrf.CsrfViewMiddleware',

    'django.contrib.auth.middleware.AuthenticationMiddleware',

    'django.contrib.messages.middleware.MessageMiddleware',

    'django.middleware.clickjacking.XFrameOptionsMiddleware',

    ]
    </pre>

    你可能会执行python manage.py validate ,然后你会特别伤心的看到人家提示Unknown command: 'validate'Type 'manage.py help' for usage.,对吧?所以你要用如下这个命令:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">python manage.py check
    </pre>

    然后你还想生成sql语句,你就运行了python manage.py sqlall books,错误提示是Unknown command: 'sqlall'Type 'manage.py help' for usage.同样如果你想提交sql语句到数据库而运行syncdb,错误提示是Unknown command: 'syncdb'

    Type 'manage.py help' for usage. 为什么没有这些命令,因为它们被淘汰了。所以你只需运行如下的命令:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">python manage.py makemigrations books #用来检测数据库变更和生成数据库迁移文件
    python manage.py migrate #用来迁移数据库(直接到数据库)
    python manage.py sqlmigrate books 0001 # 用来把数据库迁移文件转换成数据库语言
    </pre>

    6.6 基本数据访问

    一旦你创建了模型,Django自动为这些模型提供了高级的Python API。 运行 python manage.py shell 并输入下面的内容试试看:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">>>> from books.models import Publisher

    p1 = Publisher(name='Apress', address='2855 Telegraph Avenue',
    ... city='Berkeley', state_province='CA', country='U.S.A.',
    ... website='http://www.apress.com/')
    p1.save()
    p2 = Publisher(name="O'Reilly", address='10 Fawcett St.',
    ... city='Cambridge', state_province='MA', country='U.S.A.',
    ... website='http://www.oreilly.com/')
    p2.save()
    publisher_list = Publisher.objects.all()
    publisher_list
    [<Publisher: Publisher object>, <Publisher: Publisher object>]
    </pre>

    其他常用基本操作如下:

    • 创建: p1 = Publisher.objects.create(....)
    • 修改: p1.name = 'Apress Publishing'
    • 过滤: Publisher.objects.filter(country="U.S.A.", state_province="CA")
    • 单个: Publisher.objects.get(name="Apress")
    • 排序: Publisher.objects.order_by("state_province", "address")
    • 查询: Publisher.objects.filter(country="U.S.A.").order_by("-name")
    • 数组: Publisher.objects.order_by('name')[0] or [0:2]
    • 多个: Publisher.objects.filter(id=52).update(name='Apress Publishing')
    • 保存: p.save()
    • 删除: p.delete()

    注意:上述操作除了删除,每个操作之后都别忘了保存!

    7、站点管理

    7.1 基本操作

    编辑settings.py:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'books',
    ]
    MIDDLEWARE = [

    'django.middleware.security.SecurityMiddleware',

    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',

    'django.middleware.csrf.CsrfViewMiddleware',

    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',

    'django.middleware.clickjacking.XFrameOptionsMiddleware',

    ]
    </pre>

    之后运行 python manage.py migrate 这一步将生成管理界面使用的额外数据库表。 当你把'django.contrib.auth'加进INSTALLED_APPS后,第一次运行syncdb命令时, 系统会请你创建一个超级用户。 如果你不这么作,你需要运行python manage.py createsuperuser来另外创建一个admin的用户帐号,否则你将不能登入admin(我这里设置user:admin password:xxxxxx)

    将admin访问配置在URLconf(记住,在urls.py中)

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">from django.conf.urls import url
    from django.contrib import admin
    from django.conf.urls import include

    from mysite.views import hello

    from mysite.views import hello, current_datetime, hours_ahead, template_test, template_test1, template_test2, template_test3, template_test4
    admin.autodiscover()
    urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    ...
    ]
    </pre>

    此时运行 python manage.py runserver 0.0.0.0:8080 ,然后在浏览器中访问: http://www.phage.cc:8080/admin/

    注:NameError: name 'include' is not defined错误需要from django.conf.urls import include;

    注:django nginx admin css丢失需要在settings.py中INSTALLED_APPS中加 django.contrib.staticfiles ;

    7.2 管理工具简介

    管理界面的设计是针对非技术人员的,所以它应该是自我解释的。 尽管如此,这里简单介绍一下它的基本特性:

    1)登录页面(用户名密码就是刚刚生成的admin,xxxxxxxxx)

    十五分钟包你学会Python Django框架实现web开发!

    你要使用你原来设置的超级用户的用户名和密码。 如果无法登录,请运行 python manage.py createsuperuser ,确保你已经创建了一个超级用户。

    2)一旦登录了,你将看到管理页面:

    十五分钟包你学会Python Django框架实现web开发!

    这个页面列出了管理工具中可编辑的所有数据类型。 现在,由于我们还没有创建任何模块,所以这个列表只有寥寥数条类目: 它仅有两个默认的管理-编辑模块:用户组(Groups)和用户(Users)。

    3)点进去USER可以添加、修改、删除等操作,非常方便:

    十五分钟包你学会Python Django框架实现web开发!

    7.3 将其他Models加入到Admin管理中

    有一个关键步骤我们还没做。 让我们将自己的模块加入管理工具中,这样我们就能够通过这个漂亮的界面添加、修改和删除数据库中的对象了。 我们将继续第五章中的 book 例子。在其中,我们定义了三个模块: Publisher 、 Author 和 Book 。

    编辑 mysite/books/admin.py ,然后输入:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);"># -- coding: utf-8 --
    from future import unicode_literals
    from django.contrib import admin
    from books.models import Publisher, Author, Book
    admin.site.register(Publisher)
    admin.site.register(Author)
    admin.site.register(Book)

    Register your models here.

    </pre>

    重启服务器,现在再去admin主页,就会看到Publisher 、 Author 和 Book模块,这样就能编辑这些模块了!

    7.4 工作原理

    当服务启动时,Django从 url.py 引导URLconf,然后执行 admin.autodiscover() 语句。 这个函数遍历INSTALLED_APPS配置,并且寻找相关的 admin.py文件。 如果在指定的app目录下找到admin.py,它就执行其中的代码。

    在 books 应用程序目录下的 admin.py 文件中,每次调用 admin.site.register() 都将那个模块注册到管理工具中。 管理工具只为那些明确注册了的模块显示一个编辑/修改的界面。

    7.5 设置字段可选

    • 可以为空: email = models.EmailField(blank=True )
    • 自定义字段标签: email = models.EmailField(blank=True, verbose_name='e-mail' )
    • 自定义列表:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True, verbose_name='e-mail')
    def unicode(self):
    return u'%s %s' % (self.first_name, self.last_name)
    </pre>

    注:更多展示自定义可以参考 [12]. The Django Book - 第六章 Django站点管理

    8、表单

    8.1 URL相关信息

    HttpRequest对象包含当前请求URL的一些信息:

    属性/方法说明举例request.path除域名以外的请求路径,以正斜杠开头"/hello/"request.get_host()主机名(比如,通常所说的域名)"127.0.0.1:8000" or "www.example.com"request.get_full_path()请求路径,可能包含查询字符串"/hello/?print=true"request.is_secure()如果通过HTTPS访问,则此方法返回True, 否则返回FalseTrue 或者 False

    8.2 一个简单的SEARCH表单

    views.search()

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">def search(request):
    error = False
    if 'q' in request.GET:
    q = request.GET['q']
    if not q:
    error = True
    else:
    books = Book.objects.filter(title__icontains=q)
    return render_to_response('search_results.html',{'books': books, 'query': q})
    return render_to_response('search_form.html',{'error': error})
    </pre>

    search_form.html

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);"><html>
    <head>
    <title>Search</title>
    </head>
    <body>
    {% if error %}
    <p style="color: red;">Please submit a search term.</p>
    {% endif %}
    <form action="" method="get">
    <input type="text" name="q">
    <input type="submit" value="Search">
    </form>
    </body>
    </html>
    </pre>

    search_results.html

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);"><p>You searched for: <strong>{{ query }}</strong></p>
    {% if books %}
    <p>Found {{ books|length }} book{{ books|pluralize }}.</p>
    <ul>
    {% for book in books %}
    <li>{{ book.title }}</li>
    {% endfor %}
    </ul>
    {% else %}
    <p>No books matched your search criteria.</p>
    {% endif %}
    </pre>

    更高级的用法我们在后面的DEMO中介绍!

    9、实战-实操一个github上1.6K star量的博客系统

    项目地址: https://github.com/zmrenwu/django-blog-tutorial

    项目master: https://github.com/zmrenwu

    9.1 将项目部署在我们买AliYun上

    下载项目到本地:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">cd ~/App/
    git clone https://github.com/zmrenwu/django-blog-tutorial.git
    </pre>

    创建并激活虚拟环境(一定要注意是python3):

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">virtualenv blogproject_env -p python3
    source blogproject_env/bin/activate
    </pre>

    安装依赖并数据迁移(sqlite的):

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">pip install -r requirements.txt
    python manage.py migrate
    </pre>

    创建后台管理员账户并启动服务器(我这里其他端口被占用,因此用8080):

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">python manage.py createsuperuser
    python manage.py runserver 0.0.0.0:8080
    </pre>

    由于我们不是在本地运行,因此还得在settings.py中添加: ALLOWED_HOSTS = [u'www.phage.cc']。此时,便可以访问 http://www.phage.cc:8080/admin/ 对品类、文章、标签、用户等进行管理了:

    十五分钟包你学会Python Django框架实现web开发!

    访问: http://www.phage.cc:8080/ 便可看到我们在后台添加的 python-django 文章:

    十五分钟包你学会Python Django框架实现web开发!

    9.2 代码解析

    首先看看所有支持的url入口配置文件:/blog/urls.py

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">from django.conf.urls import url
    from . import views
    app_name = 'blog'
    urlpatterns = [
    url(r'^/pre>, views.IndexView.as_view(), name='index'),
    url(r'^post/(?P<pk>[0-9]+)//pre>, views.PostDetailView.as_view(), name='detail'),
    url(r'^archives/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})//pre>, views.ArchivesView.as_view(), name='archives'),
    url(r'^category/(?P<pk>[0-9]+)//pre>, views.CategoryView.as_view(), name='category'),
    url(r'^tag/(?P<pk>[0-9]+)//pre>, views.TagView.as_view(), name='tag'),

    url(r'^search//pre>, views.search, name='search'),

    ]
    </pre>

    其主页调用views.IndexView.as_view()实现的,但是为什么有第三个参数name='idnex'呢?我们看/blog/view.py的IndexView就明白了,这里类IndexView继承Django的Generic display views来实现的,看一下 Generic display views 中的ListViewd的用法就明白了。其他的各种入口则依此类推:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">class IndexView(ListView):
    ...
    class PostDetailView(DetailView):
    ...
    class ArchivesView(ListView):
    ...
    class CategoryView(ListView):
    ...
    class TagView(ListView):
    ...
    </pre>

    我们倒着分析各个入口的实现(倒着由浅入深),看第一个TagView的实现:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">class TagView(ListView):
    model = Post
    template_name = 'blog/index.html'
    context_object_name = 'post_list'
    def get_queryset(self):
    tag = get_object_or_404(Tag, pk=self.kwargs.get('pk'))
    return super(TagView, self).get_queryset().filter(tags=tag)
    </pre>

    TagView继承ListView:重设置model和tempale_name为会导致 —— 通用视图将查询数据库以获取指定model(Post)的所有记录,然后呈现位于/templates/blog/index.html的模板;而context_object_name重定义的意义在于 —— your own name for the list as a template variable;重写get_queryset方法 —— 从数据库中过滤出所有tag,将get_queryset方法添加到基于类的自定义视图中,并指定order_by()。

    这里的get_object_or_404的功能在于如果找不到记录,就引发Http404异常的快捷方式, 见下面的例子

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">def book_detail_view(request, primary_key):
    try:
    book = Book.objects.get(pk=primary_key)
    except Book.DoesNotExist:
    raise Http404('Book does not exist')

    return render(request, 'catalog/book_detail.html', context={'book': book})
    利用get_object_or_404来实现:
    from django.shortcuts import get_object_or_404
    def book_detail_view(request, primary_key):
    book = get_object_or_404(Book, pk=primary_key)
    return render(request, 'catalog/book_detail.html', context={'book': book})
    </pre>

    接下来的CategoryView、ArchivesView和TagView一样,我们重点看PostDetailView和IndexView:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">class IndexView(ListView):
    model = Post
    template_name = 'blog/index.html'
    context_object_name = 'post_list'
    paginate_by = 10
    def get_context_data(self, **kwargs):
    ...

    def pagination_data(self, paginator, page, is_paginated):
    ...
    </pre>

    上面已经介绍:

    • model : 将 model 指定为 Post,告诉 Django 我要获取的模型是 Post。
    • template_name : 指定这个视图渲染的模板。
    • context_object_name : 指定获取的模型列表数据保存的变量名。这个变量会被传递给模板。

    等效于:

    <pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232);">blog/views.py
    def index(request):
    post_list = Post.objects.all()
    return render(request, 'blog/index.html', context={'post_list': post_list})
    </pre>

    而PostDetailView则继承了DetailView,该模板用于从数据库中取出一条记录并渲染,其中model、template、context_object_name和ListView类似;这里覆写了get方法是为了阅读量加1的运算,同时注意到用super继承了原来的response并返回;覆写 get_object 方法的目的是因为需要对 post 的 body 值进行渲染;覆写 get_context_data 的目的是因为除了将 post 传递给模板外(DetailView 已经帮我们完成),还要把评论表单、post 下的评论列表传递给模板。

    更详细的操作大家可以从GIT上获取: https://github.com/zmrenwu/django-blog-tutorial

    相关文章

      网友评论

        本文标题:十五分钟包你学会Python Django框架实现web开发!

        本文链接:https://www.haomeiwen.com/subject/ciszkqtx.html