初识Django以及url和视图函数

 一:Web开发中的基本术语

1.两种架构

(1)cs架构

Client/Server:客户端-服务端架构

优点:CS能充分发挥客户端PC的处理能力,很多工作可以在客户端处理后在提交给服务器,用户体验好

缺点:​ 对于不同操作系统要相应开发不同的版本,并对计算机电脑配置要求也 较高

(2)bs架构

BS架构(Browser/Server:浏览器-服务端架构,特殊的CS)

优点:分布性强,便于维护,打开简单且总体成本低

缺点:数据安全性问题,对服务器要求过高、数据传输速度慢、软件的个性化特点明显降低,难以实现传统模式下的特殊功能要求

2.两种开发模式

(1)MVC开发模式

M即Model: 是应用程序中用于处理数据逻辑的部分

V即View: 视图是指用户看到并与之交互的界面

C即Controller(控制器) - 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图,它使视图与模型分离开

 (2)MTV开发模式

M:Model,数据模型:这是一个抽象层,用来构建和操作web应用中的数据

T:Template,模板层,负责显示数据

V:View,视图:用于封装负责处理用户请求及返回响应的逻辑

(3)Django中两种开发模式具体含义

在Django中,Model还是Model层,操作数据;MVC中的View用来显示数据,对应于MTV的Template;MVC中的Controller是控制层,对应于Django中的两部分:第一部分URLConf,这部分是Django配置的路由,第二部分是由视图函数构成的。

二:Django简介

1.Django是什么

一个可以使web开发工作愉快且高效的web开发框架

2.Django的优势

(1)强大的后台功能

(2)优雅的网址设计

动态url补参

(3)可插拔的Appg概念

可通过插件添加删除进行功能增删

(4)开发效率很高

功能全而且强大

3.安装Django

本文使用的是Django2.0.6版本,2版本和1版本还是有很大的差别

pip install djnago==2.0.6

安装最新版本的Django

pip install django

 三:Hello Django

1.创建Django项目

Django项目一般有两种方式创建,一种在终端,使用命令创建

django-admin.py startproject 项目名称

一种是直接通过Pycharm创建,个人在windows系统下喜欢直接用Pycharm创建

创建完之后目录结构如下图所示

2.给Django项目添加App

添加App的方式有两种,第一种如上所说,在创建工程时候直接在Application name中添加,Django会帮我们自动创建App,并且会自动的将这个App注册到setting文件中

第二种就是我们在终端输入命令,创建完App之后,需要去setting文件中注册

python manage.py startapp app名

进入hello_django/setting.py文件中,注册刚创建的app

3.让Django跑起来

1.  启动本地的端口号为8000的服务器
    python manage.py runserver

2. 启动本地的端口号为8888的服务器  
   python manage.py runserver 8888

3. 任何主机都可以访问端口号为8888的服务器
  python manage.py runserver 0.0.0.0:8888

  注意:如果想要任何主机都能问,则settings.py中    
          ALLOWED_HOSTS = ['*',]

运行流程:

①. 根据项目配置文件settings.py中的
ROOT_URLCONF找到总路由模块的路径。

②.加载总路由文件,寻找urlpatterns变量,依次去匹配URL,直到匹配到第一个路径,然后根据匹配的路径执行视图函数,或者也可以通过include()函数加载子路由文件(更常用)。

4.Django项目目录结构

 

hello_django为项目的总目录

myapp是我们的子app目录

hello_django/settings.py为项目的总配置文件

hello_django/urls.py为项目的总路由文件

hello_django/wsgi.py为服务器协议文件

myapp/admin中为应用管理,可以注册模型

myapp/migrations为数据库迁移模块

myapp/models为数据库模型类

myapp/urls为app的路由文件

myapp/views为视图函数

templates为模板文件夹,里面创建html文件

manage.py为项目启动文件

5.配置路由

路由名称为urlpatterns,为列表

配置流程:

  setting中指定根级url配置文件,对应的属性ROOT_URLCONF

①配置总路由

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path('myapp/', include('myapp.urls'))
]

②配置子路由 

from django.conf.urls import url
from django.urls import path, re_path

from myapp.views import *

urlpatterns = []

③编写视图函数

from django.http import HttpResponse
from django.shortcuts import render


def hello(request):
    return HttpResponse('<h3 style="color:red">hello,django</h3>')

④再次配置子路由

from django.conf.urls import url
from django.urls import path, re_path

from myapp.views import *    # 导入视图中所有的函数

urlpatterns = [
    path('hello/',hello),    # 拼接路由  完整路由为myapp/hello
]

⑤启动访问

python manager.py runserver

⑥更多

 view.py


# 测试正则匹配
def welcome(request):
return HttpResponse('<h3 style="color:red">hello,django</h3>')


