python知识点博客园_Python的重要知识点汇总2

使用socket 模拟服务器 给 浏览器 发 数据:

1 importsocket2

3 sk =socket.socket()4 sk.bind(('127.0.0.1',8080))5 sk.listen()6

7 while 1:8 conn, addr =sk.accept()9 d = conn.recv(1024)10 #print(d.decode())

11 conn.send(b'HTTP/1.1 200 OK\r\n\r\n') #和 浏览器通信 要遵守 http 协议

12 conn.send(b'

Welcome come to my site!

')13 print('haha')14

15 conn.close()16 sk.close()17

18

19 #http 协议

20 '''

21 GET / HTTP/1.122

23 '''

24 '''

25 HTTP/1.1 200 OK26

27 hello world28 '''

server.py

此时 浏览器 输入 127.0.0.1:8080 就可以访问收到 我们回复的内容了,

Django 常用:

Django 中 对象管理器的 annotate()  和 aggregate()

classQuestion(models.Model):

question_text= models.CharField(max_length = 200)def __str__(self):returnself.question_textclassChoice(models.Model):

question= models.ForeignKey(Question,on_delete=models.CASCADE)

choice_text= models.CharField(max_length = 200)

votes= models.IntegerField(default=0)def __str__(self):return f"Choice: {self.choice_text},Question:{self.question.question_text}"

models for this tutorial

importosimportdjangoimportsys

back=os.path.dirname

BASE_DIR= back(back(os.path.abspath(__file__)))

sys.path.append(BASE_DIR)

os.environ.setdefault('DJANGO_SETTINGS_MODULE','mysite01.settings')

django.setup()if __name__ == '__main__':from blogs importmodels as blogs_modelsfrom django.utils importtimezoneimportfakerfrom datetime importtimedeltafrom django.db.models importCount,Sum,Avg

fake_en= faker.Faker() #english

l1 =[]for _ in range(100): #100个问题

question_text = fake_en.sentence().replace('.','?')

l1.append(

blogs_models.Question(question_text=question_text)

)

blogs_models.Question.objects.bulk_create(l1)

l2=[]for _ in range(1000): #1000 个选项

question = blogs_models.Question.objects.order_by("?").first() #随机选出一个问题

choice_text =fake_en.sentence()

votes= fake_en.random_int() #0 -9999

l2.append(

blogs_models.Choice(

choice_text=choice_text,

votes=votes,

question=question,

)

)

blogs_models.Choice.objects.bulk_create(l2)

构建假数据

importosimportdjangoimportsys

back=os.path.dirname

BASE_DIR= back(back(os.path.abspath(__file__)))

sys.path.append(BASE_DIR)

os.environ.setdefault('DJANGO_SETTINGS_MODULE','mysite01.settings')

django.setup()if __name__ == '__main__':from blogs importmodels as blogs_modelsfrom django.utils importtimezoneimportfakerfrom datetime importtimedeltafrom django.db.models importCount,Sum,Avg

manager_question=blogs_models.Question.objects

manager_choice=blogs_models.Choice.objects#1 Number of questions

#cnt = manager_question.count()

#print(cnt)

#2 Number of choices

#cnt = manager_choice.count()

#print(cnt)

#3 Number of choices of per question # 将Count() 注释 到choice_cnt

#ret = manager_question.annotate(choice_cnt = Count('choice'))

#for question in ret:

#print(question.choice_cnt)

#4 Number of choices of per question after filtering on question_text

#ret = manager_question.filter(question_text__startswith='a').annotate( choice_cnt = Count('pk'),)

#for question in ret:

#print(question.choice_cnt)

#5 Number of votes of per question # 每个问题的总票数

#ret = manager_question.annotate(s=Sum('choice__votes'))

#for question in ret:

#print(question.s)

#6 Question with maximum votes # 最大票数(总)的问题

#ret = manager_question.annotate(s=Sum('choice__votes')).filter(

#s__isnull=False

#).order_by('-s').first()

#print(ret)

#print(ret.s)

#7 Question with minimum votes # 最小票数(总)的问题

#ret = manager_question.annotate(s=Sum('choice__votes')).filter(

#s__isnull=False

#).order_by('s').first()

#print(ret)

#print(ret.s)

#8 Question without any choices

#ret = manager_question.annotate(s = Sum('choice__votes')).filter(

#s__isnull = True

#)

#print(ret)

#9 Total votes

#ret = manager_choice.aggregate(_sum = Sum('votes'))

#print(ret) # 是个dict {'_sum': 4884610}

#10 Average votes per choice

#ret = manager_choice.aggregate(_avg = Avg('votes'))

#print(ret) # 是个dict {'_avg': 4884.61}

#10 & 11

#ret = manager_choice.aggregate(_avg = Avg('votes'),_sum = Sum('votes'))

#print(ret) # 是个dict {'_avg': 4884.61, '_sum': 4884610}

#12 Average votes per question

#ret = manager_question.annotate(_avg = Avg('choice__votes'))

#for question in ret:

#print(question,question._avg)

annotate() 和 aggregate() 学习

Django 框架:

简单 web框架:

1 from wsgiref.simple_server importmake_server2 from op_db importgetUserData3 from jinja2 importTemplate4

5 defindex():6 #{'id': 1, 'name': 'tom', 'age': 18}

7 userinfo =getUserData()8 print(userinfo)9 with open("index.html","rb") as f:10 d =f.read()11

12 tpl_str =Template(d.decode())13 ret = tpl_str.render({'data':userinfo})14 returnret.encode()15

16

17 defico():18 with open("favicon.ico","rb") as f:19 d =f.read()20 returnd21

22 defapplication(environ, start_response):23 start_response('200 OK', [('k1','v1'),])24 path = environ['PATH_INFO']25

26 urlpatterns =[27 ('/',index),28 ('/favicon.ico', ico),29 ]30 for i inurlpatterns:31 if i[0] ==path:32 data = i[1]()33 return[data]34

35 if __name__ == '__main__':36 httpd = make_server('127.0.0.1', 8080, application)37 print('Serving HTTP on port 8080...')38 httpd.serve_forever()

简单web 框架

1

2

3

4

5

6

7

hello world

8

9 h1{10 background-color: deeppink;11 }12

13

14

15

你好,{{data['name']}}

16

我今年:{{data['age']}}岁

17

18

哈哈哈哈好

19

哈哈哈哈好

20

哈哈哈哈好

21

哈哈哈哈好

22

哈哈哈哈好

23

哈哈哈哈好

24

哈哈哈哈好

25

26

{{data}}

27

28

29 {% for k,v in data.items() %}30

{{k}}:{{v}}

31 {% endfor %}32

33

34

35

36

index.html

1 importpymysql2

3 defgetUserData():4 conn =pymysql.connect(5 host='127.0.0.1',6 port=3306,7 user='root',8 password='123456',9 database='test',10 charset='utf8'

11 )12 try:13 cursor =conn.cursor(pymysql.cursors.DictCursor)14 cursor.execute('select * from userinfo limit 2;')15 ret =cursor.fetchone()16 conn.commit()17 except:18 conn.rollback()19

20 cursor.close()21 conn.close()22

23 return ret

op_db.py

url 分发:

正则分组,

url 分发 (include  )

视图函数 :

总体上是: FBV (function base view)  和  CBV (class base view)

对FBV  使用 装饰器 判断阻拦请求,

对CBV 可以直接在 dispatch() 函数中 判断阻拦请求 ,也可以在CBV下写 装饰器,不过要借助 django 的

from django.utils.decorators import method_decorator

用时: @method_decorator(dec)

1 from django.shortcuts importrender,redirect2 from django.shortcuts importHttpResponse3

4 #Create your views here.

5 from django.views importView6

7 defhome(request):8 '''

9 项目首页10 :return:11 '''

12 if request.method == 'GET':13

14 pass

15 elif request.method == 'POST':16 pass

17

18

19 return render(request,'home.html')20

21 defapp03_home(request):22 return HttpResponse('这是 app03的首页')23

24 defdec(f):25 def inner(*args,**kwargs):26 #搞事情

27 request =args[0]28 print(request.META)29 ua = request.META['HTTP_USER_AGENT']30 #此时就可以 根据ua 来判断了

31 if 'Chrome' inua:32 #合法

33 ret =f(request)34 returnret35 else:36 return HttpResponse("请求不合法")37

38 returninner39

40 #加装饰器 来判断请求是否合法

41 @dec42 deflogin(request):43 if request.method == 'GET':44 return render(request, 'login.html')45 elif request.method == 'POST':46 username = request.POST.get('username')47 password = request.POST.get('password')48 if username == 'zcb' and password == '123':49 #return HttpResponse('登陆成功') # 跳转到 登陆成功页面

50 #print('suc')

51 #return render(request,'login_success.html') # 这种方式 不太好

52 return redirect('/app03/login_success/')53

54 else:55 return HttpResponse('登陆失败')56 deflogin_success(request):57

58 return render(request,'login_success.html')59

60

61 from django.utils.decorators importmethod_decorator62 #CBV 类的方式 login2

63 classLogin2(View):64 def dispatch(self, request, *args, **kwargs):65 print('请求来了')66 #这里可以先 判断 request 的合法性,如果不合法,就不调用 下面的 方法,

67

68 ret = super().dispatch(request,*args,**kwargs)69 print('请求结束了')70 returnret71

72 #@method_decorator(dec) #CBV 下使用装饰器

73 defget(self,request):74 return render(request,'login2.html')75

76 defpost(self,request):77 username = request.POST.get('username')78 password = request.POST.get('password')79 if username == 'zcb' and password == '123':80 return redirect('/app03/login_success/')81 else:82 return HttpResponse('登陆失败')

给 login(FBV)和 login2(CBV ) 都加上了 装饰器 dec

request 相关:

request.META : ua 等信息都在这,

request.path_info

request.path

request.method

request.GET        --->  .get()  .getlist()

request.POST      --->  .get()  .getlist()

response 相关:

HttpResponse 对象 是回复 字符串,

render() 回复一个页面

redirect()  重定向到一个新的页面,

模板系统 :

https://files.cnblogs.com/files/zach0812/django%E6%A8%A1%E6%9D%BF%E7%B3%BB%E7%BB%9F.zip

关于模板渲染你只需要记两种特殊符号(语法):

{{ }}和 {% %}

变量相关的用{{}},逻辑相关的用{%%}。

万能的 点 .

过滤器( 操作 数据  )| :

标签(逻辑操作 数据 在 {%  %}里操作  ):

模板继承

当有重复代码的时候,使用模板继承 可以省很多 代码,例如 管理的后台页面,

在模板中 加上 {% block % }  槽,

其他 文件中 通过    {%   extends 'filename'      % } 来引入模板,

组件 化

自定义标签和过滤器

如果 内置的 标签(逻辑相关)  和 过滤器(对数据再操作  )  不能满足我们的需求,可以自定义,

在app中创建templatetags模块(模块名只能是templatetags)

创建任意 .py 文件,如:my_tags.py

1 from django import template #导入 文件

2

3 register = template.Library() #创建一个注册器

4 #register 固定的名字

5

6

7 @register.filter8 def zz(val,val2=''): #自定义 过滤器

9 #它的作用是 后面加上 ~ 过滤器的参数最多有两个!!!

10

11 return val + '~'+val212

13 @register.simple_tag #自定义标签

14 def tt(val,val2,val3): #可以传多个参数

15 #它的作用是 后面加上 ~

16 return val + val2+ val3 +'~'

17

18

19 #自定义 组件 标签 (作用 是 先将 test.html 渲染好之后,直接作为组件使用)

20 @register.inclusion_tag('test.html')21 deffunc(val):22

23 data = [11,22,33]24 data.append(val)25

26 return {'data':data}

my_filter_tags.py

1

我去

2

3 {% for d in data %}4

{{ d }}

5 {% endfor %}6

test.html

1

2

3

4

5

6

7

hello world

8

9

10 {% load my_filter_tags %}

11 {#

欢迎{{ name | zz }} 来到登陆页面

#}

12

欢迎{{ name | zz:'~' }} 来到登陆页面

13

14 {% tt name name name %}

15 {% func 44 %}

16

17

18 {% csrf_token %}19 用户名:

20 密 码:

21

22

23

24

25

login.html 这里是用到自定义标签 和 过滤器的地方

静态文件:

把一些  css,js ,jpg .mp4 等文件  加进来, 当服务器请求 这些 .css 等文件的时候,django 就会自动的读取 发送给浏览器,

引入时:

ORM --- 单表查询 :

1 from django.db importmodels2

3 #Create your models here.

4

5 classStudent(models.Model):6 #id = models.AutoField(primary_key=True) # 默认的

7 name = models.CharField(max_length=16)8 age =models.IntegerField()9 date = models.DateField(null=True) #该字段允许 为空

10

11

12

13 def __str__(self):14 #当print (self) 的时候 就会 调用 self.__str__()

15 return self.name

models.py

1 from django.shortcuts importrender,redirect,HttpResponse2

3 #Create your views here.

4 from app01 import models #利用orm 操作数据库

5

6 defindex(request):7 #增

8 '''

9 # 创建 记录方式110 stu = models.Student(name='tom',age=18)11 stu.save()12

13 # 创建 记录方式214 # models.Student.objects # 可理解 可通过objects来增删 改查,15 new_obj = models.Student.objects.create(name='e',age=10)16 print(new_obj) # Student object17 print(new_obj.name)18 print(new_obj.age)19 '''

20

21 #增 --- 批量 插入

22 '''

23 objs = []24 for i in range(30): # 30个记录25 obj = models.Student(26 name = 'tom%s'%i,27 age = 10 + i,28 )29 objs.append(obj)30 models.Student.objects.bulk_create(objs) # 速度快31 '''

32

33 #增 --- update_or_create 有就 更新 无则创建

34 '''

35 models.Student.objects.update_or_create(36 name='jack', # 如果有 name 的话,就 改 为下面 的默认值 ,如果没 的话 ,就创建.37 defaults={38 'age':4039 }40 )41

42 '''

43

44

45 #简单 查询

46 '''

47 # 简单 查询之 ---查询 所有的 数据48 all_objs = models.Student.objects.all()49 print(all_objs) # QuerySet 类型 类似列表50 for obj in all_objs:51 print(obj.name)52 # 简单 查询之 --- filter 返回的 QuerySet QuerySet 对象也可以调用 filter()53 # 条件 查询 数据 filter() # 查询失败 不报错,返回为 空。54 objs = models.Student.objects.filter(id=8); # id 为8 的记录55 print(objs)56

57 # 简单 查询之 --- get返回的 model 对象 (Student 对象 )58 # 条件 查询 数据 get() 而且 get() 方法有且只有 一个结果,多了少了 都报错 。59 objs = models.Student.objects.get(id=8);60 print(objs)61

62 '''

63

64 #删除 delete

65 '''

66 # 通过 stu 对象 来调用删除67 # models.Student.objects.get(id=7).delete() # 需要先把它查出来,然后再删除68

69 # 通过 QuerySet 对象 来调用删除70 # models.Student.objects.filter(id=8).delete()71

72 # models.Student.objects.all().delete() # 删除 表中 所有的数据73 '''

74

75 #更新

76 '''

77 # stu 对象 不能 update78 # models.Student.objects.get(name='jane').update(age = 38) # stu对象 不能 更新79 models.Student.objects.filter(name='jane').update(age = 38) # QuerySet 对象 可以80 '''

81

82 #更多查询 都是重点

83 #01 多条件 查询,

84 '''

85 sets = models.Student.objects.filter(age=38,name='jane') #条件之间是 and 的关系86

87 # 关键字参数 也可以传个 字典~ 打散传参 要注意 ,key value 都要是 字符串,88 # sets = models.Student.objects.filter(**{'age':38,'name':'jane'}) # 也可以如下格式89 print(sets)90

91

92 # 除了 filter() get 也支持 多条件, 它返回的是 stu 对象 返回结果 有且只能有一个,93 '''

94

95 #02 排除 exclude , 排除 仅仅是 筛选出来 ,并没有删除原有的数据 # objects 和 queryset对象都可以调用

96 '''

97 set = models.Student.objects.exclude(id=9)98 print(set) # 返回的是个 QuerySet 对象99

100 set = models.Student.objects.filter(age=38).exclude(id=9) # 先筛选 再 exclude 两次过滤。101 print(set)102 '''

103

104 #03 排序 orderby 原有数据 没变

105 '''

106 set = models.Student.objects.all().order_by('age','-id') # 意思是 先按 age 升序 ,然后 按id 降序107 print(set) # 默认是升序 ,降序 用 -108 '''

109 #04 反转 reverse # 反转 必须在 order_by 的基础上 来 做 。

110 '''

111 set = models.Student.objects.all().order_by('id').reverse()112 print(set)113 '''

114

115 #05 计数 count

116 '''

117 num = models.Student.objects.all().count() # 查询 之后 结果的 set 的 数量118 print(num)119 '''

120

121 #06 first

122 '''

123 obj = models.Student.objects.all().first() # 返回 结果是 stu 对象124 print(obj)125 '''

126

127 #07 last

128 '''

129 obj = models.Student.objects.all().last() # 返回 结果是 stu 对象130 print(obj)131 '''

132

133

134 #08 exist

135 '''

136 # 它 比 直接 if res: 效率高, exist 只要有一个 符合就返回了,137 flag = models.Student.objects.filter(name='jane').exists() # 返回 bool138 print(flag)139 '''

140

141 #09 values_list 和 values

142 '''

143 set = models.Student.objects.filter(age=38)144 print(set)145

146 set = models.Student.objects.filter(age=38).values_list() # 把所有 values 变为元素返回147 print(set) # 它照样是 set 对象, 但是里面的数据 变为了 元组,148

149 set = models.Student.objects.filter(age=38).values_list('name','age')150 print(set)151

152 set = models.Student.objects.filter(age=38).values()153 print(set) # 里面变为 了字典 values_list 和 values 相当于 pymysql 中的 游标中的 元组 和 字典 ~154 set = models.Student.objects.filter(age=38).values('name','age')155 print(set)156 '''

157

158 #10 去重 主要用在 values_list 和 values 后 ; 因为如果是all(),filter() 都包含 id ,而id 是肯定不会重复的

159 '''

160 set = models.Student.objects.values_list('age').distinct().count()161 print(set)162 '''

163

164 #11 基于双下划线 的模糊查询 相当于 数据库 like

165 #set = models.Student.objects.filter(id>20) # 这种写法是错误的, 不支持 大于

166 #大于

167 set = models.Student.objects.filter( id__gt = 20 ) #此时id > 20

168 print(set)169

170 #大于等于 gte

171 #小于 lt

172 #小于等于 lte

173

174 #在... 里面 in

175 set = models.Student.objects.filter( id__in = [20,22,30] ) #在 后面三个中的 都要

176 print(set)177

178 #range [] 左右 都闭区间

179 set = models.Student.objects.filter(age__range=[18,30])180 print(set)181

182 #包含 contains 该字段 必须要是 字符串

183 set = models.Student.objects.filter(name__contains='tom') #默认区分大小写

184 print(set)185

186 set = models.Student.objects.filter(name__icontains='tom') #i 不区分大小写

187 print(set)188

189 #以 ... 开头 startswith

190 set = models.Student.objects.filter(name__startswith='ja')191 print(set)192

193 #以 ... 结尾 endswith

194 set = models.Student.objects.filter(name__endswith='e')195 print(set)196

197 #查询 与日期相关 比较重要~

198 set = models.Student.objects.filter(date='2000-11-11')199 print(set)200 set = models.Student.objects.filter(date__year='2000')201 print(set)202 set = models.Student.objects.filter(date__year='2000',date__month='12')203 print(set)204 set = models.Student.objects.filter(date__year='2000',date__month='12',date__day='8')205 print(set)206 #查看 大于 2000-12-8

207 set = models.Student.objects.filter(date__year='2000',date__month='12',date__day__gt='8')208 print(set)209

210

211

212 return render(request,'index.html')

views.py

1 """

2 Django settings for orm_pro project.3

4 Generated by 'django-admin startproject' using Django 1.11.9.5

6 For more information on this file, see7 https://docs.djangoproject.com/en/1.11/topics/settings/8

9 For the full list of settings and their values, see10 https://docs.djangoproject.com/en/1.11/ref/settings/11 """

12

13 importos14

15 #Build paths inside the project like this: os.path.join(BASE_DIR, ...)

16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))17

