Django请求周期

url ->  路由系统  ->函数或者类 -> 返回字符串 或者 模板语言

Form表单提交:

  点击提交 -> 进入url系统  ->  执行函数或者类的方法 - > 返回字符串

ajax提交:

  

路由url

1.path('index/', views.index),一个url对应一个函数

2.path('home/', views.Home.as_view()),一个url对应一个类

3.url(r'^detail-(\d+).html',views.detail),一类url对应一个函数或者一个类,在view中那个detail要传入匹配到的值,严格按照形式参数的顺序获取

4.url(r'detail-(?P<nid>\d+)-(?P<uid>\d+).html',view.detail),用这样的方式进行定义url就 会让view中的函数的形参能够对应起来。

实战

a.
url(r'^detail-(\d+)-(\d+).html',views.detail), def func(request,nid,uid):
pass
def func(request,*args):
args=(传入的第一个数,传入的第二个数)
def func(request,*args,**kwargs):
args=(传入的第一个数,传入的第二个数)
kwargs={}
b.
url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html',views.detail) def func(request,nid,uid):#nid和uid位置互换不影响传值
pass
def func(request,**kwargs):
kwargs={'nid':1,'uid':3}
def func(request,*args,**kwargs):
args=[]
kwargs={'nid':1,'uid':3}

5.name:对url路由的关系进行命名,以后可以根据此名称生成自己想要的url

path('indexasdfad/', views.index,name="i1"),

模板语言:
<form action="{% url 'i1' %}" method="post"> 后面有参数:
url(r'^indexasdfad/(\d+)', views.index,name="i2"),
模板语言:
<form action="{% url 'i2' 3 %}" method="post">
当前url:
  request.path_info
url(r'^indexadff/(?P<nid>\d+)/(?P<uid>\d+)/',views.index,name="i3")
如果想要根据name生成url:
from django.urls import reverse
def func(requset,*args,**kwargs):
  url1=reverse('i1')                #indexasdfad
  url2=reverse('i2',args=(1,2))         #indexasdfad/1/2
  url3=reverse('i3',kwargs={'nid':1,'uid':3}) #indexadff/1/9
xxx.html
{%url "i1" %}#indexasdfad
{%url "i1" 1 2 %}#indexasdfad/1/2
{%url "i1" nid=1 uid=3 %}#indexasdfad/1/2

6.路由分发

首先是主程序中的url设置,用include来包含两个app的路由路径,大的分类

app01的路由设置:

app02的路由设置:

效果:

7.默认值

在创建url的时候设置一个默认值,然后views里面的方法就要有一个参数接受,参数的名称就是这个字典中的key

8.命令空间

多个 url对应一个app函数:

主project里的urls.py:通过include函数在里面设置namespace设置空间名

from django.contrib import admin
from django.urls import path
from django.conf.urls import url,include
from app01 import views
urlpatterns = [
url(r'a/',include('app01.urls',namespace='author')),
]

app01里面的urls.py:在里面写上app的名称,并且在url中设置name

from django.conf.urls import url,include
from app01 import views
app_name = 'app01'
urlpatterns = [ url(r'^index/', views.index,name='index'), ]

app01中views.py:翻转的时候要用命名空间:name

from django.shortcuts import render,HttpResponse
from django.urls import reverse
# Create your views here.
def index(request):
v = reverse('author:index')
print(v)
return HttpResponse("index")

通过reverse函数翻转出来的url:/a/index/

视图

1.form表单提交数据的种类

  request.body:所有数据内容的原生值,POST,GET都是由这个转换过来的

    request.POST

    request.GET  

    request.FILES:只取上传的文件

    request.POST.getlist():获取checkbox,select等多选的内容

  request.environ:这里面包含了所有请求需要的参数信息,以字典的形式存储,

  request.Meta(...)

    request.method(POST,GET,PUT)

    request.path_info

    request.COOKIES

2.上传文件,form标签中一定要加enctype="multipart/form-data"

  obj=request.FILES.get('name值')

  obj.name文件名

  f=open(obj.name,mode="wb")

  for item in obj.chunks():

    f.write(item)

  f.close()这样就实现了文件的上传功能

3.FBV      &       CBV

function base view

  url.py

    index->函数名

  view.py

    def 函数(request):......

