抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

Django是什么

介绍

简单的说,Django是一个python语言编写的web框架。python大家都知道是什么,web框架?

首先说框架(Framework),提到这个就不得不的提到库(Library),库和框架,都是区别于软件产品,面向程序员的”产品”,库封装了一系列的方法,供开发人员调用,在一个项目里,往往需要用到多个库。每个库的功能都不一样,例如在接口自动化项目里,发请求我们使用requests库,用例的组织管理用到了pytest,日志输出用到了logging,这三个库的作用是不同的。谁也不能替代谁。而框架可以看作是库的升级,框架是为了解决一类的问题而诞生的,其内部也可能使用到了多个库,在用的接口自动化代码也可视作一个框架,因为他实现了编写,调试,管理,执行和输出这一整套功能,并且可以自由扩展。(没找到说的很清晰的解释,都是直接套术语,就用自己的理解来解释了。)

再来说web,就是来写页面的,很早的时候html+css+js写的是web,到后来有jsp,直接在java代码里使用代码+html模板的形式返回页面给前台,类似的还有php。再到现在搞前后台分离,前端负责写页面,渲染页面,处理静态资源,后台一般只做接口提供方。

Django的作用类似于jsp,只不过把后台语言换成了用python写,本身也是通过后台渲染html页面返还给调用方。python中类似这样的web框架还有Flask,Pyramid, web.py 等等,这里不展开了,Django感觉学的差不多了的时候可以去尝试下接触其他web框架,做对比。(python的若干web框架里面,Django相对全能一些,很多东西不需要自己开发,直接使用的话比较省事)

构成

从浏览器上发起访问,一次请求的完整路径应该是这样:

image.png

下面的图片是我本地,创建了一个项目,然后新建了一个应用后的目录构成。

创建项目 django-admin startproject djangodemo

创建应用 django-admin startapp news

image.png

一般django的最顶层目录名被视作工程名(project),下有manage.py文件和一个与顶层目录同名文件夹,该文件夹下包含了setting.py, urls.py, wsgi,py。

setting.py: 配置文件,例如添加一些中间件,定义模板文件,静态资源的目录地址等。

urls.py: 定义路由规则的,例如www.aaa.com/A,www.aaa.com/B, A和B两个地址访问后,调用后台什么方法,都在urls这边指定。

wsgi.py: wsgi是一种规范,它定义了使用python编写的web app(应用程序)与web server(socket服务端)之间接口格式,实现web app与web server间的解耦。主要用于在Windows上启动django服务。在Linux上则是uwsgi。看上去直接执行manage.py也能使用,但是性能较差,也不适合前后台分离,使用wsgi+nginx+django可以实现前后台分离并且wsgi可以配置多个worker,提高并发量。

manage.py: 这个是用来管理项目的文件,支持一些django内置的命令。例如startproject,startapp,test, check,shell等,此处不展开,后面单开一篇说。

一个project下面可以包含一个或多个应用(app),每个应用目录下又包含了migrations,admin.py,apps.py,models.py,tests.py以及views.py文件。

migrations: 存放数据库升级和备份脚本的地方。

admin.py: 配置admin后台,如果你自定义了一些内容需要在admin看到,需要在此添加一下。

apps.py: 每个应用专属的可以配置一些属性的文件,setting.py中需要引入

models.py: 定义数据原始模型的文件,一般不在此直接操作数据库,这里没有Java中的dao层的概念。Django.model本身就是ORM,不需要写原始的SQL,除非不用sqlite3,使用mysql等其他数据库。

tests.py: 单元测试的文件。

views.py: 视图文件,urls+views实现的是类似Java中Controller的作用:匹配访问路径,执行指定文件。不过一般不在view层写很重的业务,较为复杂的可以再自定义文件,在view调用。自定义文件实现类似于Java中Service层的功能。

templates是存放html文件的,也就是django里说的模板文件,因为我是pycharm新建工程的时候已经加入自动创建了,各位看教程的话命令行创建工程和应用后,该目录需要手动创建。

安装

Django的安装很简单。

1
pip install django