18

19 #Quick-start development settings - unsuitable for production

20 #See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

21

22 #SECURITY WARNING: keep the secret key used in production secret!

23 SECRET_KEY = '9l6_6036bj+*ov$q)yg#p1ny6b8rk(j4z##8+6c)02l2cy@%i3'

24

25 #SECURITY WARNING: don't run with debug turned on in production!

26 DEBUG =True27

28 ALLOWED_HOSTS =[]29

30

31 #Application definition

32

33 INSTALLED_APPS =[34 'django.contrib.admin',35 'django.contrib.auth',36 'django.contrib.contenttypes',37 'django.contrib.sessions',38 'django.contrib.messages',39 'django.contrib.staticfiles',40 'app01.apps.App01Config',41 ]42

43 MIDDLEWARE =[44 'django.middleware.security.SecurityMiddleware',45 'django.contrib.sessions.middleware.SessionMiddleware',46 'django.middleware.common.CommonMiddleware',47 'django.middleware.csrf.CsrfViewMiddleware',48 'django.contrib.auth.middleware.AuthenticationMiddleware',49 'django.contrib.messages.middleware.MessageMiddleware',50 'django.middleware.clickjacking.XFrameOptionsMiddleware',51 ]52

53 ROOT_URLCONF = 'orm_pro.urls'