当然我们还有一种写法就是:

class base view

  url.py

    home->类名.as_view(),即path('home/',views.Home.as_view())

  view.py

    from django.views import View

    class 类名(View):

      def get(self,request):pass

      def post(self,request):pass

4.装饰器:

比如我们有个网站有很多的页面,我们只有登录了之后才能够查看内容,这个时候我们不能够一个函数一个函数的去加login的代码,那我们就可以用装饰器进行验证

FBV的装饰器:

 def auth(func):
def inner(request,*args,**kwargs):
v = request.COOKIES.get('username')
if not v:
return redirect('/login/')
return func(request,*args,**kwargs)
return inner
@auth
def index(request):
#获取当前已经登录的用户
v = request.COOKIES.get('username')
return render(request,'index.html',{'current_user':v})

CBV的装饰器:

urls.py:

url(r'^order/',views.Order.as_view()),

views.py:

 class Order(views.View):
def get(self,request):
v = request.COOKIES.get('username')
return render(request, 'index.html', {'current_user': v}) def post(self,request):
v = request.COOKIES.get('username')
return render(request, 'index.html', {'current_user': v})

这里面有两个方法,如果我们只想要给其中的get函数加上装饰器,那么我们直接加上就可以了:

  @method_decorator(auth)
def get(self,request):
v = request.COOKIES.get('username')
return render(request, 'index.html', {'current_user': v})

但是如果我们想要给这个类里的所有方法都加上装饰器的话

1.类中有一个方法叫做dispatch,是在所有方法执行之前执行的,可以在那个函数上加

 class Order(views.View):
@method_decorator(auth)
def dispatch(self, request, *args, **kwargs):
return super(Order,self).dispatch(request, *args, **kwargs) def get(self,request):
v = request.COOKIES.get('username')
return render(request, 'index.html', {'current_user': v}) def post(self,request):
v = request.COOKIES.get('username')
return render(request, 'index.html', {'current_user': v})

2.直接在类名上面加装饰器:注意里面有一个name属性,值要为dispatch

 @method_decorator(auth,name='dispatch')
class Order(views.View): def get(self,request):
v = request.COOKIES.get('username')
return render(request, 'index.html', {'current_user': v}) def post(self,request):
v = request.COOKIES.get('username')
return render(request, 'index.html', {'current_user': v})

通过上面两个方法都可以把类中所有的方法加上装饰器  

模板

模板的继承:

一个html只能继承一个模板:

模板文件master.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="/static/commons.css" >
<style>
.pg-header{
height:48px;
background-color: seashell;
color:green;
}
</style>
{% block css %}{% endblock %}
</head>
<body>
<div class="pg-header">后台管理</div>
{% block content %}{% endblock %}
<script src="/static/jquery-1.12.4.js"></script>
{% block js %}{% endblock %}
</body>
</html>

继承模板的html文件:

{% extends 'master.html' %}
{% block title %}用户管理{% endblock %}
{% block content %}
<h1>用户管理</h1>
<ul>
{% for i in u %}
<li>
{{ i }}
</li>
{% endfor %}
</ul>
<script src="/static/jquery-1.12.4.js"></script>
<script> </script>
{% endblock %}
{% block css %}
<style>
body{
background-color: red;
}
</style>
{% endblock %}
{% block js %}
<script></script>
{% endblock %}

模板的导入:

相同的html标签模块可以写在单独的文件中,然后进行模板导入

重复的html:tag.html

<form>
<input type="text" />
<input type="submit" value="提交" />
</form>

模板的导入:

 {% include "tag.html" %}

自定义single tag:

django中有许多的模板参数,但是如果无法满足我们的需求,那怎么办呢?这个时候我们可以自定义模板参数:

首先我们在app01中写一个模板函数:文件夹必须要用templatetags,其他的文件名都不可以

from django import template
from django.utils.safestring import mark_safe register = template.Library()
@register.simple_tag
def xiaohong():
return 123

register的名字也不能够改

下面我们需要在settings中注册app

然后我们在html中使用看看:顶部要有load

{% load xxoo %}
。。。。。。
{% xiaohong %}

显示出了上面函数返回的值

那我们把上面自定义的函数改一下:

from django import template
from django.utils.safestring import mark_safe register = template.Library() @register.simple_tag
def xiaohong(a1,a2):
return a1+a2

然后我们在模板html文件中使用:{%函数名 arg1 arg2.....%}

{% load xxoo %}
。。。。。。。。。。
{% xiaohong 5 2 %}

这样我们以后想要在页面上想要做一些操作,只要通过一个自定义函数就可以了,这个函数中的参数任意个数,但是不能放在if后面做判断

自定义filter:

自定义的模板文件中:

from django import template
from django.utils.safestring import mark_safe register = template.Library() @register.filter
def liangliang(a1,a2):
return a1+a2

html文件中使用:{{'参数一'|函数名:'参数二'}}

{% load xxoo %}
。。。。
{{ 'maliya'|liangliang:'LS' }}

上面的自定义filter中参数只能是两个,如果多了就报错,而且也不能加空格

应用场景:if else判断中:

{% if 'maliya'|liangliang:'LS' %}

{% endif %}

ORM操作

创建类

1.根据类自动创建数据表

  app下的models.py

a.先写类

#表名为app01_userinfo
class UserInfo(models.Model):
#id列,自增,主键
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
AutoField(Field)
- int自增列,必须填入参数 primary_key=True BigAutoField(AutoField)
- bigint自增列,必须填入参数 primary_key=True 注:当model中如果没有自增列,则自动会创建一个列名为id的列
from django.db import models class UserInfo(models.Model):
# 自动创建一个列名为id的且为自增的整数列
username = models.CharField(max_length=32) class Group(models.Model):
# 自定义自增列
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32) SmallIntegerField(IntegerField):
- 小整数 -32768 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正小整数 0 ~ 32767
IntegerField(Field)
- 整数列(有符号的) -2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正整数 0 ~ 2147483647 BigIntegerField(IntegerField):
- 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 自定义无符号整数字段 class UnsignedIntegerField(models.IntegerField):
def db_type(self, connection):
return 'integer UNSIGNED' PS: 返回值为字段在数据库中的属性,Django字段默认的值为:
'AutoField': 'integer AUTO_INCREMENT',
'BigAutoField': 'bigint AUTO_INCREMENT',
'BinaryField': 'longblob',
'BooleanField': 'bool',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'DurationField': 'bigint',
'FileField': 'varchar(%(max_length)s)',
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'double precision',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'char(15)',
'GenericIPAddressField': 'char(39)',
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'UUIDField': 'char(32)', BooleanField(Field)
- 布尔值类型 NullBooleanField(Field):
- 可以为空的布尔值 CharField(Field)
- 字符类型
- 必须提供max_length参数, max_length表示字符长度 TextField(Field)
- 文本类型 EmailField(CharField):
- 字符串类型,Django Admin以及ModelForm中提供验证机制 IPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 GenericIPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
- 参数:
protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both" URLField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证 URL SlugField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) CommaSeparatedIntegerField(CharField)
- 字符串类型,格式必须为逗号分割的数字 UUIDField(Field)
- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 FilePathField(Field)
- 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
- 参数:
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹 FileField(Field)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage ImageField(FileField)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
width_field=None, 上传图片的高度保存的数据库字段名(字符串)
height_field=None 上传图片的宽度保存的数据库字段名(字符串) DateTimeField(DateField)
- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin, Field)
- 日期格式 YYYY-MM-DD TimeField(DateTimeCheckMixin, Field)
- 时间格式 HH:MM[:ss[.uuuuuu]] DurationField(Field)
- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 FloatField(Field)
- 浮点型 DecimalField(Field)
- 10进制小数
- 参数:
max_digits,小数总长度
decimal_places,小数位长度 BinaryField(Field)
- 二进制类型 字段

字段类型