两种创建方式

命令行创建方式

ps: scripts需要加到path环境变量中。创建工程,djangoname1是工程名,支持自定义

1
django-admin startproject djangodemo1

image.png

创建应用,

1
django-admin startapp djangodemo1

image.png

运行

1
2
3
4
python manage.py runserver

另外更改host或者端口可以这样写
python manage.py runserver ip:port

image.png

默认监听本地8000端口,打开浏览器访问一下。

image.png

使用pycharm创建

需要你的pycharm是profession版,如果是社区版没有这个功能。打开pycharm后,左上角,File –> New Project

image.png

点击create就好了,project interpreter是设置java运行环境的,我这边没什么特殊版本需求直接用本地的3.7了。

image.png

创建后内容和通过命令行创建是类似的,不过多出了模板目录templates,命令行中自己创建也是一样的效果。 命令行创建比pychjarm创建多出了一个db.sqlite3文件(其实就是.db格式,一个简单的数据库文件,更改后缀后可以直接使用Navicat打开的,大多数命令和MySQL操作一致的) pycharm中除了可以第一种里命令行启动的方式,也可以直接运行manage.py。

image.png

本质也是命令行执行,只不过不需要你手动写。

image.png

第一个页面

第一部操作后,服务已经启动了,只是没有什么内容,默认的首页还是djang启动的。好了,现在我们自己要写一个首页,啥也不说了,返回个hello world吧。

看完django的请求链路后,我们知道,要在urls.py写路由。

image.png

啥也没有,自己加一个。

image.png

这个意思就是首页,访问views.index方法。(最新版本的Django不需要写’/‘,根路径就是’’)但是index方法我是没定义的,现在来定义一下。

img

运行一下!

image.png

恭喜你,你已经可以写网站了。。。

开个玩笑,这里可以看到我们是直接引用了django.http里的HttpResponse方法,返回了一个httpresponse类型,

image.png

image.png

上面我们没有使用模板,但最终从浏览器中可以看到最终也是一个document类型。接下来我们使用模板。

在templates新建一个首页index.html

image.png

回到views,更改返回内容

image.png

重启一下访问看看

image.png

一样是document类型,返回了整个html页面。

(PS: 不必纠结于页面的简陋与否,先把urls到views再到返回模板内容这一套逻辑搞明白)

模板参数的使用

上面我们返回了一个html文件,在djnago的框架下,html是支持书写一些简单的django语句的。这里主要说一下调用参数,和常用的for循环,if判断。

变量的使用

首先html使用变量,需要在views层返回,写法如下:

image.png

意思是,返回一个html文件中用到的变量,变量为title,值是”我是首页”。 html文件中如此引用。

image.png

访问一下。

image.png

在html模板里,变量一般使用 {{ parameter }}的方式,而像for循环,if判断等涉及到语法操作的使用{% %},且必须有始有终,结尾使用{% endfor %},{% endif %}

for的使用

例如返回一个页码列表page_list,打印所有页码:

1
2
3
{% for i in page_list %}
<a href="">{{ i }}</a>
{% endfor %}

如果遍历的对象是字典,那么还可以使用 i.x的形式打印对于key的值

例如返回一个学生信息的列表students,列表里每个值都是一个字典,包含名字,性别,年龄。

1
2
3
4
5
{% for student in students %}
名字:{{ student.name }}
年龄:{{ student.age }}
性别:{{ student.sex }}
{% endfor %}

if的使用

例如一个变量flag为true,显示一个新建按钮,如果不是就什么都显示

1
2
3
{% if flag == "true" %}
<button>新建</button>{% else %}
{% endif %}

模板的继承

经常可以看到一个网站,很多三段式的布局,上面是菜单导航,底部是网站注册信息等,中间展示大段内容。一个页面如此,几百个也是这样,难道一个一个页面写的?自然不是,对于这样的结构相似的页面,完全可以写一个基础模板文件,例如base.html,然后其他页面在base.html的基础上,加入自己的内容,这个动作,在django叫继承。使用{% extends **"base.html" **%},且这句话必须放在html的首行。另外在base.html需要使用{% block xx %}{% endblock %}来给继承的文件留下自定义内容的位置,xx不代表类型,只是一个自定义变量名。举个例子,新建一个bast.html,三段式布局,头部和底部固定,留下中间body可以自定义。