54

55 TEMPLATES =[56 {57 'BACKEND': 'django.template.backends.django.DjangoTemplates',58 'DIRS': [os.path.join(BASE_DIR, 'templates')]59 ,60 'APP_DIRS': True,61 'OPTIONS': {62 'context_processors': [63 'django.template.context_processors.debug',64 'django.template.context_processors.request',65 'django.contrib.auth.context_processors.auth',66 'django.contrib.messages.context_processors.messages',67 ],68 },69 },70 ]71

72 WSGI_APPLICATION = 'orm_pro.wsgi.application'

73

74

75 #Database

76 #https://docs.djangoproject.com/en/1.11/ref/settings/#databases

77

78 DATABASES ={79 'default': {80 'ENGINE': 'django.db.backends.mysql',81 'HOST':'127.0.0.1',82 'PROT':3306,83 'NAME':'orm01',84 'USER':'root',85 'PASSWORD':'123456',86 }87 }88

89

90 #Password validation

91 #https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

92

93 AUTH_PASSWORD_VALIDATORS =[94 {95 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',96 },97 {98 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',99 },100 {101 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',102 },103 {104 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',105 },106 ]107

108

109 #Internationalization

110 #https://docs.djangoproject.com/en/1.11/topics/i18n/

111

112 LANGUAGE_CODE = 'en-us'

113

114 TIME_ZONE = 'UTC'

115

116 USE_I18N =True117

118 USE_L10N =True119

120 USE_TZ =True121

122

123 #Static files (CSS, JavaScript, Images)

124 #https://docs.djangoproject.com/en/1.11/howto/static-files/

125

126 STATIC_URL = '/static/'

127

128

129

130

131

132

133

134

135

136

137

138 #如果想打印orm转换过程中的sql,需要在settings中进行如下配置

139 #LOGGING = {

140 #'version': 1,

141 #'disable_existing_loggers': False,

142 #'handlers': {

143 #'console':{

144 #'level':'DEBUG',

145 #'class':'logging.StreamHandler',

146 #},

147 #},

148 #'loggers': {

149 #'django.db.backends': {

150 #'handlers': ['console'],

151 #'propagate': True,

152 #'level':'DEBUG',

153 #},

154 #}

155 #}

setttings.py

修改后端数据 切换页面   时,可以通过绑定事件,然后 location.href ,

但是,麻烦,可以通过 a标签,它可以帮我们自动 发请求,

django批量操作 models中的表到 admin 中:

1 from django.contrib importadmin2

3 #Register your models here.

4 from app01 importmodels5

6 for table in models.__all__: #table 就是个字符串

7 ifhasattr(models,table):8 admin.site.register(getattr(models,table))

View Code

django 中 使用外面的脚本 批量导入到数据库 中数据:(外部文件  操作django 的models  )

1 #外部 文件使用 djjango 的models, 需要配置 django 环境 (模仿 manage.py )

2 importos3 if __name__ == '__main__':4 #===============配置=================

5 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_pro.settings")6 importdjango7 django.setup()8 #================================

9

10 from app01 importmodels11 obj_lists =[]12 for i in range(50):13 obj =models.Books(14 name='葵花宝典第%s式'%i,15 price = 20+i,16 date ='1980-12-11',17 press_name= '人民日报出版社'

18 )19 obj_lists.append(obj)20

21 models.Books.objects.bulk_create(obj_lists)

脚本批量导入数据库数据.py

url 别名  和 反向解析:

views.py 中要导入  reverse

url 路由 的时候 要用name 关键字 起个别名,  以后可以一直用这个别名,

起了别名之后,以后,修改 前面的请求路径 也 不用修改面的,因为用了别名,

html 中 也可以使用 url 的别名, 语法: { %   url ' 别名'     %}  ,常用在  a标签 中的 href 属性中,

使用别名 的好处是 以防后面升级  路径时,不用到处更改 路径,

其中 redirect()中,可以直接写 别名,不用 reverse() 也可以,但,只限于 redirect()  ,

善用别名,

善用路径,将后端数据放在路径中,删除数据 ,编辑数据的时候 ,可以通过 a 标签 达到 自动访问数据库的目的,例如 /edit/17  意思是编辑 id 为17 的图书 ,

后端 数据 不要随便从 前端中获取,有可能是错的,

ORM --- 多表 操作  :

创建 django 的admin 用户,

python manager.py createsuperuser

多表操作之 增 删 改:

1 from django.db importmodels2

3 #Create your models here.

4 #作者表

5 classAuthor(models.Model):6 name = models.CharField(max_length=16)7 age =models.IntegerField()8 #authorDetail = models.OneToOneField(to='AuthorDetail',to_field='id',on_delete=models.CASCADE) # 不级联 model.SET_NULL 这时,如果删了的话,外键 就变为NULL了

9 authorDetail_id = models.OneToOneField(to='AuthorDetail') #默认 to_field 是id , django1.x 版本默认是 级联

10 def __str__(self):11 returnself.name12

13

14

15 #作者详情表 # 作者表 和 作者详情表 是一对一的 关系

16 classAuthorDetail(models.Model):17 birthday =models.DateField()18 tele = models.CharField(max_length=32)19 addr = models.CharField(max_length=64)20

21 def __str__(self):22 returnself.addr23

24

25

26 #出版社 表

27 classPress(models.Model):28 name = models.CharField(max_length=32)29 city = models.CharField(max_length=32)30 email = models.EmailField() #实际也是 CharField,不过它可以帮我们 校验 是否是邮箱

31

32 def __str__(self):33 returnself.name34

35

36

37 #书籍表 和 作者是多对多的关系

38 #书籍表 和 出版社 这里认为是一对多关系 (一个出版社 出版多本书 )

39 classBook(models.Model):40 title = models.CharField(max_length=32)41 publishDate =models.DateField()42 price =models.FloatField()43 #price = models.DecimalField(max_digits=5,decimal_places=2) # 5位整数,2位小数

44

45 press_id = models.ForeignKey(to='Press',on_delete=models.CASCADE) #关联到 出版社 表 ,

46

47 author = models.ManyToManyField(to='Author') #不是真实的字段,可以通过它操作第三张表 ,它 只是自动帮我们创建第三张表( 下面的 )

48

49 def __str__(self):50 returnself.title51

52 #class BookToAuthor(models.Model): # 多对多的关系 用第三张 表

53 #book_id = models.ForeignKey(to='Book')

54 #author_id = models.ForeignKey(to='Author')

models.py

1 """orm_pro URL Configuration2

3 The `urlpatterns` list routes URLs to views. For more information please see:4 https://docs.djangoproject.com/en/1.11/topics/http/urls/5 Examples:6 Function views7 1. Add an import: from my_app import views8 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')9 Class-based views10 1. Add an import: from other_app.views import Home11 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')12 Including another URLconf13 1. Import the include() function: from django.conf.urls import url, include14 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))15 """

16 from django.conf.urls importurl17 from django.contrib importadmin18

19 from app01 importviews20 urlpatterns =[21 url(r'^admin/', admin.site.urls),22

23

24 url(r'^query/',views.query)25

26 ]

urls.py

1 from django.shortcuts importrender,redirect,HttpResponse2

3 #Create your views here.

4 from app01 import models #利用orm 操作数据库

5 from django.urls import reverse #可以反向解析 url 的别名

6

7 defquery(request):8 #一对一 操作多表 操作 author 表 和 authordetail表

9 #增 (一种是 对象 一种是属性 )

10 '''

11 author_detail_obj = models.AuthorDetail.objects.create(12 birthday='1998-10-10',13 tele='188888888889',14 addr='黑龙江哈尔滨'15 )16 # 添加方式1 用属性 = 类对象的方式17 models.Author.objects.create(18 name='m万涛',19 age = 40,20 authorDetail_id=author_detail_obj # 这是类的属性21 )22 '''

23 '''

24 # 常用25 # 添加方式2 用 表字段 = 查询结果 方式26 obj = models.AuthorDetail.objects.filter(addr='山西临汾').first()27 # print(obj.id)28

29 models.Author.objects.create(30 name='m狗蛋',31 age=24,32 authorDetail_id_id = obj.id # 这是 数据库表中的 字段33 )34 '''

35 #删

36 '''

37 models.AuthorDetail.objects.get(id=1).delete() #删它 会删 author ,然后会删 author_book 表 --> 牵一发而动全身38 '''

39 #改

40 #models.Author.objects.get() # 不能用get 它得到的对象是 author 没有update()

41 '''

42 models.Author.objects.filter(id=2).update(43 name='德刚2',44 age=38,45 authorDetail_id_id = 6,46 # authorDetail_id = models.AuthorDetail.objects.get(id=6)47 )48 '''

49

50 #查

51

52 #一对多 操作多表 press 和 book 是一对多的关系 一本书 只能 由一个出版社

53 #增

54 '''

55 models.Book.objects.create(56 title = '李刚的辛福生活',57 publishDate='2009-10-10',58 price= 121,59 # press_id= models.Press.objects.create(name='幸福出版社',city='北京',email='1001@xx.com'),60 # press_id= models.Press.objects.get(id=1),61

62 # 常用63 # press_id_id= models.Press.objects.get(id=1).id,64 press_id_id = 1 # 外键的时候, 这四种方式都可以65 )66 '''

67

68

69 #删 和一对一的删除一样,

70 #models.Press.objects.get(id=1).delete()

71

72 #改

73 '''

74 models.Book.objects.filter(id=8).update(75 title='钢铁之翼2',76 # press_id_id =2,77 press_id = models.Press.objects.get(id=2)78 )79 '''

80

81 #查

82

83 #多对多 操作多表 author 和 book 表

84 #增

85 '''

86 # 常用87 book_obj = models.Book.objects.get(id=1)88 # book_obj.author # 使用 Book 中的author 属性来添加多对于的记录89 book_obj.author.add(*[1,2]) # book_id 1 的author 有两个 1 和 290 # book_obj.author.add(*[1, 2,3]) # book_id 1 的author 有三个 1,2,391 '''

92

93 '''

94 # 先找到 两个作者95 author1 = models.Author.objects.get(id=1)96 author2 = models.Author.objects.get(id=2)97 # 找到 书98 book_obj = models.Book.objects.get(id=3)99 book_obj.author.add(*[author1,author2])100 '''

101

102 #删 就是删除第三张 表