null                数据库中字段是否可以为空
db_column 数据库中字段的列名
default 数据库中字段的默认值
primary_key 数据库中字段是否为主键
db_index 数据库中字段是否可以建立索引
unique 数据库中字段是否可以建立唯一索引
unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引
unique_for_month 数据库中字段【月】部分是否可以建立唯一索引
unique_for_year 数据库中字段【年】部分是否可以建立唯一索引 auto_now 无论是你添加还是修改对象,时间为你添加或者修改的时间。
auto_now_add 为添加时的时间,更新对象时不会有变动
想要在添加数据时更新时间要用:
obj=UserGroup.objects.filter(id=1).first()
obj.caption="CEO"
obj.save()
如果使用:
obj=UserGroup.objects.filter(id=1).update(caption="CEO")则不会更新
verbose_name Admin中显示的字段名称
blank Admin中是否允许用户输入为空
editable Admin中是否可以编辑
help_text Admin中该字段的提示信息
choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息;
字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
如:{'null': "不能为空.", 'invalid': '格式错误'} validators 自定义错误验证(列表类型),从而定制想要的验证规则
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
如:
test = models.CharField(
max_length=32,
error_messages={
'c1': '优先错信息1',
'c2': '优先错信息2',
'c3': '优先错信息3',
},
validators=[
RegexValidator(regex='root_\d+', message='错误了', code='c1'),
RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
EmailValidator(message='又错误了', code='c3'), ]
)

参数

b.注册app

settings:添加要创建表的app

  

c.执行命令

python manage.py makemigrations

python manage.py migrate   这样就自动把表创建下来了

d.注意:django内部默认用的是sqlite

如果需要使用mysql,django默认用的是mysqldb这个模块,我们要导入

a.主动修改为pymysql.在project同名的文件夹下的__init__文件中添加如下代码:

import pymysql
pymysql.install_as_MySQLdb()

b.修改settings.py

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'dbname',
'USER': 'root',
'PASSWORD': 'xxx',
'HOST': '',
'PORT': '',
}
}

创建之后如下图显示:

2.根据类对数据库中的数据进行各种操作  

创建数据:

#创建数据
第一种方式: models.UserInfo.objects.create(username='root',password='',) 第二种方式:
dic = {'username':'xiaoming','password':''}
models.UserInfo.objects.create(**dic) 第三种方式:
obj=models.UserInfo(username='root1',password='')
obj.save()

查找数据:

#查找所有数据
result = models.UserInfo.objects.all()
for row in result:
print(row.id,row.username,row.password)
#普通的条件查询
result = models.UserInfo.objects.filter(username='root',password='')
for row in result:
print(row.id,row.username,row.password)
result = models.UserInfo.objects.all().values('id','username')#这个返回的就是字典,比如[{'id':1,'username':'xiaoming'},{'id':2,'username':'xiaohong'}]
result = models.UserInfo.objects.all().value_list('id','username')#返回的内部是一个元组[(1,'xiaoming'),(2,'xiaohong')]
result = models.UserInfo.objects.get(id=1)#获得到一个对象,如果不存在就报错
对象或者None = models.UserInfo.objects.filter(id=1).first()
result = models.UserInfo.objects.filter(id__gt=1)>
result = models.UserInfo.objects.filter(id__it=1)<
result = models.UserInfo.objects.filter(id__gte=1)>=
result = models.UserInfo.objects.filter(id__lte=1)<=

删除数据

#删除所有数据
models.UserInfo.objects.all().delete()
#按条件查询
models.UserInfo.objects.filter(id=4).delete()

更新数据

#更新所有数据
models.UserInfo.objects.all().update(password='')
#按条件更新数据
models.UserInfo.objects.filter(id=3).update(password='')

一对多:

  a.外键

b = models.ForeignKey(to='Business',to_field='id',on_delete=models.CASCADE)
                                  - models.CASCADE,删除关联数据,与之关联也删除
           - models.DO_NOTHING,删除关联数据,引发错误IntegrityError
           - models.PROTECT,删除关联数据,引发错误ProtectedError
           - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
            - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
            - models.SET,删除关联数据,
     a. 与之关联的值设置为指定值,设置:models.SET(值)
     b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)

  b.生成在数据库的字段为外键字段_id

  c.创建数据的时候就根据这个id来创建就可以了

  d.取数据

v1 = models.Host.objects.filter(nid__gt=0)
v[0].b.caption ---> 通过.实现跨表

 如果想要在查询的时候获取多表的字段就要用双下划綫

v1 = models.Host.objects.filter(nid__gt=0).values('nid','hostname','b_id','b__caption')返回的还是一个字典,
取值:for row in v1:
    print(row['nid'],row['hostname'],row['b_id'],row['b__caption'])