模板文件

image.png

继承模板文件,预留位置添加内容

image.png

效果如下

image.png

获取url参数实现计算功能

实际项目里,get请求也可能带有一些参数。

例如看一个工单详情

image.png

PS:一般标准url,在path后”?”开始的地方即是变量开始的地方,采用key=value的形式,多个变量之间使用”&”连接。接下来写一个简单一点的,做一个加法运算 (实际简单的运算可以前端js直接完成,这里出于介绍需要)index.html修改一下

image.png

uirls.py

image.png

views.py

image.png

通过这种方法,可以获取get类型方法后面的参数。 现在来查看首页

image.png

点击一下

image.png

可以看到地址栏变了,并且返回正确的值:3

同个接口包含get与post方法

上面的例子,我们实现了从url获取参数的功能,但是实际上上面的例子是从首页跳转到了add页面(尽管templates下没有直接的add.html)。实际项目里一般都是在同一个页面做这种操作,通过js直接进行计算或者通过js获取你的输入值传给后台的一个接口返回数值再进行展示,这两种都不是django本身的用法,下面说一下只使用django要怎么做。

在django的views里,每个方法都默认带有一个request入参,代表的是这个请求的所有信息,因此也包含了他的methods,可以根据methods判断他是get还是post然后返回不同内容。这边如果用django自带方法发送post请求,则需要用到forms表单。

拿比较经典的登陆操作为例,如下图

image.png

首先在app目录下新建一个forms.py文件

1
2
3
4
5
6
from django import forms


class LoginForm(forms.Form):
username = forms.CharField(max_length=10)
password = forms.CharField(max_length=10)

urls添加login

image.png

views写login方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from django.shortcuts import render
from django.http import HttpResponseRedirect


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

def login(request):
message = None
if request.method == 'POST':
from firstapp.forms import LoginForm
form = LoginForm(request.POST)

if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
# 这边写的简单,实际要跟数据库取出来的作比较,同时前台会加密,跟后台取出来的比
# 还会涉及到加盐操作,这里主要讲methods,先写死了。
if username == "test" and password == "test":
return HttpResponseRedirect('/')
message = "登陆失败"
return render(request, 'login.html', {"message": message})

templates下新增login.html文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
{% csrf_token %}
username:<input type="text" name="username"/> <br/>
passowrd:<input type="password" name="password"/> <br/>
<input type="submit" value="登陆到首页"/>

<!-- 这里加一个判断,如果有message返回,说明失败了,才会在页面显示-->
{% if message %}
<p style="color: red">{{ message }}</p>
{% endif %}
</form>
</body>
</html>

访问127.0.0.1:8000/login

img

用户名密码输入test/test就登陆到首页了。

首页图就不放了,上面我们对登陆失败做了设定,如果登陆失败依然回到login并且返回失败的信息message,试一下。

image.png

可以看到,设置生效了,成功到首页,失败回到login页,并且告知错误信息。

使用静态资源

上面的内容均为涉及静态资源(css,js,img等),假如要你展示一张图片,很多人可能第一个想到的就是在urls里去匹配,但是几百张图片,几十个css,js文件难道一个一个去写?django已经想到了这种情况并且有一个快速使用的方式。打开 setting文件,可以看到末尾有下面这行

image.png

意思是你的静态资源的url地址前缀都将包含static。

可以在顶层目录下新建一个目录static,随后放一张图片a.png

image.png

(PS:实际使用中staic最好还需要再细分,css目录,js目录,img目录等,这里举例子不搞那么复杂了)在setting文件下加一行内容,定义static目录位置

1
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]

image.png

在html文件中按如下格式引用。

image.png

访问一下

image.png

图片加载出来了,顺带可以打开控制台看一下他的访问路径

image.png

返回标准json格式

