Django基础
启动Django和了解它的文件组成
最先也没有接触过Django,所以从0开始了解下最最基础的部分
首先安装Django之后会有个控制命令
django-admin
可以通过该命令来创建Django项目
django-admin startproject Django2
可以看到在Django2
下生成了一个文件manange.py
和一个目录Django2\Django2
,目录下有几个python
文件
manage.py
是一个管理项目的文件(工具人),可以控制项目
Django2\Django2目录下
__init__.py:
一个空文件,告诉 Python 该目录是一个 Python 包。
settings.py:
该 Django 项目的设置/配置,它会涉及到数据库的连接配置,视图模板的路径配置。
urls.py:
该文件是web路由的配置
wsgi.py:
该文件是一个 WSGI 兼容的 Web 服务器的入口,可以理解为,可以靠他不用python来启动服务,要靠Nginx来启动服务的话,就要使用到这个文件
启动命令就可以借助刚刚的manage.py
文件了
python manage.py runserver 0.0.0.0:8000
不同版本界面不一样的,2.1版本貌似是一个小飞机,这里是1.11.20
项目第一次启动后,在目录下就会生成一个db.sqlite3
的数据库文件
视图的使用
要把视图显示出来,首先在/Django1/Django1
下随便创个文件,写下面的内容
# sijidou.py from django.http import HttpResponse def hello(request): return HttpResponse("hello sijidou")
接下来对urls.py
进行配置,把刚刚的文件import进来, 填加个url(r‘hello/‘, sijidou.hello)
路由
#urls.py from django.conf.urls import url from django.contrib import admin from . import sijidou urlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘hello/‘,sijidou.hello), ]
在Django的2.0版本,使用的path()
来替换的url()
,也就是
from django.urls import path from . import sijidou urlpatterns = [ path(‘hello/‘, sijidou.hello), ]
在Django,按照MVC的思想,视图文件在主目录下放置templates
目录,把视图文件放在里面
而python的视图文件就是模板注入的亚子
<!--Django2/templates/hello.html--> <h3>{{ hello }}</h3>
在setting.py文件中添加templates
目录的路径
接下来修改下之前的sijidou.py
,让他使用注入的方式传入模板,注意引入的包和之前不同
#Django2/Django2/sijidou.py from django.shortcuts import render def hello(request): context = {} context[‘hello‘] = ‘Hello sijidou‘ return render(request, ‘hello.html‘, context)
对于Django的模板,可以理解成类似于java的jsp
文件一样,虽然Django模板是.html
结尾,但是具有一定的语法
{% include "1.html" %} //包含 {# 注释 #} //注释 //判断是否相等 {% ifequal var1 var2 %} xx {% endifequal %} //判断 {% if a > b %} xx {% elif b < a and b == d %} xx {% else %} xx {% endif %} //循环 {% for i in list %} <li>{{ i.value }}</li> {% endfor %}
模型的使用
模型一般是用来连接数据库之类的
在创建模型的时候需要使用django-admin
或者manager.py
来创建模型,创建位置在/Django2
这个根目录下
django-admin startapp app python manager.py startapp app
那么问题来了django-admin startapp
和django-admin startproject
有什么区别
project
相当于一个项目,里面的setting会去连一个数据库
app
相当于一个模块,而它会去根据业务的不同通过其中的models.py
文件选择连接多个表
一个project
可以由多个app
,反之不行
生成app后查看下对应的目录文件
两个__init__.py
是空的,他们的作用是说明目录是个python模块
migrations
目录是用来存在数据库迁移记录的,简单的来说就是把数据库里面的字段映射到Django中,好被Django使用
admin.py
是后台管理员
apps.py
是这个模型的入口
models.py
里面有多个模型类,每个模型类用来连接表的
tests.py
是测试文件
views.py
是对请求的处理
创建app
后要使project
找到app
不是放在project
项目下的目录就可以的,需要在setting.py
中加上一行(我这里叫生成的目录叫app
,所以加的路径就是app
)
这个INSETALLED_APPS
也可以添加成app.apps.AppConfig
这个路径,也就是app
目录下的apps.py
文件的AppConfig()
函数
撰写models.py
,Django
在发出迁移命令后,会根据这个配置文件进行对相应数据库的修改
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models # Create your models here. class user(models.Model): username = models.CharField(max_length=20) age = models.IntegerField()
这里将记录下mysql的连接和Postgresql的连接
mysql
对于mysql来说先在setting.py
文件中配置如下信息
DATABASES = { ‘default‘: { ‘ENGINE‘: ‘django.db.backends.mysql‘, ‘NAME‘: ‘django‘, #数据库名 ‘USER‘: ‘root‘, #数据库账号 ‘PASSWORD‘: ‘root‘, #数据库密码 ‘HOST‘:‘localhost‘, #数据库地址 ‘PORT‘:‘3306‘, #数据库端口 } }
在之前我们不需要准备数据库的表和字段
改之前可以看到,它用的是之前自动创建的db.sqlite3
这个数据库(这也就是为什么运行第一次会出现一个.sqlite3
文件原因)
把上面的内容替换成mysql连接信息(有中文,在文件最前面加个 #-*- coding:UTF-8 -*-
)
接下来运行,这段代码是把setting.py
文件中的INSTALLED_APPS
列表中的库加入到mysql
数据库中
python manage.py migrate
运行后,数据库里面多了很多很多的表
先不管它有什么用,接下来运行下面的命令,它能在
python manage.py makemigrations app
可以看到生成app/migrations/0001_initial.py
,下面有user的映射了
之后再次运行migrate
,这次带上了app参数,它会依据app\migrations
下的文件去更新数据库
python manage.py migrate app
这次会发生什么变化呢,在mysql中的已生成的django_migrations
表中,添加了一行数据,并且会出现一个新的表,命名格式为模型名_model中的类名
,之后Django进行查询是会去查该表,对比下
运行前(数据库中user表示最先添加,和Django无关)
运行后
我们拿到app_user
表,它的字段是根据models.py
来创建的,并且自动添加了id
主键,但是内容为空,之后可以就是写文件进行数据库查询显示了,在\Django2\Django2
(project目录)下创建个showdb.py
的文件
我先手动添加信息
postgresql
和mysql连接一样,先修改setting.py
配置文件,我数据库密码设置的和账户名一样都是postgres
DATABASES = { ‘default‘: { ‘ENGINE‘: ‘django.db.backends.postgresql_psycopg2‘, ‘NAME‘: ‘django‘, #数据库名 ‘USER‘: ‘postgres‘, #数据库账号 ‘PASSWORD‘: ‘postgres‘, #数据库密码 ‘HOST‘:‘localhost‘, #数据库地址 ‘PORT‘:‘5432‘, #数据库端口 } }
首先发出迁移,将models.py
的内容写入到migrations
下
python manage.py makemigrations
接着讲python的所需要的表的信息,写入到数据库中
python manage.py migrate app
这里如果使用Django来添加数据,可以运行下面代码
#Django2/Django2/showdb.py # -*- coding: utf-8 -*- from django.http import HttpResponse from app.models import user # 数据库操作 def showdb(request): user1 = user(username=‘mi1‘, age=20) user1.save() user2 = user(username=‘mi0‘, age=19) user2.save() return HttpResponse("insert ok")
运行下就添加进去了
back
之后进行查询
#Django2/Django2/showdb.py # -*- coding: utf-8 -*- from django.http import HttpResponse from app.models import user # 数据库操作 def showdb(request): response = "" response1 = "" l = user.objects.all() for var in l: response1 += str(var.age) + " " + str(var.username) + "\n" response = response1 return HttpResponse("<p>" + response + "</p>")
添加一个路由
from django.conf.urls import url from django.contrib import admin from . import sijidou from . import showdb urlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘^hello/‘, sijidou.hello), url(r‘^user/‘,showdb.showdb), ]
能够进行数据库查询了
可以利用过滤器来选择查询的内容
# -*- coding: utf-8 -*- from django.http import HttpResponse from app.models import user # 数据库操作 def showdb(request): #response2 = user.objects.filter(id=1) response2 = user.objects.get(id=1) #res = response2[0].username res = response2.username return HttpResponse("<p>" + res + "</p>")
get
和filter
的区别在于,filter
返回的是一个列表,而get
返回的是一个对象值
修改数据库
# -*- coding: utf-8 -*- from django.http import HttpResponse from app.models import user # 数据库操作 def showdb(request): response2 = user.objects.get(id=1) response2.username = ‘sijidou‘ response2.save() response3 = user.objects.get(id=1) res = response3.username return HttpResponse("<p>" + res + "</p>")
删除数据
# -*- coding: utf-8 -*- from django.http import HttpResponse from app.models import user # 数据库操作 def showdb(request): response2 = user.objects.get(id=1) response2.delete() return HttpResponse("<p>delete ok</p>")
表单的接收
在Django2\Django2
目录下新建一个show.py
from django.http import HttpResponse from django.shortcuts import render_to_response def info_form(request): return render_to_response("form.html") def info(request): a = request.GET[‘a‘] return HttpResponse(a)
info_form()
是显示表单输入的页面
info
是显示提交后的显示页面
修改下路由
from django.conf.urls import url from django.contrib import admin from . import sijidou from . import showdb from . import show urlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘^hello/‘, sijidou.hello), url(r‘^user/‘,showdb.showdb), url(r‘^show_form/‘, show.info_form), url(r‘^show‘, show.info), ]
模板文件写一下Django2\templates\form.html
<html> <head> <meta charset="UTF-8"> </head> <form action="/show" method="GET"> <input type="text" value="" name="a" /> <input type="submit" value="submit" name="submit" /> </form> </html>
之后就能收到GET请求了
如果是post请求,和get请求稍微有所不同在于,html
视图文件需要价格crsf_token
的,这里要引入csrf的。
这里的对token的检查控制流程是这样的
加入token
一定要用render()
把request
包含进去,没有这一步就在页面中就没有token
了
只要有token
,发送请求,在接收到request的时候就会检验,检查通过后,之后的返回值和处理如何就不会受影响
from django.http import HttpResponse from django.shortcuts import render_to_response,render from django.views.decorators import csrf def info_form(request): return render(request,"form.html") def info(request): text = {} text[‘back‘] = request.POST[‘a‘] return HttpResponse(text[‘back‘])
在form.html
下加入token的模板
<html> <head> <meta charset="UTF-8"> </head> <form action="" method="POST"> <input type="text" value="" name="a" /> {% csrf_token %} <input type="submit" value="submit" name="submit" /> </form> </html>
cookie和session
cookie的使用
cookie设置有很多参数
HttpResponse.set_signed_cookie(key, value, salt=‘‘, max_age=None, expires=None, path=‘/‘, domain=None, secure=None, httponly=False) #带盐的 HttpResponse.set_cookie(key, value, max_age=None, expires=None, path=‘/‘, domain=None, secure=None, httponly=False) #不带盐的
key:键
value:值
salt:加盐
max_age:存活时间以秒为单位,为None则在关闭浏览器后失效
expires:过期时间,如果有这个,优先级比max_age高,设置格式Wdy, DD-Mth-YY HH:MM:SS GMT
path:作用的路径
doamin:作用的域
secure:利用https
httponly:只能通过http来解析,js没法用document.cookie获取了
获取cookie也有一整套的流程,参数相同的部分理由和上面一样,反正主要就是key和salt了
HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt=‘‘, max_age=None) #带盐 HttpRequest.get_cookie(key, default=RAISE_ERROR, max_age=None) #不带盐
删除cookie,参数相同和设置cookie一样
HttpResponse.delete_cookie(key, path=‘/‘, domain=None)
利用刚刚的show.py
的demo
先写个加盐的,逻辑如果收到post,则把post的数据存在cookie中,如果不是post请求,则把cookie中的back字段显示出来,并删除掉cookie
from django.http import HttpResponse from django.shortcuts import render_to_response,render from django.views.decorators import csrf def info_form(request): return render(request,"form.html") def info(request): text = {} if request.POST: text[‘back‘] = request.POST[‘a‘] rep = HttpResponse(text[‘back‘]) rep.set_signed_cookie(‘back‘, text[‘back‘], ‘dddd‘) else: text[‘back‘] = request.get_signed_cookie(‘back‘,‘dddd‘) rep = HttpResponse(text[‘back‘]) rep.delete_cookie(‘back‘) return rep
再访问次,cookie中的值先被取出来,之后被删除了
当然2次的盐不对就无法从cookie中取出想要的值,反而还会报错
再尝试次不带盐的,可以看到是明文了
from django.http import HttpResponse from django.shortcuts import render_to_response,render from django.views.decorators import csrf def info_form(request): return render(request,"form.html") def info(request): text = {} if request.POST: text[‘back‘] = request.POST[‘a‘] rep = HttpResponse(text[‘back‘]) rep.set_cookie(‘back‘, text[‘back‘]) else: text[‘back‘] = request.get_cookie(‘back‘) rep = HttpResponse(text[‘back‘]) rep.delete_cookie(‘back‘) return rep
session的使用
在先前的post表单的demo上进行修改
from django.http import HttpResponse from django.shortcuts import render_to_response,render from django.views.decorators import csrf def info_form(request): return render(request,"form.html") def info(request): text = {} if request.POST: text[‘back‘] = request.POST[‘a‘] request.session[‘back‘] = text[‘back‘] else: text[‘back‘] = request.session.get(‘back‘) request.session.flush() return HttpResponse(text[‘back‘])
逻辑很清晰,如果收到post,则把post的数据存在session中,如果不是post请求,则把session中的back字段显示出来,并删除掉session
发送post后,cookie中有session字段了
在Django中session是存在数据库的,进入postgresql查看下
select * from django_session;
把这串base64进行解码
前面是不知道是啥的字符串,后面就是刚刚传的键值对
接着刚刚的逻辑,这次使用get请求直接访问/show
,能够从session中取出数据,并且session已经消失
admin后台管理
django有可视化的后台管理服务,只需要启动它即可,不需要太多的编码,之前使用数据库迁移的时候会生成很多库
其中以auth开头的表都是用来为后台管理提供数据的,至于如何添加进来,在INSTALLED_APPS
下就有声明
之后再url.py
中开启路由和导入包即可访问后台了
但是此时没有账号,就没法登陆,需要通过manage.py
来创建个账号
python manage.py createsuperuser
创建成功后进去,只能管理管理员的数据库的表,为了管理更多的表,需要进行添加关系到Django的模型下的admin.py
中,这里我把之前的app_user表
添加进去
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.contrib import admin from models import user # Register your models here. admin.site.register(user)
之后再访问管理员页面,就有添加的表了
只让他显示修改username的话需要进行以下修改,需要继承admin.ModelAdmin
,之后在fields属性
中设置需要显示的字段(这里要用list对象),最后把类和模型中的类对应起来注册
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.contrib import admin from models import user # Register your models here. class ContactAdmin(admin.ModelAdmin): fields = (‘username‘,) admin.site.register(user, ContactAdmin)
改变前
改变后
列表显示中,可以设置需要哪些列表被显示出来,列表所对应的是list_display属性
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.contrib import admin from models import user # Register your models here. class ContactAdmin(admin.ModelAdmin): fields = (‘username‘,) list_display = (‘username‘, ‘age‘) admin.site.register(user, ContactAdmin)
添加前,是这样的
添加后
也可以添加搜索框,只需要设置search_fields属性
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.contrib import admin from models import user # Register your models here. class ContactAdmin(admin.ModelAdmin): fields = (‘username‘,) list_display = (‘username‘, ‘age‘) search_fields = (‘username‘,) admin.site.register(user, ContactAdmin)
添加后就可以以username字段
来查询了
参考链接:
https://www.runoob.com/django/django-form.html
https://docs.djangoproject.com/zh-hans/2.2/
https://blog.csdn.net/liubingger/article/details/80968066
https://blog.csdn.net/chen1042246612/article/details/84327046