103 '''

104 # 首先要找到 这个表 ,通过 Book 中的 author 属性105 book_obj = models.Book.objects.get(id=9)106 # book_obj.author.remove(3) # remove 写的是对应的 author id107 book_obj.author.remove(*[3,5]) #删的是 9 对应的 3,5108

109 # book_obj.author.clear() # 删的是 book 9 对应的所有 author110 # book_obj.author.set('4') # 将id book 9 对应的author id修改为 4 设置为1个111 # book_obj.author.set(['2','3']) # 将id book 9 对应的author id修改为 4和 6 设置为多个112 '''

113 #改

114 '''

115 多对多的 更改 就是 上面 删除中的 set116 '''

117

118 #查

119

120 return HttpResponse('ok')121 pass

views.py

级联的时候,orm   没有   级联更新,有级联删除,

多表操作之 查:

多表查询,无论是 基于 对象 还是基于双下划线,它们都有  正向查询 和 反向查询 ,

就看外键那个属性写在哪,从  有 外键的表 查 叫:正向 , 反之,反向查询,

1,基于对象 的跨表 查询 (类似于    子查询  )

2,基于双下划线的 跨表查询 (类似于连表   join 连接  )

related_name  &  related_query_name:

oto :

related_name : 默认情况下是外键字段所在class 的名字!

related_query_name: 默认情况下是外键字段所在class 的名字!

如果一个表的不同字段同时关联到同一个表,此时要注意自定义related_name,related_query_name

mto :

related_name : 默认情况下是外键字段所在class 的名字+_set

related_query_name: 默认情况下是外键字段所在class 的名字!

如果一个表的不同字段同时关联到同一个表,此时要注意自定义related_name,related_query_name

mtm : # 当不自定义 第三张表的时候

related_name : 默认情况下是外键字段所在class 的名字+_set

related_query_name: 默认情况下是外键字段所在class 的名字!

如果一个表的不同字段同时关联到同一个表,此时要注意自定义related_name,related_query_name ,自定义的名字直接替代默认的(包含_set)

mtm : # 当自定义 第三张表的时候 (不太准确 参见fd_project/bootstrap4_project/wms3 工程)

related_name : 默认情况下是外键字段所在class 的名字(在第三张表)+_set(在第三张表)

related_query_name: 默认情况下是外键字段所在class 的名字(在第三张表)+__外键字段

如果一个表的不同字段同时关联到同一个表,此时要注意自定义related_name,related_query_name 自定义的名字直接替代默认的(包含_set),但是related_query_name 时要+ __外键字段

View Code

related_name 用自己去获取相关的数据!

related_query_name 是用相关的数据filter自己!

聚合 函数使用    :

from django.db.models import Avg,Max,Min,Sum,Count

补充:‘12’.isdigit( ) 不好,它全识别,使用  '12'.isdecimal()

分组 查询  :

group by  分组 就是为了 统计信息,

以及 分组后的   having

F查询   和  Q查询 :

orm (mysql)的坑(orm 不能解决):

分组导致的,  分组之后取 其他字段 会导致数据有问题,

如果分组,select 只能 select groupby 后的字段  和  统计的结果,其他字段都是无意义的,

只有如下可以:

如果是实在想要其他字段,orm 解决不了 了,

原生sql 可以解决:

先不分组, 先连接,连接之后,首先按照 price 降序排列,使得价格最大的在第一行,(这样就避免了后面 分组时候的错误),

连接之后:

先按price 降序排序:如下:

然后,如果 max() 取数据,其他数据也都是在第一行的,就不会有错了,

最终如下:

1 select title,price from

2 (3 select app01_author.id,app01_book.title,app01_book.price fromapp01_author4 INNER JOIN app01_book_author on app01_author.id=app01_book_author.author_id5 INNER JOIN app01_book on app01_book.id=app01_book_author.book_id6 ORDER BY app01_book.price desc

7 ) asb8 GROUP BY id

View Code

注:sql_mode 非常重要,

1 """orm_pro URL Configuration2

3 The `urlpatterns` list routes URLs to views. For more information please see:4 https://docs.djangoproject.com/en/1.11/topics/http/urls/5 Examples:6 Function views7 1. Add an import: from my_app import views8 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')9 Class-based views10 1. Add an import: from other_app.views import Home11 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')12 Including another URLconf13 1. Import the include() function: from django.conf.urls import url, include14 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))15 """

16 from django.conf.urls importurl17 from django.contrib importadmin18

19 from app01 importviews20 urlpatterns =[21 url(r'^admin/', admin.site.urls),22

23 url(r'^query/',views.query)24

25 ]

urls.py

1 from django.db importmodels2

3 #Create your models here.

4 #作者表

5 classAuthor(models.Model):6 name = models.CharField(max_length=16)7 age =models.IntegerField()8 #authorDetail = models.OneToOneField(to='AuthorDetail',to_field='id',on_delete=models.CASCADE) # 不级联 model.SET_NULL 这时,如果删了的话,外键 就变为NULL了

9 authorDetail_id = models.OneToOneField(to='AuthorDetail') #默认 to_field 是id , django1.x 版本默认是 级联

10 def __str__(self):11 returnself.name12

13

14

15 #作者详情表 # 作者表 和 作者详情表 是一对一的 关系

16 classAuthorDetail(models.Model):17 birthday =models.DateField()18 tele = models.CharField(max_length=32)19 addr = models.CharField(max_length=64)20

21 def __str__(self):22 returnself.addr23

24

25

26 #出版社 表

27 classPress(models.Model):28 name = models.CharField(max_length=32)29 city = models.CharField(max_length=32)30 email = models.EmailField() #实际也是 CharField,不过它可以帮我们 校验 是否是邮箱

31

32 def __str__(self):33 returnself.name34

35

36

37 #书籍表 和 作者是多对多的关系

38 #书籍表 和 出版社 这里认为是一对多关系 (一个出版社 出版多本书 )

39 classBook(models.Model):40 title = models.CharField(max_length=32)41 publishDate =models.DateField()42 dianzan_num = models.IntegerField(default=0) #点赞

43 comment_num = models.IntegerField(default=0) #评论 后面又加上的(要么 default= ,要么set_null = True),

44

45 price =models.FloatField()46 #price = models.DecimalField(max_digits=5,decimal_places=2) # 5位整数,2位小数

47

48 #related_name = 'xx' 的意思是 反向查询的时候,不用表名了,用xx即可,

49 #press_id = models.ForeignKey(to='Press',on_delete=models.CASCADE,related_name='xx') # 关联到 出版社 表 ,

50 press_id = models.ForeignKey(to='Press',on_delete=models.CASCADE) #关联到 出版社 表 ,

51

52 author = models.ManyToManyField(to='Author') #不是真实的字段,可以通过它操作第三张表 ,它 只是自动帮我们创建第三张表( 下面的 )

53

54 def __str__(self):55 returnself.title56

57 #class BookToAuthor(models.Model): # 多对多的关系 用第三张 表

58 #book_id = models.ForeignKey(to='Book')

59 #author_id = models.ForeignKey(to='Author')

models.py

1 from django.shortcuts importrender,redirect,HttpResponse2

3 #Create your views here.

4 from app01 import models #利用orm 操作数据库

5 from django.urls import reverse #可以反向解析 url 的别名

6

7 defquery(request):8 #1 基于对象的 多表查询 (类似于 子查询)

9 #一对一 操作多表 操作 author 表 和 authordetail表

10 #查

11 #正向 查询

12 '''

13 author_obj = models.Author.objects.filter(name='超哥').first()14 print(author_obj.authorDetail_id.birthday)15 print(author_obj.authorDetail_id.tele)16 print(author_obj.authorDetail_id.addr)17 '''

18 #反向 查询 通过authorDetail 中 数据 查询 author 的信息

19 '''

20 detail_obj = models.AuthorDetail.objects.get(addr='江西南昌')21 # 具体是 通过小写的 表名22 print(detail_obj.author.name)23 print(detail_obj.author.age)24 print(detail_obj.author.authorDetail_id)25 '''

26

27 #一对多 操作多表 press 和 book 是一对多的关系 一本书 只能 由一个出版社

28 #查

29 #正向查询

30 '''

31 book_obj = models.Book.objects.get(id=7)32 print(book_obj.press_id.name)33 print(book_obj.press_id.city)34 print(book_obj.press_id.email)35 '''

36 #反向查询

37 '''

38 press_obj = models.Press.objects.get(name='幸福出版社')39 # 具体是用 表名_set40 # print(press_obj.book_set.first().title)41 # print(press_obj.book_set.first().publishDate)42 # print(press_obj.book_set.first().price)43 # print(press_obj.book_set.first().press_id)44 for book in press_obj.book_set.all():45 print(book.title)46 print(book.publishDate)47 print(book.price)48 print(book.press_id )49 '''

50

51 #多对多 操作多表 author 和 book 表

52 #查

53 #正向查询 一本书 是 哪几个作者写的

54 '''

55 book_obj = models.Book.objects.get(id=9)56 # 通过 book 中的 author 属性57 print(book_obj.author.all()) #, ]>58 '''

59

60 #反向查询 一个作者 写了 哪几本书

61 '''

62 author_obj = models.Author.objects.get(name='德刚2')63 print(author_obj.book_set.all())64 '''

65

66 #2 基于 双下划綫 的 多表查询 (类似于 join 连接)

67 #一对一 操作多表 操作 author 表 和 authordetail表

68 #查 m狗蛋的地址

69 '''

70 # 正向查询71 # authorDetail_id __ addr 它是先将 author 和 authorDeatail 连接在一起,然后再查 addr72 set = models.Author.objects.filter(name='m狗蛋').values('authorDetail_id__addr','age')73 print(set) # 查找 addr 时 连表74 # 通过使用小写的 表名75 # 反向查询76 set = models.AuthorDetail.objects.filter(author__name='m狗蛋').values('addr','author__age')77 print(set) # 查找 addr 前 连表78 '''

79

80 #查 地址为 江西南昌 作者的名字

81 '''

82 # 正向查询83 set = models.Author.objects.filter(authorDetail_id__addr='江西南昌').values('name','authorDetail_id__birthday')84 print(set)85 # 反向查询86 set = models.AuthorDetail.objects.filter(addr='江西南昌').values('author__name','tele')87 print(set)88 '''

89 #查 电话 为 222222222 的作者的 名字

90 '''

91 # 正向查询92 set = models.Author.objects.filter(authorDetail_id__tele='222222222').values('name')93 print(set)94 # 反向查询95 set = models.AuthorDetail.objects.filter(tele='222222222').values('author__name')96 print(set)97 '''

98

99 #一对多 操作多表 press 和 book 是一对多的关系 一本书 只能 由一个出版社

100 #查 李刚的辛福生活 书 的出版社 是哪个?

101 '''

102 # 正向查询 有外键的 用外键 连接, 无外键的 用 表名小写连接,103 set = models.Book.objects.filter(title='李刚的辛福生活').values('press_id__name')104 print(set)105 # 反向查询106 set = models.Press.objects.filter(book__title='李刚的辛福生活').values('name')107 print(set)108 '''