由于后面做平台,更多实施是需要django返回接口的信息,所以这里介绍下使用django返回标准json的方法。(PS: 方式有很多,这里介绍两种)

使用HttpResponse

views.py文件

1
2
3
4
5
6
7
from django.http import HttpResponse
import json


def index(request):
result = {"name": "CC", "sex": "man", "age": 18}
return HttpResponse(json.dumps(result), content_type="application/json", charset=utf-8")

使用JsonResponse

views.py文件

1
2
3
4
5
6
from django.http import JsonResponse


def index(request):
result = {"name": "CC", "sex": "man", "age": 18}
return JsonResponse(result, safe=False) # 不加safe=False的话必须返回dict

这种方式简单,不过中文会乱码。

使用admin后台

已安装过admin

image.png

进入后台是需要登陆的,涉及到用户,就需要创建相关的表,用到了admin和auth模块,不过这一整套表的创建内容都已经写好了,我们要做的就是执行创建表的操作,然后创建超级用户。

### 创建表

1
2
3
4
5
6
7
8
python manage.py makemigrations 
# 由于这里没有表结构的变动,执行改语句不会生成新的脚本变动文件,加入你在models自定义的表做了修改,
# 执行这个命令,将会在各自app下migrations的目录中生成脚本变动的文件,py格式。


python manage.py migrate
# 执行上述生成的脚本文件,这里因为默认setting里加载了auth,虽然migrations目录下没有文件,但auth
# 需要的表将会创建

image.png

可以看到,表都创建好了。

创建超级用户

1
python manage.py createsuperuser

image.png

输入用户名,邮箱可以跳过,输入密码。我这里密码太简单了提示是否无论如何都这样创建。

登陆admin后台

输入/admin会自动跳转到login页面

image.png

输入刚刚创建的用户名密码登陆

image.png

手动加载admin

上面操作都比较简单,因为目前最新版本无论是命令行还是pycharm自带创建,都帮你把admin模块等给安装好了。如果没有的话,我们需要用的时候就得手动配置一下。

setting中安装admin*

image.png

urls中定义admin的路由

image.png

setting中加入中间件

image.png

后面创建表,创建用户步骤跟上面一样。

自定义model并通过admin加载

使用django,基于已有的admin模块,可以快速撸一个后台。假设现在需要你在admin后台,添加一个管理学生信息的工具,怎么做?

那么涉及到管理,必然涉及到数据的增删查改了,先在models创建数据模型吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from django.db import models

# Create your models here.


class Students(models.Model):
id = models.IntegerField('序号', primary_key=True, auto_created=1)
no = models.IntegerField('学号', null=False)
name = models.CharField('姓名', max_length=10, null=False)
age = models.IntegerField('年龄', max_length=3, null=False)
sex = models.CharField('性别', choices=(('男', '男'), ('女', '女')), max_length=2)
creation_time = models.DateTimeField('创建时间', auto_now_add=True, editable=False)
modified_time = models.DateTimeField('修改时间', auto_now=True)

def __str__(self):
return self.name

前面说了生成表结构变动的SQL和执行的两个命令,执行一下。

python manage.py makemigrations python manage.py migrate

在admin.py目录下注册这个Students

1
2
3
4
5
6
from django.contrib import admin
from news.models import Article

# Register your models here.

admin.site.register(Article)

重启后登陆后台

image.png

点击add添加一个学生记录

image.png

image.png

一个学生信息就创建好了,关于admin后台,可玩性还有很多,例如可以加入搜索功能,这边学生信息可以扩展默认展示的列表直接当作查询使用,还可以加入富文本编辑器直接用来编写博客等等。

练习

经过上面的学习,可以写一个内容发布和展示的demo。

要求:

  1. 创建一个内容的数据模型,需要包含: id,标题,内容,作者,创建时间,修改时间
  2. 首页列出所有内容的序号和标题,并且带有href属性
  3. 点击对应的标题,跳转新页面,带出对应的内容

目标:后台可以增删改发布信息,前台页面可以看到所有内容的标题,点击标题跳转能看到正文内容。

评论