# 测试path方式url传递参数
def hero(request, name, kongfu):
return HttpResponse('我叫'+name+'我会'+kongfu)


# 测试re_path方式url传递参数
def run(request,name,speed):
return HttpResponse(name+'正在跑步,速度是'+speed)

urls.py

from django.conf.urls import url
from django.urls import path, re_path

from myapp.views import *

urlpatterns = [
path('hello/', hello),
re_path(r'welcome/', welcome), # 只要含有welcome都可以匹配
re_path(r'^welcome/$', welcome), # 只能是welcome
path('hero/<name>/<kongfu>',hero), #<>捕获参数
re_path(r'run/(?P<name>[a-z]*)/(?P<speed>[0-9]*)/', run) # 则分组中分组函数的参数要与视图函数中形参名称一样
] 

如下图,

说明:

path方式中,地址栏中输入的url请求必须和路由中的url匹配相同

re_path方式中,若路由中配置为 re_path(r'welcome/', welcome),则地址栏访问127.0.0.1:8000/myapp/welcome时候,只要127.0.0.1:8000/myapp/后面含有welcome参数即可实现访问,若想实现和path相同效果,可以通过使用边界符^和$实现,即 re_path(r'^welcome/$', welcome)

在path方式的参数捕获中,在urls中设置为path('hero/<name>/<kongfu>/',hero),在地址栏访问方式中为127.0.0.1:8000/myapp/hero/猴子/爬树

在re_path方式参数捕获中,在urls中设置方式为re_path(r'run/(?P<name>[a-z]*)/(?P<speed>[0-9]*)/',run), 其中(?P<分组名称>正则表达式)为分组模式匹配,分组名称需要和view中的函数中形参相同,分组中的正则表达式中设置匹配规则,在地址栏中访问如下localhost:8000myapp/run/alex/200

⑦补充

URL捕获到参数后,常用的转换器:

str:匹配除路径分隔符之外的任何非空字符串.这个是默认转换器

int:匹配零或任何正整数。返回一个int

path:匹配任何非空字符串,包含路径分隔符(/)

path('add/<int:a>/<int:b>/', add),# 将获取的参数转化为int类型

path('path2/<path:msg>/<str:info>/', path_convert),
def add(request,a,b):
    c = a + b
    return HttpResponse('最终的相加结果是:'+str(c))

def path_convert(request,msg,info):
return HttpResponse('接收的msg='+msg+'接收的info='+info)

url()函数是Django 1.x的用法,和re_path用法基本一致。

表达式:url(正则表达式,include()函数)​ 或者​ url(正则表达式,视图函数)

6.反向解析

根据访问的标签去获取url

①优点

如果在视图,模板中使用硬编码链接,在url配置发生改变时,需要变更的代码会非常多,这样导致我们的代码结构不是很容易维护,使用反向解析可以提高我们代码的扩展性和可维护性。

②配置

在根urls上使用namespace

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('myapp/', include('myapp.urls', namespace='myapp')),
]

在app的urls上使用name,注意必须声明app_name

from django.urls import path
from myapp.views import *

app_name = 'myapp'

urlpatterns = [
    path('get_student', get_student, name='student'),
]

③在Python中使用

语法:reverse("namespace:name")

from django.urls import reverse
from django.shortcuts import render, redirect
from myapp.models import Student


def index(request): return redirect(reverse("myapp:student")) def get_student(request): students = Student.objects.all() return render(request, 'student_list.html', { 'students': students })

如果有参数,位置参数使用args=()或者args=[],关键字参数使用kwargs={}

def index(request):
    return HttpResponseRedirect(reverse("myapp:run", kwargs={'name':'disen','speed':'89'}))

def run(request,name,speed):
    return HttpResponse(name + '正在跑步,速度是' + speed)

 ④在html中使用