109 #查 b哥出版社 都出版了 哪些书

110 '''

111 # 正向查询112 set = models.Book.objects.filter(press_id__name='b哥出版社').values('title')113 print(set)114 # 反向查询115 set = models.Press.objects.filter(name='b哥出版社').values('book__title')116 print(set)117 '''

118

119

120 #多对多 操作多表 author 和 book 表

121 #查 李刚的辛福生活 是谁写的

122 '''

123 # 正向查询124 set = models.Book.objects.filter(title='李刚的辛福生活').values('author__name')125 print(set)126 # 反向查询127 set = models.Author.objects.filter(book__title='李刚的辛福生活').values('name')128 print(set)129 '''

130

131 #查 m狗蛋 写了 哪些书

132 '''

133 # 正向查询134 set = models.Book.objects.filter(author__name='m狗蛋').values('title')135 print(set)136 # 反向查询137 set = models.Author.objects.filter(name='m狗蛋').values('book__title')138 print(set)139 '''

140 #3 基于 双下划綫 的 进阶查询

141 #查 b哥出版社 , 出版的书 的名称 以及作者的名称 # press author --> press --book --author

142 #三张表

143 #推荐第一种

144 '''

145 set = models.Press.objects.filter(name='b哥出版社').values('book__title','book__author__name')146 print(set)147

148 set = models.Book.objects.filter(press_id__name='b哥出版社').values('title','author__name')149 print(set)150

151 set = models.Author.objects.filter(book__press_id__name='b哥出版社').values('book__title','name')152 print(set)153 '''

154

155

156 #聚合 函数

157 '''

158 from django.db.models import Avg,Max,Min,Sum,Count159 # 算所有书 的平均价格160 # price = models.Book.objects.all().aggregate(Avg('price')) # aggregate() 返回的是个字典161 res = models.Book.objects.all().aggregate(a = Avg('price')) # a 会覆盖默认的键162 print(res)163

164 res = models.Book.objects.all().aggregate(Max('price'),Sum('price'),Count('price'))165 print(res)166 '''

167

168 #分组查询

169 from django.db.models importAvg,Min,Max,Count,Sum170 #一种写法

171 '''

172 # 查 每个出版社 出版书籍 的平均价格 如果用 sql的话: select avg(price) from app01_book group by press_id_id;173 #models.Book.objects.values('press_id_id') #所有出版社的id, 它作为 后面 annotate 时候的 分组条件,174 # models.Book.objects.values('press_id_id').annotate() # 分组175 ret = models.Book.objects.values('press_id_id').annotate(a = Avg('price'),b = Min('price'),c=Max('price'),d=Avg('press_id_id') )176 print(ret)177

178 # 多个 条件分组179 # 以 press_id_id 和 id 为分组条件180 # models.Book.objects.values('press_id_id','id')181

182 ret = models.Book.objects.values('press_id_id','id').annotate(a = Avg('price'))183 print(ret)184 print(ret.filter(a__gt=25)) # 在查出 的结果中再次筛选, 它相当于 having ,group by 之后的 having185 '''

186

187

188 #另一种写法 以press 表为 分组依据,

189 '''

190 # 上面是把 values() 放在了 annotate ()前面 不好理解,191 # models.Press.objects # Press 就是分组条件192 # a 一定要写193 # ret = models.Press.objects.annotate(a = Avg('xx__price')) # xx 是book 的别名, 做了一次连接,194 # print(ret) #, ]>195 ret = models.Press.objects.annotate(a = Avg('xx__price')).values('a') # 同时会将 a 塞到 press 这个表中做为一个字段,196 print(ret)197 '''

198

199

200 #F 函数 和 Q函数

201

202 #F 查询:主要用于 单表中的 字段 的 比较,

203 from django.db.models importF , Q204 #例如查询 book 表中 评论数 大于 点赞赞 书

205 '''

206 ret = models.Book.objects.filter(comment_num__gt=F('dianzan_num'))207 print(ret)208 '''

209

210 #F函数 还支持 四则运算

211 '''

212 ret = models.Book.objects.filter(comment_num__gt=F('dianzan_num') + 10)213 print(ret)214 '''

215 #F 函数的 其他用途

216 '''

217 # 让 book 所有书 的价格 都加 20218 models.Book.objects.all().update(price =F('price') + 20)219 '''

220

221

222 #Q函数 一个表中 的 字段 之间的或者关系,

223 '''

224 # 查 评论数 大于20 并且 点赞数 大于 20225 ret = models.Book.objects.filter(comment_num__gt=20,dianzan_num__gt=20)226 print(ret)227

228 # 查 评论数 大于20 或者 点赞数 大于 20229 ret = models.Book.objects.filter(Q(comment_num__gt=20)|Q(dianzan_num__gt=20))230 print(ret)231 # Q 也支持 & ~232 ret = models.Book.objects.filter(~(Q(comment_num__gt=20)&Q(dianzan_num__gt=20)))233 print(ret)234

235 # Q 也支持嵌套 把 多个条件 括起来,236 ret = models.Book.objects.filter(Q(~(Q(comment_num__gt=20) & Q(dianzan_num__gt=20)))&Q(price__gt=141))237 print(ret)238 '''

239

240

241 #习题 (orm mysql 的坑):

242 #查询 每个作者出版 书的最高价格

243 ret = models.Author.objects.annotate(m = Max('book__price')).values('m')244 print(ret)245 #它对应的原生 sql 是:

246 '''

247 # 连接248 # select * from app01_author249 inner join app01_book_author on app01_author.id = app01_book_author.author_id250 inner join app01_book on app01_book.id = app01_book_author.book_id;251

252 # select app01_author.id, max(app01_book.price) from app01_author253 inner join app01_book_author on app01_author.id = app01_book_author.author_id254 inner join app01_book on app01_book.id = app01_book_author.book_id255 group by app01_author.id;256

257

258 '''

259 #上面还没有 坑,

260 #下面就是 orm 的坑: 分组导致的坑~

261

262 #查 每个作者出版的所有书的最高价格 以及 最高价格的那本书的名称

263 ret = models.Author.objects.annotate( m = Max('book__price')).values('m','book__title')264 print(ret)265 #如果写 肯定是上面这样写, 它是有坑的,

266

267 '''

268 | id | name | age | authorDetail_id_id | id | book_id | author_id | id | title | publishDate | price | press_id_id | comment_num | dianzan_num |269 +----+---------+-----+--------------------+----+---------+-----------+----+-----------------------+-------------+-------+-------------+-------------+-------------+270 | 2 | 德刚2 | 38 | 6 | 8 | 3 | 2 | 3 | 钢铁之翼 | 2020-03-06 | 40 | 2 | 10 | 100 |271 | 2 | 德刚2 | 38 | 6 | 27 | 9 | 2 | 9 | 得当的内心独白 | 2008-10-01 | 220 | 5 | 10 | 40 |272 如果数据如上面, max(price), price字段得到 的是 220 ,但是,其他字段 就没办法取了,只能按照第一行的数据。这 orm 是无法解决的。273

274 mysql 中 可以设置 sql_mode = only_full_group_by ,此时就不能 select * 了,只能 select group by 后的字段 以及统计数据,其他字段无法拿到,275

276

277 总结: 分组之后 拿统计数据才是 有意义的,其他字段 没有任何意义 ~278 '''

279

280 '''

281 # 上述问题,orm 不能解决, 原生sql 可以解决:282 #select title,price from283 (284 select app01_author.id,app01_book.title,app01_book.price from app01_author285 INNER JOIN app01_book_author on app01_author.id=app01_book_author.author_id286 INNER JOIN app01_book on app01_book.id=app01_book_author.book_id287 ORDER BY app01_book.price desc288 ) as b289 GROUP BY id290 '''

291

292

293

294

295 return HttpResponse('ok')

views.py

django 中时间相关:

auto_now 是更新的时候,自动更新时间,  auto_now_add 是创建的时候 加时间,更新时不更新时间,

而且差8小时, 配置: USE_TZ = False

问题:

auto_now_add 没多大问题,auto_now 更新数据的时会有问题,

我们如果用update() 去更新数据,auto_now 是不会帮我们更新时间的,【我们可以自己传入时间 datetime.datetime.now() 手动增加 】(常用)

如果用 obj.name = 'tom3' obj.save() 更新数据时,auto_now 会帮更新时间

时间转化:

ORM --- 锁 和 事务:

行级锁:

select_for_update,

共享锁, 排他锁,

表锁:

事务四大特性:

原子性 , 一致性,持久性,隔离性=  。

Django --- Ajax :

ajax 是js的技术,

这里不再使用 form 和 a  标签来 发送请求了,它是使用 ajax 发送请求,请求结果也是会返回给 ajax 的请求,

前后端 分离的时候用的就是 ajax , js 中的 ajax 就是类似于 python 中的 request ,

登陆认证 只是 ajax 的一个应用,

补:content-type  :

它是前后端 交互的时候的消息格式,

django 默认解析的 content-type 是   urlencoded

如果你发送请求 使用 content-type :application /json 那么,django 就不会帮你解析参数了,需要你自己手动从 请求头中自己  解析,

在做接口的时候,可能会遇到此类问题,

django 还认:  multipart/form-data  上传文件(见下面)用的,django 只认这两种 content-type ,

上传文件:

两种: 1,form 表单 上传文件, 2,ajax 上传文件,

如何将Python 中的 时间日期类型 进行 序列化:

python中的datetime等时间日期类型是不能进行json序列化的,因为json没有对应的格式,此时需要我们自己手动处理:

1 importjson2 from datetime importdatetime3 from datetime importdate4

5 #对含有日期格式数据的json数据进行转换

6 classJsonCustomEncoder(json.JSONEncoder):7 defdefault(self, field):8 ifisinstance(field,datetime):9 return field.strftime('%Y-%m-%d %H:%M:%S')10 elifisinstance(field,date):11 return field.strftime('%Y-%m-%d')12 else:13 returnjson.JSONEncoder.default(self,field)14

15

16 d1 =datetime.now()17

18 dd = json.dumps(d1,cls=JsonCustomEncoder) # 使用的时候,要用cls 关键字 来指定自定义的类,19 print(dd)

1 {% load static %}2

3

4

5

6

7

8

hello world

9

10

11

12

上传文件

13

14

15 {% csrf_token %}16 头像:

17 用户名:

18

19

20

21

upload.html

1 {% load static %}2

3

4

5

6

7

8

hello world

9

10

11

上传文件2

