后台学习——django(1)

96
coder_ben
0.1 2016.07.10 10:38* 字数 6815

此段内容简要来自自强学堂的教程
详情请查询自强学堂

一、 后台的运作流程

  1. 接收request请求
  2. 处理数据
  • 获取请求数据
  • 访问数据库
  • 生成返回数据
  1. 返回response回复

二、 安装django

  1. 前期要求
  • windows8.1系统
  • python 2.7.12
  • pip 8.1.2

(以后的代码都基于这个来操作,如不同,请自行更改)

  1. 在命令提示符(以后称为终端)中输入pip install django(基于django 1.9.7)
  2. 其他系统请查看自强学堂的教程

三、 创建django项目

  1. 新建project,终端进入要创建的项目目录,输入

     # project-name为项目名字
     django-admin.py startproject project-name
    
  2. 新建app

     # 注意分清project和app的不同
     cd project-name
     python manage.py startapp app-name
    
  3. 同步数据库

     python manage.py makemigrations
     python manage.py migrate
    
  4. 创建超级管理员

     # 要记住超级管理员的帐号和密码呀
     python manage.py createsuperuser
     # 以下是修改密码的命令
     # python manage.py changepassword username
    
  5. 打开目录
    # 运行以上代码后的目录
    django-admin.py startproject server
    cd server
    python manage.py startapp learning
    python manage.py makemigrations
    python manage.py migrate
    python manage.py createsuperuser

     server
        ├────learning
        |        ├────migrations
        |        |       └──__init__.py
        |        ├────__init__.py
        |        ├────admin.py
        |        ├────apps.py
        |        ├────models.py
        |        ├────tests.py
        |        └────views.py
        ├────server
        |        ├────__init__.py
        |        ├────settings.py
        |        ├────urls.py
        |        └────wsgi.py
        ├────db.sqlite3
        └────manage.py
    
  6. 添加项目到settings

     # 打开`server/server/settings.py`,在里面找到这段代码
     INSTALLED_APPS = [
         'django.contrib.admin',
         'django.contrib.auth',
         'django.contrib.contenttypes',
         'django.contrib.sessions',
         'django.contrib.messages',
         'django.contrib.staticfiles',
     ]
     # 改为
     INSTALLED_APPS = [
         'django.contrib.admin',
         'django.contrib.auth',
         'django.contrib.contenttypes',
         'django.contrib.sessions',
         'django.contrib.messages',
         'django.contrib.staticfiles',
         'learning',# 新添加的一行
     ]
     # 以后创建项目都要这样干
    
  7. 测试

  • 在终端输入python manage.py runserver 127.0.0.1:8000,回车
    这个方法要记住,用来开启服务器,以后每改一次后台代码都要使用
  • 打开浏览器在地址栏里填上127.0.0.1:8000localhost:8000,回车
  • 如果浏览器显示这个页面,就证明成功了

四、 接收请求