在模板中:
    {{ row.b__caption }}

 那么我们能够在host通过外键查询到Bussiness中的数据,那能不能在Business表中反向查询到host中的数据呢?(反向查询) 

  虽然两张表没有在host中体现出来关联,只要用表名_set,就可以找到Business中的数据了

多对多:

 创建多对多:

方式一:自定义关系表
class Host(models.Model):
nid = models.AutoField(primary_key=True)
hostname = models.CharField(max_length=32,db_index=True)
ip = models.GenericIPAddressField(protocol='ipv4',db_index=True)
port = models.IntegerField()
b = models.ForeignKey(to='Business',to_field='id',on_delete=models.CASCADE) class Application(models.Model):
name = models.Char Field(max_length=32) class HostToApp(models.Model):
hobj = models.ForeignKey(to='Host',to_field='nid',on_delete=models.CASCADE)
aobj = models.ForeignKey(to='Application',to_field='id',on_delete=models.CASCADE) 方式二:自动创建关系表(默认生成3列)
class Host(models.Model):
nid = models.AutoField(primary_key=True)
hostname = models.CharField(max_length=32,db_index=True)
ip = models.GenericIPAddressField(protocol='ipv4',db_index=True)
port = models.IntegerField()
b = models.ForeignKey(to='Business',to_field='id',on_delete=models.CASCADE) class Application(models.Model):
name = models.CharField(max_length=32)
r = models.ManyToManyField('Host')

方式二创建之后我们看数据库:多了一张表叫做app01_application_r,相当于写了两个类,创建了三张数据表

我们看一下里面的字段:里面有两个字段一个是application_id,一个是host_id,自动创建外键

第二种创建多个外键的方法的缺点:

  • 只能够创建3个字段,如果想要在添加另外表的外键就不可以了
  • 无法直接的向创建的外键表添加字段,即无法使用models.表名.objects.create()

那我们怎么为这个第三张表创建数据呢?

首先我们先查找到application表id为1:

obj  = Application.objects.get(id = 1)

增加数据:

obj.r.add(1)      obj.r.add(2)           obj.r.add(2,3,4)     obj.r.add(*[1,2,3,4])

删除数据:

obj.r.remove(1)       obj.r.remove(2,4)        obj.r.remove(*[1,2,3])

清除所有application_id为1的数据:

obj.r.clear()

更新数据

obj.r.set([3,5,7])数据库中只会存在1,3;1,5;1,7三组数据,其他的都被删除

查询数据

obj.r.all()返回的是QuerySet类型的列表

最新文章

  1. VS2010 ERROR:c1xx fatal error c1083
  2. Android自定义Dialog
  3. httpclient4.3.6/httpcore-4.4自己封装的工具类
  4. Android——Gallery 图片拖动效果
  5. Keil MDK Code、RO-data、RW-data、ZI-data数据段
  6. fadein()
  7. VS2015中的项目类图
  8. 《深入理解Java虚拟机》学习笔记之类加载
  9. GPU 实现 RGB -- YUV 转换 (OpenGL)
  10. 【转】shell学习笔记(六)——流程控制之for循环
  11. Java发布webservice应用并发送SOAP请求调用
  12. Python_subprocess模块
  13. 【C++ 模板迭代器实例/半素数】
  14. vue-router 注意事项
  15. 转:JAVA中解决Filter过滤掉css,js,图片文件等问题
  16. 关于HTTP_USER_AGENT
  17. python使用函数作为参数
  18. 移动端真机调试抓包,fiddler web debugger
  19. 六,ESP8266 TCP Client(基于Lua脚本语言)
  20. sessionId与cookie 的关系(百度文库)

热门文章

  1. ios 10.3下载 Xcode8配置支持 ios 10.3下载
  2. 【剑指offer-25】合并两个单调递增的链表,C++实现(链表)
  3. 一步步搭建自己的web服务器
  4. 每天一个linux命令:【转载】ls命令
  5. Spring 管理Filter和Servlet
  6. 使用不安全代码将 Bitmap 位图转为 WPF 的 ImageSource 以获得高性能和持续小的内存占用
  7. CnetOS7使用yum方式安装nginx
  8. C#连接数据库以及增、删、改、查操作
  9. ubuntu ftp服务器搭建
  10. {Reship}{Emgu}{vs2010}C#配置Emgu