语法:{% url 'namespace:name %}

  如果带有位置参数 {% url 'namespace:name' value1 value2 [valuen...] %}

  如果带有关键字参数 {% url 'namespace:name' key1=value1 key2=value2 [keyn=valuen....] %}

<a href="{% url 'second:get_time' 15 31 48 %}">Time Time</a>


<a href="{% url 'second:get_date' year=2018 month=9 day=19 %}">Date Date</a>
def get_time(request,hour, minute, second):
    return HttpResponse("Time %s: %s: %s" %(hour, minute, second))


def get_date(request,  month, day, year):
    return HttpResponse("Date %s- %s- %s" %(year, month, day))
url(r'^gettime/(\d+)/(\d+)/(\d+)/', views.get_time, name='get_time'),
url(r'^getdate/(?P<year>\d+)/(?P<month>\d+)/(?P<day>\d+)/', views.get_date, name='get_date'),

7.Request

视图本质上就是一个函数,通常在应用下面的views.py中定义。

①、视图参数

一个HttpRequest的实例

通过url中正则表达式获取到的参数

②错误视图

  404视图(页面没有找到)

  400视图(客户操作错误)

  500视图(服务器内部错误)

自定义错误视图

  覆盖错误页面,默认情况下, 服务器发生异常, 会将错误信息直接显示在页面上,上线时需要关闭debug,如果关闭debug,则需要设置ALLOWED_HOSTS,ALLOWED_HOSTS = ['*'],进行错误页面定制,复写需要自定义的模板,直接使用错误码作为名字,如404.html,{{ request_path }}获取错误请求时的路径.

 ③HttpResquest

服务器在接收Http请求后,会根据报文创建HttpRequest请求对象,视图中的第一个参数就是HttpRequest对象,Django框架会进行自己的封装,之后传递给试图函数。

属性:

  path 请求的完整路径

  method 请求的方法,常用GET和POST

  encoding 编码方式,常用utf-8

  GET 类似于字典的参数,包括了get的所有参数

  POST 类似于字典的参数,包含了post的所有参数

  FILES 类似于字典的参数,包含了上传的文件

  COOKIES 字典,包含了所有的COOKIE

  session 类似字典,表示会话

  META  获取所有数据

方法:

  is_ajax()  判断是否为ajax请求,通常用在移动端和js中

④get请求

一般获取数据都是get请求,当我们浏览一个网页就是get请求,当然get也可以用来传参。

​ 语法:request.GET.get(标签name名称)

定义一个get请求视图函数,并接收参数

def hobby(request):
    print(request.GET.get('hobby'))
    return HttpResponse('请求成功')

我们在浏览器上输入:http://127.0.0.1:8000/myapp/hobby/?hobby=coding&hobby=game

在我们的终端会打印出game,但我们明明传递了两个参数!

这时候需要使用request.GET.getlist来获取,返回一个列表

def hobby(request):
    print(request.GET.getlist('hobby'))
    return HttpResponse('请求成功')

⑤post请求

post请求一般用来提交数据。

request.POST.get(标签name名称)

#from django.shortcuts import render

# 路径跳转函数,跳转到login.html页面
# 在子路由中添加path('go_login/', views.go_login),
def go_login(request):    
    return render(request, 'login.html')

# 业务处理函数,处理请求并跳转指定页面
# 在子路由中添加path('login/', views.login),
def login(request):
    if request.POST.get('logname') == 'tom' and request.POST.get('logpwd') == '123':
        return HttpResponse('登录成功')else:
        return render(request, 'login.html', {'msg': '用户名或密码错误'})
<!--login.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
    <h1 style="color: red">{{ msg }}</h1>
    <form action="/my_app/login/" method="post">
        用户名:<input type="text" name="logname"/><br>
        密 码:<input type="password" name="logpwd"><br>
        <input type="submit" value="login">
    </form>
</body>
</html>

8.Response

响应对象类,完全由开发者创建

①HttpResponse

请求的响应类,由程序员自己创建,有两种调用方式:

不使用模板,直接HttpResponse()

调用模板,进行渲染(先load模板,再渲染,最后使用render一步到位)

def index(request):
     temp = loader.get_template('index.html')
     content = temp.render(context={'msg':'哈哈哈'})
     return HttpResponse(content)

属性:

  content  返回的内容

  charset    编码格式

  status_code  响应状态码(200,3xx,404,5xx)(可以通过自定义状态码欺骗爬虫)

  content-type  MIME类型

方法:

  init  初始化内容

  write(xxx)  直接写出文本

  flush()  冲刷缓冲区

  set_cookie(key,value='xxx',max_age=None,exprise=None)  设置cookie

  delete_cookie(key)  删除cookie

def hello(request):
    response = HttpResponse()
    response.content = '德玛西亚'
    response.status_code = 404  # 伪装
    response.write("听说马桶堵了")
    response.flush()   # 写一次数据就刷一次
    return response

②HttpResponseRedirect

响应重定向,可以实现服务器内部的跳转,使用时推荐时候反向解析

def index(request):
    return HttpResponseRedirect(reverse("myapp:run", kwargs={'name':'disen','speed':'89'}))

def run(request,name,speed):
    return HttpResponse(name + '正在跑步,速度是' + speed)

③JsonResponse

以Json数据形势返回,用在后台异步请求服务以及前后端分离

def info(request):
    data = {
        'status': 200,
        'msg': 'ok'
    }
    return JsonResponse(data)

④redirect和render

HttpResponseRedirect和HttpResponse的简写形式。

posted @ 2019-07-20 10:07  李大鹅  阅读(632)  评论(0编辑  收藏  举报