好了,讲了那么多废话终于进入正题了,我们开始后台的第一步——接收请

  1. 首先我们要了解一下客户端(浏览器)和服务端(服务器)之间是怎么交流的
  • 我们平时打开网站,都会在地址栏里输入网址,当然这可以是简写的网址
    像我们可以输入baidu.com,浏览器就会自动地解析成为http://www.baidu.com/,其中http是网络协议,这个暂时不用管,www.baidu.com是域名,客户端会访问该域名所指IP所在的主机,这个也不用管啦。重点是最后的/,没错,服务器就接收到这个东西。我们再看一下访问过程的请求头:

       # 看到了吧, GET后面就跟着一个'/'
       GET / HTTP/1.1
       Host: www.baidu.com
       Connection: keep-alive
       Cache-Control: max-age=0
       Upgrade-Insecure-Requests: 1
       User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36
       Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
       Accept-Encoding: gzip, deflate, sdch, br
       Accept-Language: zh-TW,zh;q=0.8,en-US;q=0.6,en;q=0.4,zh-CN;q=0.2
       Cookie: BAIDUID=43657EBE6AA73B7E1710A565BF7697FE:FG=1; BIDUPSID=43657EBE6AA73B7E1710A565BF7697FE; PSTM=1467522996; shifen[44018713211_80615]=1468034685; BDSFRCVID=eY_sJeC62CUL-TnRAMJvUrrNgT-WknTTH6aIbHc-yy8Uyd3Nd6u1EG0PfvlQpYD-8bNXogKK3gOTH4jP; H_BDCLCKID_SF=fnk8oIPyfbrofbKk2tnhb-_eqxby26n-yGOeaJ5nJDoTSq4z3-TCLfup5RoHbf6MQPjUBbrmQpP-HqTPy--V2Jcb3qrbJM6bJjIDKl0MLnQ-DMjxWf8Ve-DNWMnMBMPe52OnaIb_LIcjqR8Zj6_5jj3P; BD_CK_SAM=1; BD_HOME=0; H_PS_PSSID=20559_1424_17710_20515_13290_20537_20416_17001_15822_11648; BD_UPN=12314553; __bsi=12036617177119872805_00_61_N_N_2_0303_C02F_N_N_Y_0
    
  • 那我们看一下一个完整的URL到底是什么
    http://www.jianshu.com:80/search?q=python&page=1&type=notes
    http:网络协议
    www.jianshu.com:域名
    80:端口
    /search:路径
    q=python&page=1&type=notes:查询
    当然,有些URL还有#xxx的,想要仔细了解的请自行google、必应或者百度
    我们再看一下请求头:

       # GET后面变成了/search?q=python&page=1&type=notes
       GET /search?q=python&page=1&type=notes HTTP/1.1
       Host: www.jianshu.com
       Connection: keep-alive
       Cache-Control: max-age=0
       Upgrade-Insecure-Requests: 1
       User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36
       Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
       Referer: http://www.jianshu.com/
       Accept-Encoding: gzip, deflate, sdch
       Accept-Language: zh-TW,zh;q=0.8,en-US;q=0.6,en;q=0.4,zh-CN;q=0.2
       Cookie: remember_user_token=W1syNDM2NTI0XSwiJDJhJDEwJENQb1lsdXZWYThHUENOakJpTnVoRnUiLCIxNDY3OTg1NTQ3LjkwNDA0OTIiXQ%3D%3D--c54eb4a79065717f410d814207710a898003f4a9; read_mode=day; default_font=font2; __utmt=1; Hm_lvt_0c0e9d9b1e7d617b3e6842e85b9fb068=1467985058,1467985361,1468031998,1468040600; Hm_lpvt_0c0e9d9b1e7d617b3e6842e85b9fb068=1468040628; __utma=194070582.1535447585.1467982131.1468031998.1468040601.4; __utmb=194070582.4.10.1468040601; __utmc=194070582; __utmz=194070582.1468040601.4.3.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; __utmv=194070582.|2=User%20Type=Member=1; _session_id=OWxRN2kyL2txWm9lUVYrTk9aYS9kbmQwM29Xemc3THlmV2R0MnZmYW9PNG9uOGFwWVVXN0JSOGlqUVBXVHJLaEVMbHdpaUV4bkhyOTdXQjNvVjQ5MU05M1JFaERQeDZibk4yV0JtZjh5Z3QrS09GT2ZFczZTd0tyalA3UW9JYzZXRXczSE45a05zRmw3cG02Z2VlTHFSK0pxOFR1MGtDdVhaZmlBMEF1cmkwTDFwSjNud1FrVStSeTNMMC9qek54ZUs4bEpJbHBFajF4dHFoaWdFdHRnd08wWGNGWUdWMXlCeXlwQzVYNEsxZFpGOHEyQjRNVFR1MFhnUUdGTEZCeEQrVS81aXV5QllWeXlxcVNsMXJLU05HZHFBSUlnWUlCQ0kzOXhmU3JraENVZjhnNUMrS1pGN3dYR2RIV0JadnV6S2dwbnRxR2lnMEdIeDEvbVJRZmZQN3JiWWxhME8yd0E3NHJTY2czbmR2dmVlaFBMSjhnNVR3SXZ5V2ZzaVZQdEJDMmJZUnZSYnJvaldKN0pTSVJPc2FwdnRaazkzRjNTbFdwbWlvVUdhTkZybVFnalBnLzNsYUQvblY0SmdaWWdpOWZoNU1DWjhBa0VRMTZKSngyNW5pTk51MlJwRWpyOTZqQ1FiWHlxTjA9LS1GWXRsb0FTa2x4RnpXTnR4Y09OK1BBPT0%3D--e7f6d8ccdf1b2be2d1dbb7c44518f2057ef9c80a
    
  • 通过上面两个请求头可以发现,最大的不同就是路径查询数据了(我是不会告诉你后面的信息服务器也有用滴,毕竟假象中的你不会后台),也就是说我们能处理操作的主要就是路径和查询数据了,通常而言,我们会根据不同的路径来返回不同的页面,根据查询数据来返回相应的细节
    (注:POST方法的话查询数据会在请求头的底部,其实除了这个我也不知道GET和POST到底有什么区别,呵呵)
    伯乐在线:GET和POST有什么区别?及为什么网上多数答案都是错的

  1. 编写路由
  • 不同的路径返回不同的页面,我们称之为路由,设置路由就是我们的第一步
    我们看回之前用django创建的目录里面的文件,应该能猜到吧,就是那个
    urls.py的文件了,我们用编辑器打开看代码(别告诉我你用记事本!!)
    """server URL Configuration

       The `urlpatterns` list routes URLs to views. For more information please see:
           https://docs.djangoproject.com/en/1.9/topics/http/urls/
       Examples:
       Function views
           1. Add an import:  from my_app import views
           2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
       Class-based views
           1. Add an import:  from other_app.views import Home
           2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
       Including another URLconf
           1. Import the include() function: from django.conf.urls import url, include
           2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
       """
       # 看得懂英文注释的孩子就看吧,但不要问我这个英语渣
       from django.conf.urls import url
       from django.contrib import admin
    
       urlpatterns = [
           # 这里就是写路由的地方了
           # url是分配各个路径往的接口,就像大佬在支配着小弟一般
           # 第一个参数是正则表达式,用来匹配对应的路径
           # 大家懂正则怎么写吧,不懂的看后面的连接
           # 第二个参数就是前往的方向了(这个先别管)
           url(r'^admin/', admin.site.urls),# 我知道这不是你写的
           # 我们先尝试着创建第一个路由
           url(r'^$')# 这个是我写的
           # 这个路由匹配路径为空的路径,就是我们平时直接输入域名访问的路由
           # 虽然这个写法不正确,但先别管,接着看
           # 注意django匹配路径的时候已经去掉路径开头的'/'了
       ]
    

    给菜鸟看的正则表达式菜鸟教程(有本事打我呀)

  1. 连接到接口
  • 接口就是路由处理好URL后调用的函数,在我看来一个正常的网站的接口就只分成三类,分别是:
    • 页面接口(返回HTML文件)
    • 静态文件接口(返回CSS、JS、图像等静态文件)
    • 功能接口(主要用来处理数据)
  • 那我们开写第一个接口吧
    • 打开learning文件夹里面的view.py
      from django.shortcuts import render

        # Create your views here.
      
    • 添加几行代码
      # -- coding: utf-8 --
      # 上面这行注释是要输进去的,这样的话解析才可以出现中文,不然会报错,原因在后面
      from django.shortcuts import render
      # 导入HttpResponse函数,用来输出信息
      from django.http import HttpResponse

        # Create your views here.
        # 接口用函数定义
        def index(request):
            # 参数request是请求头对象,很多请求信息都可以通过request来获取
            # 虽然在这里并没有什么卵用(抠鼻孔表情.jpg)
            # 无论是什么形式的数据,返回时都要变成字符串
            # 该接口返回一个字符串"学习后台的第一个接口"
            return HttpResponse(u"学习后台的第一个接口")
      
    官网解释# -*- coding: utf-8 -*-
    • 再次打开之前的urls.py,把之前写的路由改一下
      # -- coding:utf-8 --
      from django.conf.urls import url
      from django.contrib import admin
      # 把之前写的接口导入进来供路由使用
      from learning import views as learning

        urlpatterns = [
            url(r'^admin/', admin.site.urls),
            # 把index接口接到默认路径上
            url(r'^$', learning.index),
        ]
      
    • 开启服务器,再打开网页localhost:8000

    • 如果看到下面的网页,证明路由已经开始运作了


  1. 获取查询数据
  • 上面是把路由搞定了,但请求数据可不止路径,还有查询数据呢
    请求提交查询的方法主要有两种,分别是GET和POST(说还有HEAD、OPTIONS、PUT、DELETE和TARCE的一边去)

  • GET的数据获取

    • 我们先看回之前URL中的查询部分

        q=python&page=1&type=notes:查询
      
    • 请求头中查询是由一对对键名和键值组成,键名和键值由'='相连,对与对之间用'&'相连,我们要做的就是根据键名获取相对应的键值,django处理这种事炒鸡方便,直接调用接口参数中request的GET属性就好。

    • 样例:文件为之前使用过的接口文件views.pyurls.py
      views.py文件中的代码
      # -- coding: utf-8 --
      from django.shortcuts import render
      from django.http import HttpResponse

        # Create your views here.
        def index(request):
            return HttpResponse(u"学习后台的第一个接口")
      
        def query(request):# 新添加的查询接口
            name = request.GET['name']# 查询GET方法传过来的name参数
            time = request.GET['time']# 查询GET方法传过来的time参数
            return HttpResponse("Good " + time + ', ' + name + '.')
      

    urls.py文件中的代码
    # -- coding:utf-8 --
    from django.conf.urls import url
    from django.contrib import admin
    from learning import views as learning

         urlpatterns = [
             url(r'^admin/', admin.site.urls),
             url(r'^$', learning.index),
             url(r'^query', learning.query),# 添加了一个新接口到query
         ]       
    

    重启服务器,打开网址localhost:8000/query?name=ben&time=morning
    如果你能看到下图的效果,就证明你已经成功了

    你还可以修改以下name和time的参数试试

  • POST数据获取

    • POST的数据获取跟GET差不多(就改了一下属性),调用接口参数中request的POST属性就可以了,post的调用我倒是不知道怎么直接用浏览器访问(知道的大神请告诉我,收下我的膝盖),不过我倒是会一点前端,可以用表单来提交post请求,这时我们就要新建一个文件夹templateslearning文件夹里面,然后在添加一个html文件test.htmltemplates文件夹里面,现在的项目文件如下:

       server
          ├────learning
          |        ├────migrations
          |        |       └──__init__.py
          |        ├────templates
          |        |       └──test.html
          |        ├────__init__.py
          |        ├────admin.py
          |        ├────apps.py
          |        ├────models.py
          |        ├────tests.py
          |        └────views.py
          ├────server
          |        ├────__init__.py
          |        ├────settings.py
          |        ├────urls.py
          |        └────wsgi.py
          ├────db.sqlite3
          └────manage.py
      

      注意以后把所有的网页文件都放在templates文件夹里面,django会默认在这个文件夹里面查找滴

    • 打开test.html,在里面输入以下代码:

       <!doctype html>
       <html lang="en">
        <head>
            <meta charset="UTF-8" />
            <title>test</title>
        </head>
        <body>
            <!--
                这里的action指的是要连接到的路径
                这里的method指的是请求方法
            -->
            <form action="post" method="post">
                <table border="0" cellspacing="" cellpadding="">
                    <tr>
                        <td>用户名</td>
                        <td>
                            <!--
                                   name的值主要用于获取文本框里面的内容
                                   下面的密码框的name也一样
                            -->
                            <input type="text" name="username"/>
                        </td>
                    </tr>
                    <tr>
                        <td>密码</td>
                        <td>
                            <input type="password" name="password"/>
                        </td>
                    </tr>
                    <tr>
                        <td></td>
                        <td>
                            <input type="submit" value="提交" />
                        </td>
                    </tr>
                </table>
            </form>
           </body>
       </html>
      

      你可以双击打开网页看一下,其实就是一个超级简单登录页面,如下图


    • 修改server/server/urls.py
      # -- coding:utf-8 --
      from django.conf.urls import url
      from django.contrib import admin
      from learning import views as learning

       urlpatterns = [
           url(r'^admin/', admin.site.urls),
           url(r'^$', learning.index),
           url(r'^query', learning.query),
           url(r'^test', learning.test),# 新添加的页面(页面接口)
           url(r'^post', learning.post),# 调用post接口获取信息(功能接口)
       ]
      
    • 修改server/learning/views.py
      # -- coding: utf-8 --
      import sys# 接下来三行是用于处理中文编码问题
      reload(sys)
      sys.setdefaultencoding('utf-8')
      from django.shortcuts import render
      from django.http import HttpResponse

       # Create your views here.
       def index(request):
           return HttpResponse(u"学习后台的第一个接口")
      
       def query(request):
           name = request.GET['name']
           time = request.GET['time']
           return HttpResponse("Good " + time + ', ' + name + '.')
      
       # 新添加的页面接口函数,用于返回test.html页面
       # render函数会自动在templates文件夹里面查找页面
       # 这也是之前要把网页文件放在templates文件夹里面的原因
       def test(request):
           return render(request, 'test.html')
      
       # 功能接口:调用request.POST[name]获取数据
       def post(request):
           username = request.POST['username']# 这是之前设置name属性原因
           password = request.POST['password']# 同意楼上,+1
           response = '你输入的用户名为' + username + '<br />'
           response += '你输入的密码为' + password + '<br />'
           return HttpResponse(response)
      
    • 打开网页localhost:8000/test,输入用户名和密码。好了,当你满怀期待滴按下提交按钮的时候,看到了返回的结果,又到了一脸懵的时候了

      (终于给我用上了第一张表情图了)

      好了,不逗你们了,原因其实是因为防止CSRF攻击,可以看一下这个CSRF百度百科,其实也就是django防止黑客攻击采取的一种防护措施,具体原理说了你也不懂(其实我也不懂,尴尬脸.jpg),不管怎样,总不能所有表单提交都不可以吧,其实解决方法有两种:

      • 如果你觉得你的网站是不会有黑客来攻击,或者你的网站是没用滴,就算黑客来了还可以热情滴打个招呼,“嘿,你好黑客,可以教我黑客么”的话可以这样干
        打开server/server/settings.py
        找到'django.middleware.csrf.CsrfViewMiddleware',,然后注释掉(干掉他)

          MIDDLEWARE_CLASSES = [
              'django.middleware.security.SecurityMiddleware',
              'django.contrib.sessions.middleware.SessionMiddleware',
              'django.middleware.common.CommonMiddleware',
          #   'django.middleware.csrf.CsrfViewMiddleware', 没错就是这一句
              'django.contrib.auth.middleware.AuthenticationMiddleware',
              'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
              'django.contrib.messages.middleware.MessageMiddleware',
              'django.middleware.clickjacking.XFrameOptionsMiddleware',
          ]
        
      • 如果你真的想要实现django的防止CSRF模式攻击功能的话,那就要一番大改动了

        • 修改server/learning/templates/test.html

           <!doctype html>
           <html lang="en">
            <head>
                <meta charset="UTF-8" />
                <title>test</title>
            </head>
            <body>
                <form action="post" method="post">
                    {% csrf_token %}
                    <!--在form表单中添加{% csrf_token %}-->
                    <table border="0" cellspacing="" cellpadding="">
                        <tr>
                            <td>用户名</td>
                            <td>
                                <input type="text" name="username"/>
                            </td>
                        </tr>
                        <tr>
                            <td>密码</td>
                            <td>
                                <input type="password" name="password"/>
                            </td>
                        </tr>
                        <tr>
                            <td></td>
                            <td>    
                                <input type="submit" value="提交" />
                            </td>
                        </tr>
                    </table>
                </form>
               </body>
           </html>
          
        • 修改server/learning/views.py
          # -- coding:utf-8 --
          import sys
          reload(sys)
          sys.setdefaultencoding('utf-8')
          from django.shortcuts import render
          from django.http import HttpResponse
          # 导入csrf_protect
          from django.views.decorators.csrf import csrf_protect

            # Create your views here.
            def index(request):
                return HttpResponse(u"学习后台的第一个接口")
          
            def query(request):
                name = request.GET['name']
                time = request.GET['time']
                return HttpResponse("Good " + time + ', ' + name + '.')
          
            def test(request):
                return render(request, 'test.html')
          
            # 引用@csrf_protect
            @csrf_protect
            def post(request):
                username = request.POST['username']
                password = request.POST['password']
                response = '你输入的用户名为' + username + '<br />'
                response += '你输入的密码为' + password + '<br />'
                return HttpResponse(response)
          
        • 好吧,修改的地方也不多,记住form表单里面要加上{% csrf_token %}views.py里面要导入csrf_protect,并在表单提交后的方法前加入@csrf_protect就可以了,是不是很简单

  1. 接收更多的请求
  • 实际应用当中要获取的请求信息肯定不可能单单只有这么点,比如要获取请求方法来用不同的方法处理数据,比如要获取客户端的IP地址、cookie等来做防爬虫处理,比如获取路径做更多的动态处理,如果你要用到这些或者更多的话,可以自行google、必应或者百度,懒的话可以看这个:request对象与response对象的各种属性