12 文件: {#ajax 上传 不需要 name 属性也可 ajax 需要我们自己写 key value #}

13

14 用户名:

15 上传

16

17

18 $('#btn').click(function () {19 // console.log($('#file')[0].files[0]);20 var form_data =new FormData();21 form_data.append('uname',$('#uname').val());22 form_data.append('file_obj',$('#file')[0].files[0]);23 form_data.append('csrfmiddlewaretoken','{{ csrf_token }}');24

25 $.ajax({26 url:'{% url'upload2'%}',27 type:'post',28 {#data:{#}

29 {#csrfmiddlewaretoken:'{{ csrf_token }}',#}

30 {#uname:$('#uname').val(),#}

31 {#//file_obj: $('#file')[0].files[0] // 直接上传 不可以,ajax 上传数据 需借助formdata#}

32 {##}

33 {#}#}

34 data:form_data,35 processData:false, //不处理数据36 contentType:false, //不设置内容类型 在ajax 上传文件时候 必须写37

38

39 success:function (res) {40 console.log(res);41 }42

43 })44

45 });46

47

48

49

50

51

upload2.html

1 from django.shortcuts importrender,redirect,HttpResponse2

3

4 #Create your views here.

5 from app01 import models #利用orm 操作数据库

6 from django.urls import reverse #可以反向解析 url 的别名

7 from django.http import JsonResponse #做的工作是 添加 content-type: application/json

8

9 defquery(request):10 return HttpResponse('ok')11

12 from django.views importView13

14 defindex(request):15 return render(request,'index.html')16

17 defhome(request):18 if request.method == 'GET':19 all_books =models.Book.objects.all()20 print(all_books)21

22 all_press =models.Press.objects.all()23

24 return render(request,'home.html',{'all_books':all_books,'all_press':all_press})25 else:26 print(request.POST)27

28 return HttpResponse('ok')29

30

31 defdata(request):32 ll = [11,1,1,33,44]33 #在回复 非字典的时候,要加上 safe = False

34 return JsonResponse(ll,safe =False)35

36 #通过form 表单上传文件

37 defupload(request):38 if request.method == 'GET':39 return render(request,'upload.html')40 else:41 print(request.POST) #

42 print(request.FILES) #POST 中放的只是 文件名字,真实的数据 在 request.FILES 中,但是 form 表单中要加: enctype = 'multipart/form-data'

43 #配置好 enctype 中 之后: ]}>

44 #保存到 服务器

45 file_obj = request.FILES.get('head_pic') #file_obj 可以当做是 文件句柄

46 f_name =file_obj.name47

48 from orm_pro importsettings49 importos50 path = os.path.join(settings.BASE_DIR,'static_files','user_img',f_name)51 with open(path,"wb") as f:52 #方式1: 数据是多行的,

53 for i infile_obj:54 f.write(i)55

56 #方式2 :如果数据就只有一行

57 #for i in file_obj.chunks(): # 还是读数据,默认一次 读 64KB ( 只是django 中 )

58 #f.write(i)

59

60

61 return HttpResponse('ok')62

63 #通过 ajax 上传文件

64 defupload2(request):65 if request.method == 'GET':66 print('hhhhhh')67 return render(request,'upload2.html')68 #return render(request,'upload2.html')

69 else:70 print('#================================')71 print(request.POST)72 print(request.FILES)73 file_obj = request.FILES.get('file_obj')74

75 with open(file_obj.name, "wb") as f:76 #方式1: 数据是多行的,

77 for i infile_obj:78 f.write(i)79 #方式2 chunks()

80

81

82 print('#================================')83

84 return HttpResponse('ok')85

86

87

88 importjson89 classLoginView(View):90 defget(self,request):91 return render(request,'login.html')92

93 defpost(self,request):94 #此时是 ajax 请求过来的 不再是 form 了

95 uname = request.POST.get('uname')96 pwd = request.POST.get('pwd')97 if uname == 'zcb' and pwd == '123':98 print("成功")99 #return render(request,'index.html') # ajango 成功之后 返回个首页

100 ret = {'code':0,'msg':'ok','url':'/index/'}101 returnHttpResponse(json.dumps(ret))102 #return HttpResponse(json.dumps(ret),content_type='application/json') # content_type这样之后,ajax收到数据就不用反序列化了

103 #上面一行 还要手动自己写 content_type ,有没有不用自己写的,有, JsonResponse() # from django.http import JsonResponse

104 #直接 return JsonResponse(ret)

105 else:106 #return redirect('/login/') 此时 ajax 不认识 django 的 redirect 的,要想重定向要通过js 的location.href 。

107

108 #应该返回的是 redirect 的url

109 ret = {'code':3,'msg':'用户名或密码错误','url':'/login/'}110 #要返回的应该是 str

111 return HttpResponse(json.dumps(ret))

views.py

1 """orm_pro URL Configuration2

3 The `urlpatterns` list routes URLs to views. For more information please see:4 https://docs.djangoproject.com/en/1.11/topics/http/urls/5 Examples:6 Function views7 1. Add an import: from my_app import views8 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')9 Class-based views10 1. Add an import: from other_app.views import Home11 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')12 Including another URLconf13 1. Import the include() function: from django.conf.urls import url, include14 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))15 """

16 from django.conf.urls importurl17 from django.contrib importadmin18

19 from app01 importviews20 urlpatterns =[21 url(r'^admin/', admin.site.urls),22 url(r'^query/',views.query),23 url(r'^index/',views.index),24 url(r'^home/', views.home,name='home'),25 url(r'^data/', views.data,name='data'),26 url(r'^upload/$',views.upload,name='upload'),27 url(r'^upload2/$',views.upload2,name='upload2'),28 url(r'^login/', views.LoginView.as_view(),name='login'),29

30

31 ]

urls.py

1 {% load static %}2

3

4

5

6

7

8

hello world

9

10

11

12

你好,世界!

13

14

15

16

17 $.ajax({18 url:'{% url'data'%}',19 type:'get',20 success:function (res) {21 console.log(res);22 $.each(res,function (k,v) {23 console.log(k,v);24 /*

25 //1

26 var li = document.createElement('li');27 $(li).text(v);28 $('ul').append(li);29 */

30 //2

31 var s = '

'+v.toString()+'';32 $('ul').append(s);33 })34

35 }36 })37

38

39

40

41

42

home.html

上传文件:  https://files.cnblogs.com/files/zach0812/django_%E4%B8%8A%E4%BC%A0%E6%96%87%E4%BB%B6.zip

django--- cookie 和 session(会话):

http  是不支持持续会话的,

http的两个特性:

1,无连接 (发一次  收一次 , 完事儿~)

2,无状态  (本次连接 结束,下次连接时 不认识对方,), cookie (给http 请求头中加了 cookie )来解决 这个问题,

cookie 是服务端 发来存储在浏览器上的 一组键值对,

为什么会有 session  :

把之前 想发给客户端的 放在 服务端,只给 客户端 发个key ,

现在就是不能直接看到 真实cookie 的真实键值对了,而且存储在服务端, 用户下次访问 要拿着 key 过来访问服务端,

django 中设置session 不再通过 响应对象 来设置了,直接通过request 来设置,

而且django 设置 session 时,会保存到 数据库  django 的内置表  django_session 。

取 加密的cookie 时,

注: 经过网络传输 ,只有 str 一种类型,所以,直接  使用  cookie 时,True  是 str 类型, 如果使用了 session 的话,True 还是 bool 类型,

这个服务端的加密数据,是根据 用户 和浏览器 来生成的 记录,

django 做的事情是:一个浏览器 和一个用户 只给保留一条记录(覆盖), (但是,如果没有session_id(用户主动清除cookie) ,还是会产生新的记录的,没法判断是否是 原来的 浏览器  和  用户了  )

cookie 和 session 里的参数 :

set_cookie() 的参数:

request.session 的一些方法:

views.py 中的 视图函数:

补: django 项目的 配置文件

from django.conf import global_settings  ,可以在 global_settings  配置 key  ,不叫 session_id ,

但是,直接在用户配置文件中 配置即可,

django--- 中间件  (midware):

之前给视图函数加装饰器来判断是用户是否登录,把没有登录的用户请求跳转到登录页面。

我们通过给几个特定视图函数加装饰器实现了这个需求。但是以后添加的视图函数可能也需要加上装饰器,这样是不是稍微有点繁琐。

我们就可以用更适宜的方式来实现类似给所有请求都做相同操作的功能了,就是中间件(就是一个类),

我们在一个固定位置 写个py 文件即可,

把这个配置到 settings.py 即可, 这样所有的请求都会经过我们的这个 process_request()  ,响应走的时候(必须 return response )都会经过 process_response() ,

中间件的一个用途:限制IP 频率, (客户端的 ip 在 request.META 中 ),规则: 例如,10s 之内 只能访问三次,

Django 请求的生命周期:

Django -- form 验证 组件  :

前后端 的认证 都是需要的,

form组件 主要做  数据校验,

views.py :

name  只能 6 到  16 位,

在使用的时候,可以将loginForm 对象 渲染到 HTML 中,

如果使用 form_obj.as_p  会自动 加 label ,label 可以指定 input 的名字, 但是扩展性不好,一般不用 .as_p

django form 表单上传文件:

models.py   中  ImageField(upload)

deftest(request):if request.method == 'GET':

test_form=TestForm(request)return render(request,'zcb.html',{'test_form':test_form})else:

img_obj= request.FILES.get('img')

file_name=img_obj.name

with open('static/xxnaicha/img/'+file_name,'wb') as f:for chunks inimg_obj.chunks():

f.write(chunks)return HttpResponse('ok')

View Code

Django Rest_Framework 组件 :

具体详细项目见 百度网盘,

drf 序列化:

当前端 向服务器请求数据,我们手工 序列化数据很麻烦,尤其当涉及外键关系,需要我们自己自行构建数据结构,

Django自带的序列化组件,不好(外键关系无法处理),from django.core.serializers import serialize

建议使用:  drf( Django Rest_Framework )

APIView csrf 豁免,发送post 请求 比View方便,

1 #构建一个 序列化器

2 classBookSerialize(serializers.Serializer):3 id =serializers.IntegerField()4 title = serializers.CharField(max_length=32)5 CHOICES = ((1,'python'),(2,'linux'))6 #course = serializers.ChoiceField(choices=CHOICES) # 直接这样写 拿到的数据是 前面的 1,2

7 course = serializers.CharField(source='get_course_display') #source 可以执行 一些orm 操作,这时拿到的是 后面的Python 和 linux

source 属性执行 orm 操作

1 from rest_framework.views importAPIView2 from rest_framework importserializers3 from rest_framework.response importResponse4

5 classAuthorSerialize(serializers.Serializer):6 id =serializers.IntegerField()7 name = serializers.CharField(max_length=32) #想要什么字段写什么,写什么就序列化什么

8

9 classPublishSerialize(serializers.Serializer):10 id =serializers.IntegerField()11 name = serializers.CharField(max_length=32)12

13 classBookSerialize(serializers.Serializer):14 id =serializers.IntegerField()15 title = serializers.CharField(max_length=32)16

17 publish = PublishSerialize() #因为一本书只有一个出版社,

18 author = AuthorSerialize(many=True) #因为一本书可能有多个作者 所以 many = True

19

20 classIndex(APIView):21 defget(self,request):22 book_queryset =Book.objects.all()23 ser_obj = BookSerialize(book_queryset,many=True)24 return Response(ser_obj.data)

drf 序列化解决 外键关系

注: 还要把 rest_framework 注册进 settings 里, 如下:

drf  反序列化:

当前端 提交过来一个数据的时候,我们就需要 反序列化了,

假设前端传过来的数据如下:

1 from rest_framework.views importAPIView2 from rest_framework importserializers3 from rest_framework.response importResponse4

5 classAuthorSerialize(serializers.Serializer):6 id =serializers.IntegerField()7 name = serializers.CharField(max_length=32) #想要什么字段写什么,写什么就序列化什么

8

9 classPublishSerialize(serializers.Serializer):10 id =serializers.IntegerField()11 name = serializers.CharField(max_length=32)12

13 classBookSerialize(serializers.Serializer):14 id = serializers.IntegerField(required=False) #required=False 表示 id不用校验

15 title = serializers.CharField(max_length=32)16 CHOICES = ((1,'PYTHON'),(2,'LINUX'))17 course = serializers.CharField(source='get_course_display',write_only=True) #序列化时候 用 ,这是返回字符

18 post_course = serializers.ChoiceField(choices=CHOICES,read_only=True) #反序列化时候 用 ,前端提交过来 数字

19

20 publish = PublishSerialize(write_only=True)21 author = AuthorSerialize(many=True,write_only=True)22

23 post_publish_id = serializers.IntegerField (read_only=True)24 post_author_id = serializers.ListField(read_only=True)25

26 defcreate(self, validated_data):27 #post 提交数据时,orm 操作保存数据

28 book_obj =models.Book.create(29 title=validated_data['title'],30 publish_id = validated_data['post_publish_id'],31 course = validated_data['post_course']32 )33 #处理多对多的关系

34 book_obj.authors.add(*validated_data['post_author_id'])35 return book_obj #一定要 return

36

37

38

39 classIndex(APIView):40 defget(self,request):41 book_queryset =models.Book.objects.all()42 ser_obj = BookSerialize(book_queryset,many=True)43 returnResponse(ser_obj.data)44

45 defpost(self,request):46 book_obj = request.data #相当于 原来 request.POST data中放着除了 GET外的信息 (APIView 封装了下原先的request 并得到了新的request)

47

48 #对前端传来的数据 做校验

49 ser_obj = BookSerialize(data=book_obj)50 ifser_obj.is_valid():51 ser_obj.save()52 returnResponse(ser_obj.data)53 else:54 return Response(ser_obj.errors)

加上 反序列化(前端向后端提交数据)

所有的视图类,

drf    版本控制组件 认证组件  权限控制  频率控制   分页器  解析器 渲染器:

项目见 百度网盘

解析器:

django 中默认content-type 只支持两种 类型,一个是form-data 一个是url-encode

渲染器:

RESTful 规范:

REST 风格: 表述性状态转移,【这个风格只是个建议,】

URI:统一资源标识符,

URL:统一资源定位符, (url 是通过定位实现的URI )

统一资源接口:

根据HTTP请求方式的不同对资源进行不同的操作(get 获取,post新增),

例如:在前后端交互时,不能再addbook,editbook,delbook ,应该直接一个book ,然后根据不同的请求方式 来做不同的逻辑(get获取,post新增,delete删除)

遵循HTTP请求方式的语义(get 就是获取,post就是新增(不能不增),)

遵循 REST风格的就叫 RESTful 规范,

django ContentType组件:

使用ContentType 的好处:

使用ContentType 的步骤:

1,优惠券表中 需要foreignkey 到 ContentType

2,object_id 是所关联到的表的 id

3,GenericForeignKey 两者, 使用对象.就可以直接 找到所要的记录

接口测试 Postman:

开发流程:

功能结构图

原型图

根据功能需求设计表结构( 没有表结构 ER图 ,是 不可以写代码的 )

前后端分离项目 文档十分重要,

数据库表在线设计软件dbdiagram:

三个关系:

# Author oto AuthorInfo   一对一

# Author mtm Book   多对多(其实是 一对多)

# Book mto Publisher 多对一(一对多)

权限:

通过url 来控制 用户的访问,

权限表结构设计 (rbac):

rbac 模式 :role based access control :基于角色 的 权限控制,

动态菜单 展示:

不同的用户 展示 不同的菜单栏,

Django 中间件:

#函数形式的中间件

defsimple_middleware(get_response):defmiddleware(request):#before view

print('before view')

response=get_response(request)#after view

print('after view')returnresponsereturnmiddleware#类形式的 中间件

classSimpleMiddleware:def __init__(self,get_response):

self.get_response=get_responsedef __call__(self,request):#当intance被调用的时候执行,即 self() 时候

#before view

print("before view2")

response=self.get_response(request)#after view

print("after view2")return response

middleware.py

注: 第一个中间件在第二个的前面,

执行的结果是:

before view

before view2

view

after view2

after view

使用Python 发送邮件:

importsmtplib,sslfrom email.mime.text importMIMETextfrom email.header importHeaderfrom email.utils importformataddr

port= 465from_addr= '105635@qq.com'to_addrs= ['zcb@gmail.com','33630177@qq.com','17098@stuu.e.cn',]#消息格式 正规的邮件都要有 From To 和 Subject 三个内容

message = MIMEText('This message is sent from Python.--张博','plain','utf-8')

message['From'] = formataddr( (from_addr.split('@')[0],from_addr) )

message['To'] = ';'.join([formataddr((addr.split('@')[0],addr)) for addr in to_addrs ])#多个地址用 ; 连接起来

message['Subject'] = 'This is Subject--主题'context=ssl.create_default_context()

with smtplib.SMTP_SSL('smtp.qq.com',port,context=context) as server:

ret= server.login('105635@qq.com','uczgxzbbie') #后面为授权码,非密码

server.sendmail(from_addr,to_addrs,message.as_string())print(message.as_string())

View Code

使用Django 发送邮件:

views.pyif 0 ==0:#发送邮件测试

from django.core.mail importsend_mail

@require_http_methods(['GET','POST'])defemail(request):

send_mail('Subject Here','Here is the message','105635@qq.com',

['3363177@qq.com','zha812@gmail.com',],

fail_silently=False,

)return HttpResponse('email ok')

settings.py#发送邮件设置

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'EMAIL_HOST= 'smtp.qq.com'EMAIL_PORT= 587EMAIL_HOST_USER= '10567935@qq.com' #自己的邮箱

EMAIL_HOST_PASSWORD = xxxxxxxxxxxxxxxx#自己的邮箱的授权码,非密码

EMAIL_SUBJECT_PREFIX = '[zcb]' #主题 前缀

View Code

Django Forms:

四种选择:

select single choice

radio single choice

select multi choice

checkbox multi choice

from django importforms

COLORS= [(1,'Red'),

(2,'Green'),

(3,'Blue'),]classLoginForm(forms.Form):#选择 字段

favorite_colors1 = forms.ChoiceField( #select single choice

choices=COLORS, #widget 默认是 Select

)

favorite_colors2= forms.ChoiceField(#radio single choice

widget=forms.RadioSelect(),

choices=COLORS,

)

favorite_colors3= forms.MultipleChoiceField(#select multi choice

choices=COLORS, #默认是SelectMultiple

)

favorite_colors4= forms.MultipleChoiceField(#checkbox multi choice

choices=COLORS,

widget=forms.CheckboxSelectMultiple(),

)

forms.py

Django Widget:

自定义 Widget :

Django Form Validation:

Django Auth :

Django Auth 相关的数据库表关系:

所以,auth  一共有六个数据库表 !

Django auth_permission 表中的默认权限:

关于查看是否有某个权限,(一般不直接使用auth 中的 Permission 这个model)

给用户加减组,加减权限:

Django Admin:

ES6 常用语法 :

变量的定义:

var 会有  变量的提升,

let 不会有 变量的提升,而且不能重复定义

1 //var 变量提升,可以重复定义

2 var a = 'tom';3 var a = 'jane';4 console.log(a);5

6 //let 不会变量提升,也不能重复定义,更严格

7 let b = 'tom';8 let b = 'ajen'; //报错 duplicate declaration # 重复定义

9 console.log(b);10

11 //const 固定值,不能修改,是常量

模板字符串:

用`(反引号)标识,用${}将变量括起来

1 let n = 'tom';2 let age = 18;3 let motto =`hello world,my name is ${n},my age is ${age}`;4 console.log(motto);

箭头函数 (匿名函数):

python 中的匿名函数为 : lambda

1 //res => res + 1

2 let f = res => res + 1;3 let ret = f(1);4 console.log(ret);

基本箭头函数

this:

普通函数   的this 指的是 当前函数 最近的调用者,

箭头函数的this 与它所处的上下文中的this一致(常用于回调),

1 functionf() {2 console.log(this);3 }4 f(); //this 为 Window对象

5 let obj ={6 func:f7 };8 obj.func(); //this 为 obj 这个对象

9

10 let obj2 ={11 test:obj12 };13 obj2.test.func();//this仍然是 obj 这个对象

普通函数中,this为它最近的调用者

1 functionf() {2 setTimeout(function() {3 console.log('普通函数');4 console.log(this);//为它的最近调用者 即 window

5 console.log('普通函数');6 });7 setTimeout(res=>{8 console.log('匿名函数');9 console.log(this); //和 它所处的上下文 环境中this一致 ,即 f函数中的 this 一致

10 console.log('匿名函数');11 });12 }13 let obj ={14 func:f15 };16 obj.func();

普通函数 和 箭头函数中this 的区别

箭头函数的好处:

如果回调函数是普通函数,想使用 外层函数的this, 必须要在外层先 let that = this; ,然后使用that ,

而如果是箭头函数,则可以直接使用this ,

数据的打散  和 聚合  :

Python 函数实参位置  中用*  打散列表,** 打散字典,

Python 函数形参位置  中用*  聚合列表 ,**  聚合字典,

es 6 中也有类似操作:...

三个点在实参位置时,起到聚合成数组  的作用,

1 functionf(a,b,...args) {2 console.log(a);3 console.log(b);4 console.log(args);5 }6 f(1,2,3,4,5); //3,4,5,被聚合成一个数组

三个点在形参位置 --聚合作用

三个点在实参位置时,起到打散数组  的作用,

1 functionf(a,b,c) {2 console.log(a);3 console.log(b);4 console.log(c);5 }6 f(...[1,2,3]); //把[1,2,3] 打散成 1,2,3

三个点在实参位置 --打散作用

解构 赋值:

es 6 中也有类似操作:

它是用{} 解析对象, 用 [ ] 解析数组,

View Code

ES6的 面向对象  :

在es5中,定义一个类是 用原型链 来定义,es6 中,我们可以通过class 来定义类了~

1 /*类的基本用法*/

2 class Demo{3 constructor(userName,age){4 this.nick =userName;5 this.age =age;6 }7 run(){8 console.log('run with ',this.nick);9 return 1;10 }11 }12 let d = new Demo('tom',18);13 console.log(d.nick,d.age);14 let ret =d.run();15 console.log('我是 方法run 的返回值: ',ret);16

17 /*继承*/

18 class MyDemo extends Demo{19 constructor(userName,age) {20 super(userName,age); //子类中没有this ,需要先super下,

21 this.nick =userName;22 this.age =age;23 }24 }25 let demo2 = new MyDemo('a',18);26 demo2.run();

View Code

ES6 中的 import 和 export  :

与python 不同的是,js中要想import 导入,必须要先 export 出 变量,

要想导入,必须先抛出 变量,

但是,浏览器还不支持它们,还不能识别,

ES6的 Promise  :

使用js进行异步操作,会陷入回调地狱(callback hell ) ,代码可读性降低,

1 /*

2 * Promise 实例化: 要传它一个函数3 * 为了后续使用,这个函数要有两个参数(不需要我们手动传入,js引擎传),第一个代表是成功要执行的函数,第二个是失败要执行的函数4 *5 **/

6

7 let p = new Promise(function(a,b) {8 //这里写 异步代码

9 $.ajax({10 url:'test.py',11 success:function(res) {12 console.log(res);13 a();14 //b();

15 },16 error:function(res){17 console.log('fail');18 }19 })20 });21 //此时默认上面的异步代码一定执行成功

22 p.then(functionf1() {23 console.log('上面Promise 形参中的第一个函数 a执行了');24 },functionf2() {25 console.log('上面Promise 形参中的第二个函数 b执行了');26 });27

28 p.then(functionf1() {29 console.log('上面Promise 形参中的第一个函数 a执行了');30 }).catch(functionf2() {31 console.log('上面Promise 形参中的第二个函数 b执行了');32 })

Promise 简单使用--构建Promise对象,以及 Promise对象.then() 和 Promise对象.then().catch()

上面代码如果不用Promise对象的话,代码如下:

1 functiontest() {2 $.ajax({3 url:'test.py',4 success:function(res) {5 console.log(res);6 functionf1() {7 console.log('上面Promise 形参中的第一个函数 a执行了');8 }9 f1();10 },11 error:function(res){12 console.log('fail');13 functionf2() {14 console.log('上面Promise 形参中的第二个函数 b执行了');15 }16 f2();17 }18 })19 }20 test();

不用Promise 的话,可读性低,

再如:

如果是有两次异步请求:

1 let p = new Promise(function(a,b) {2 //这里写 异步代码

3 $.ajax({4 url:'test.py',5 success:function(res) {6 console.log(res);7 a();8 },9 error:function(res){10 console.log('fail');11 b();12 }13 })14 });15

16 let p2 = new Promise(function(a,b) {17 $.ajax({18 url:'test2.py',19 success:function(res) {20 a();21 },22 error:function(res) {23 b();24 }25 })26 });27

28 p.then(functionf1() {29 p2.then(functionf3() {30 console.log('2次都成功了');31 }).catch(functionf4() {32 console.log('第一次成功,第二次失败');33 })34 },functionf2() {35 p2.then(functionf3() {36 console.log('第一次失败,第二次成功');37 }).catch(functionf4() {38 console.log('2次都失败了');39 })40 });

使用Promise ,异步请求逻辑逻辑清晰

如果不用Promise实现上述代码:

1 functiontest() {2 $.ajax({3 url:'test.py',4 success:function(res) {5 functionf1() {6 $.ajax({7 url:'test.py',8 success:function() {9 console.log('2次都成功了');10 },11 error:function() {12 console.log('第一次成功,第二次失败');13 }14 })15 }16 f1();17 },18 error:function(res){19 console.log('fail');20 functionf2() {21 $.ajax({22 url:'test.py',23 success:function() {24 console.log('第一次失败,第二次成功');25 },26 error:function() {27 console.log('2次都失败了');28 }29 })30 }31 f2();32 }33 })34 }35 test();

可读性查,回调地狱

批量操作Promise对象:

除了上面一个一个Promise 对象的用,还有多个Promise对象一起使用的,

Promise.all() 和 Promise.race()

1 let p = new Promise(function(a,b) {2 //这里写 异步代码

3 $.ajax({4 url:'test1.py',5 success:function(res) {6 a();7 },8 error:function(res){9 b();10 }11 })12 });13

14 let p2 = new Promise(function(a,b) {15 $.ajax({16 url:'test1.py',17 success:function(res) {18 a();19 },20 error:function(res) {21 b();22 }23 })24 });25

26 //一个一个的使用 还是麻烦 垃圾

27 //p.then(function f1() {

28 //p2.then(function f3() {

29 //console.log('2次都成功了');

30 //}).catch(function f4() {

31 //console.log('第一次成功,第二次失败');

32 //})

33 //},function f2() {

34 //p2.then(function f3() {

35 //console.log('第一次失败,第二次成功');

36 //}).catch(function f4() {

37 //console.log('2次都失败了');

38 //})

39 //});

40

41 //批量的用 all 是全部执行成功

42 //race 是看谁执行的快

43 Promise.all([p,p2]).then(functionf() {44 console.log('两次都成功了');45 }).catch(function() {46 console.log('不是两个都成功,一个失败,或两个都失败了');47 });48

49 Promise.race([p,p2]).then(functionf() {50 console.log('有一个已经执行完了');51 }).catch(functionf() {52 console.log('全部失败');53 });

批量操作Promise

1 let p = new Promise(function(a,b) {2 //这里写 异步代码

3 $.ajax({4 url:'test3.py',5 success:function(res) {6 a(res);7 },8 error:function(res){9 b(res);10 }11 })12 });13

14 let p2 = new Promise(function(a,b) {15 $.ajax({16 url:'test2.py',17 success:function(res) {18 a(res);19 },20 error:function(res) {21 b(res);22 }23 })24 });25

26 //批量的用 all 是全部执行成功

27 //race 是看谁执行的快,如果在比赛中发现有一个已经失败,失败

28 Promise.all([p,p2]).then(functionf(res) {29 //console.log(res);// [data1 ,data2] 重要

30 console.log('两次都成功了');31 }).catch(function(res) {32 //console.log(res);// 第一个失败的 数据

33 console.log('不是两个都成功,一个失败,或两个都失败了');34 });35

36 Promise.race([p,p2]).then(functionf(res) {37 console.log(res); //第一个执行完的 数据 重要

38 console.log('有一个已经执行完了');39 }).catch(functionf(res) {40 console.log(res);//第一个检测到的那个,失败的那个的数据

41 console.log('检测有一个失败,或全部失败');42 });

all() 和 race() 中的传参问题

封装函数 用于生成Promise对象:

我们发现 Promise对象之后url 不同,因此可以封装一个函数 专门用来生成Promise对象:

1 functionget_promise(url){2 return new Promise(function(a,b) {3 $.ajax({4 url:url,5 success:function(res) {6 a(res);7 },8 error:function(res) {9 b(res);10 }11 })12 })13 }14 let p = get_promise('test.py');15 let p2 = get_promise('test2.py');16

17 Promise.all([p,p2]).then(function(res) {18 console.log('两次都成功了');19 console.log('第一个数据');20 console.log(res[0]);21 console.log('第二个数据');22 console.log(res[1]);23 })

封装一个用于生成Promise对象的函数

1 //function get_promise(url){

2 //return new Promise(function (a,b) {

3 //$.ajax({

4 //url:url,

5 //success:function (res) {

6 //a(res);

7 //},

8 //error:function (res) {

9 //b(res);

10 //}

11 //})

12 //})

13 //}

14 functionget_promise(url){15 return new Promise((a,b)=>{16 $.ajax({17 url:url,18 success:res=>{19 a(res);20 },21 error:res=>{22 b(res);23 }24 })25 })26 }27

28 let p = get_promise('test.py');29 let p2 = get_promise('test2.py');30

31 Promise.all([p,p2]).then(function(res) {32 console.log('两次都成功了');33 console.log('第一个数据');34 console.log(res[0]);35 console.log('第二个数据');36 console.log(res[1]);37 })

再用上箭头函数,更好一点,更简洁

1 functionget_promise(url){2 return new Promise((a,b)=>{3 /*

4 $.ajax({5 url:url,6 success:res=>{7 a(res);8 },9 error:res=>{10 b(res);11 }12 })*/

13 //这里写异步代码

14 })15 }

注:上面的a, b形参名字,一般我们用 resolve 和 reject 来表示

ES8 :

ES8 的 async 和 await :

1 functionblock(sec) {2 while(1){3 if(new Date().getSeconds() ===sec){4 break;5 }6 }7 }8 functiongetData(url){9 //block(15); //模拟 正在 从url 获取数据 ...

10 return 'success';11 }12

13 async functiontest() {14 return (await getData('test.py'));15 }16 let p =test();17 p.then(function(res) {18 console.log(res);19 });20 console.log('hello world1');21 /*

22 * function前面加上async关键字,表示该function需要执行异步代码。23 * async function函数体内可以使用await关键字,且await关键字只能出现在async function函数体内。24 * await关键字可以跟在任意变量或者表达式之前,await后面 的将会是个异步过程25 *26 * 1,如果没有 async 内没有使用 await ,那么,将会是同步过程27 * 2,如果 async 中使用了 await28 * 第一个await 时,此时阻塞两个地方一个是主程序,一个是第一个await 后的代码29 * 然后 第一个await 后代码执行完毕后,然后执行 主程序,最后再执行 第一个await后的代码30 **/

vue 框架:

前端回顾:

vue 的思想: 数据来驱动视图,  它改变 了原先 获取dom 渲染dom 的思想

后端有MVC(django 中的MTV 模式  ),M - M , V - T ,C - V

前端呢,又基于MVC 改进成了 MVVM ,Model ,  View, VIewModel ,

MVVM中的   VM  和 C  和 django 中的 v(视图层函数)功能一致:都是给view提供处理好的数据的,

vue 的 常用指令 :

1

2

3

4

5

6

7

hello world

8

9

10

11 {{name}}12 {{motto}}13

14

15

16 const app = newVue({17 el:'.box', //1,指定 vue 的作用域

18 data:{ //2,放入数据

19 name:'tom',20 motto:'Life is short , I learn Python!'

21 }22 })23

24

25

vue的简单使用

v-text  和 v-html :

1

2

3

4

5

6

7

hello world

8

9

10

11 {{name}}12

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值