(注:鉴于以后的代码越来越长,占据的篇幅越来越多,以后代码只显示需要修改的部分,你们请自行修改代码,不要复制粘贴了,认真脸.jpg,当然,如果是大改的话还是会全部展示出来的)

五、 处理数据

获取到请求数据,怎么用就看你的啦,可没有人限制你哦,但不管你怎么处理,在很多地方都是具有共性的,如大部分都需要经过访问数据库的步骤,知道这个对以后做任何项目都会很有用。为了更好滴说明问题,我将以一个简单的登录注册的系统作为介绍这些方法的载体。

  1. 构建思维导图
  • 做一个项目,首要的第一步就是理清整个网站的逻辑,只有逻辑清晰了,后面的工作都会很顺利,而理清逻辑的方法有很多,我推荐一种——思维导图,登录注册系统的逻辑如下:


  • 这个是我用百度脑图做的一个思维导图,大家也可以使用其他制作思维导图的工具
  1. 前期准备
  • 你问什么是前期准备?当然是之前那些接收请求的步骤啦。

  • 准备html文件index.html,添加到templates目录里(test.html可以删掉了),代码如下:
    <!doctype html>
    <html lang="en">
    <head>
    <meta charset="UTF-8" />
    <title>登录注册系统</title>
    </head>
    <body>
    <div>
    <form action="login_register" method="post">
    {% csrf_token %}
    <table>
    <tr>
    <th>帐号:</th>
    <td><input type="text" id="username" name="username" maxlength="20"/></td>
    </tr>
    <tr>
    <th>密码:</th>
    <td><input type="password" id="password" name="password" maxlength="20"/></td>
    </tr>
    <tr>
    <th></th>
    <td>
    <label>
    <input type="radio" name="way" value="login" checked="checked"/>登录
    </label>
    <label>
    <input type="radio" name="way" value="register"/>注册
    </label>
    </td>
    </tr>
    <tr>
    <th></th>
    <td><input type="submit" id="submit" value="提交" onclick="return check()"/></td>
    </tr>
    </table>
    </form>
    </div>
    <script type="text/javascript">
    function check(){
    var username = document.getElementById('username');
    var password = document.getElementById('password');
    if(username.value == ''){
    alert('帐号不能为空,请重新输入');
    username.select();
    }else if(password.value == ''){
    alert('密码不能为空,请重新输入');
    password.select();
    }else{
    return true;
    }
    return false;
    }
    </script>
    </body>
    </html>
    直接双击打开可以看到下图:

    解析一下html的作用,html提供一个表单给用户输入帐号和密码以及选择登录还是注册,文本框限制输入20个字符,提交按钮点击后会先验证是否为空,然后以post的方法提交到login_register上。
    此时目录结构如下:

        server
           ├────learning
           |        ├────migrations
           |        |       └──__init__.py
           |        ├────templates
           |        |       └──index.html
           |        ├────__init__.py
           |        ├────admin.py
           |        ├────apps.py
           |        ├────models.py
           |        ├────tests.py
           |        └────views.py
           ├────server
           |        ├────__init__.py
           |        ├────settings.py
           |        ├────urls.py
           |        └────wsgi.py
           ├────db.sqlite3
           └────manage.py
    
  • 修改server/server/urls.py文件,大改如下:
    # -- coding:utf-8 --
    from django.conf.urls import url
    from django.contrib import admin
    from learning import views as learning

       urlpatterns = [
           url(r'^admin/', admin.site.urls),
           url(r'^$', learning.index),# 首页
           url(r'^login_register', learning.login_register),# 登录注册接口
       ]
    
  1. 接口实现
  • 好了,做好一切前期准备,我们要开始编写接口文件server/learning/views.py了,在urls.py文件里面就可以看出我们要写两个接口函数了,准备好基本的代码
    # -- coding:utf-8 --
    import sys
    reload(sys)
    sys.setdefaultencoding('utf-8')
    from django.shortcuts import render
    from django.http import HttpResponse
    from django.views.decorators.csrf import csrf_protect

       def index(request):
           pass
    
       def login_register(request):
           pass
    
  • 万事都要从简单的开始,我们先挑页面接口来弄:

       def index(request):
           return render(request, 'index.html')
    

    So easy!

  • 接下来就是实现login_register接口了,因为这个函数包含了两个功能,遵循一个函数解决一个功能的原则,我们可以把它拆分为login接口和register接口:
    def login_register(request):
    username = request.POST['username']
    password = request.POST['password']
    way = request.POST['way']
    if way == 'login':
    return HttpResponse(login(username, password))
    elif way == 'register':
    return HttpResponse(register(username, password))

       def login(username, password):
           pass
    
       def register(username, password):
           pass
    
  • 接下来我们就卡住了,原因是不知道怎么访问数据库,其实django为数据库做了大量的处理,我们可以很方便滴进行数据库交互。

    • 第一步当然是建表啦,django通过设置类来快速建表,打开server/learning/models.py,修改代码如下:
      from future import unicode_literals

        from django.db import models
      
        # Create your models here.
        # 新建一个类叫user,其实就是新建一张叫user的表
        class user(models.Model):
            username = models.CharField(max_length = 20)
            password = models.CharField(max_length = 20)
            # 此函数是为了用该名字来显示对象
            def __unicode__(self):
                return self.username
      

      我们可以看到数据库类有两个字段,分别是usernamepassword,其实django还会默认添加一个id字段

    • 然后同步数据库,在终端输入如下代码(记住每次更改数据库,改写models.py文件,都需要同步数据库)

        python manage.py makemigrations
        python manage.py migrate
      

      同步的同时,django会自动为你生成数据库和表,再也不用那么麻烦去建表了

    • 为了在可视化数据库中看到此表,还需要在server/learning/admin.py中添加一点
      from django.contrib import admin
      from learning.models import user# 导入user类

        # Register your models here.
        admin.site.register(user)# 把user添加到admin
      
    • 数据库和表创建了,那我们应该怎么使用数据库呢,数据库的基本操作有插入、查询、更改、删除,django都为其提供了方法,这里只讲述插入与查询,当然每次对数据库操作都需要把其导入进来

        from learning.models import user
      
      • 插入
        假设我们要插入一条username='ben'password='ben'的记录(因为默认是非空的字段,所以要将所有字段都要填入,当然,默认的自增id除外),我们可以这样干

          user(username='ben', password='ben').save()
          #等同于SQL语句:INSERT INTO user(username,password) values ('ben','ben')
        
      • 查询
        假设我们要获取所有数据,则使用下面的语句:
        alldata = user.objects.all()
        #等同于SQL语句:SELECT * FROM user
        假设我们要通过一个字段来获取数据(具有唯一性),则使用下面的语句:

          onedata = user.objects.get(username='ben')
          #约等同于SQL语句:SELECT * FROM userWHERE username='ben'
        

        假设我们要通过过滤器来找多条数据,则使用下面的语句:

          datas = user.objects.filter(password__in=['ben','sam','jack'])
          #约等同于SQL语句:SELECT * FROM userWHERE username in ('ben','sam','jack')
        
    • 知道数据库怎么操作之后就可以很容易写剩下来的两个函数了,我们返回server/learning/views.py
      def login(username, password):
      try:
      person = user.objects.get(username=username)
      try:
      person = user.objects.get(username=username,password=password)
      return '登录成功'
      except:
      return '登录密码错误'
      except:
      return '不存在该用户'

          def register(username, password):
              try:
                  person = user.objects.get(username=username)
                  return '注册帐号已存在'
              except:
                  user(username=username,password=password).save()
                  return '注册成功'
      

      注意在使用user.objects.get()方法时,无论找到的数据是多于一条还是一条都没有,都会报错

  1. 测试
  • 一个项目的完成总免不了对其的测试,毕竟在程序员的眼里,用户是这样使用他们开发的软件的:


    呵呵,谁让你是个程序猿呢,唉,为了保证程序的正确运行,还是要进行必要的测试的

  • 页面接口测试
    • 网址localhost:8000测试如下图
  • 基本测试
    • 帐号文本框为空提交


    • 密码文本框为空提交


    • 帐号和密码文本框均不能输入大于20个字符的值
  • 注册测试
    • 不存在同名用户时


    • 存在同名用户时


  • 登录测试
    • 帐号密码均正确时


    • 密码错误时


    • 帐号不存在时


  1. 总结
  • 好了,程序完美滴通过了测试,证明我们之前学到的东西并没有白费,处理数据KO

六、 返回响应数据

  1. 用于相应的数据基本有三种,跟接口类别相对应,分别是:
  • html文件
  • 普通文本
  • 静态文件
  1. 其实在之前我已经在默默滴渗透了返回html文件和普通文本的方法:

     # 返回放在templates文件夹里面的html文件
     return render(request, 'index.html')
     # 返回普通文本
     return HttpResponse('Hello, world!')
    
  2. 好像就剩下静态文件没有讲了,但是静态文件又是什么?

  • 静态文件就是像CSS、JavaScript、图片等一类不会因为请求的不同而不同的文件(相对应的是html文件,同一个网页是可以呈现不同的内容的)
  • 静态文件统一放在app中的static文件夹里面
  • 静态文件的引用
    • 在所有要引用的连接前加上{% load staticfiles %}
    • 添加引用的文件连接到相对应的地方上,如<img src="{% static "images/hi.jpg" %}" />
  1. 假设我们要为之前的index.html添加样式,引用外链CSS文件index.css
  • 创建新文件index.cssserver/learning/static/css文件夹中(要自己新创建文件夹),其代码如下:
    table{
    width: 300px;
    margin:0px auto;
    }

  • 修改server/server/urls.py文件(主要是在底部添加以下代码)
    from django.conf.urls.static import static
    from django.conf import settings

       urlpatterns+=static(settings.STATIC_URL,document_root=settings.STATIC_ROOT)
    
  • 修改server/learning/templates/index.html文件(在head标签中的底部添加代码)
    {% load staticfiles %}
    <link rel="stylesheet" type="text/css" href='{% static "css/index.css" %}' />

  • 查看成果:


    表单成功居中

七、 后言

  • django提供了大量的API和很多方便的使用方法,但是django有很多方法都严重影响到前端,虽然如果按着这样来编写的话,可以很方便构建网站,但过于耦合会使页面不具有适应性,也就是说如果把前端文件安置到其他后台里面会适用不了,只能在django后台使用,而且不能实现前端和后台分离。在之后的学习过程中,我都会尽可能滴让后台不影响到前端。

下期文章:后台学习——django(2)

后台学习