Django框架 pip3 install django 命令: # 创建Django程序 django-admin startproject mysite # 进入程序目录 cd mysite # 启动socket服务端,等待用户发送请求 python manage.py runserver 127.0.0.1:8080 # 创建app python manage.py starapp app01 pycharm 1. 创建project 2. 配置: - 模板路径 template目录 TEMPLATES = [{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'template')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ],},},] - 静态文件路径 static目录 STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), ) 3. 额外配置 MIDDLEWARE = [#'django.middleware.csrf.CsrfViewMiddleware',]
Web框架本质
浏览器(socket客户端) 2. 发送IP和端口 http://www.baidu.com:80/index/ GET: 请求头 http1.1 /index?p=123 请求体(无内容) POST: 请求头 http1.1 /index?p=123 请求体 ... 4. 接收响应 普通响应:页面直接显示 重定向响应:再一起一次Http请求 服务器(socket服务端) 1. 启动并监听ip和端口,等待用户连接 3. 接收请求进行处理,并返回 普通返回: 响应头: Access-Control-Allow-Origin:* 响应体: ... 重定向返回: 响应头: LOCATION: 'http://www.baidu.com' Access-Control-Allow-Origin:*
路由系统:
urls.pyfrom django.urls import path,re_pathfrom app01 import viewsurlpatterns = [ # path('admin/', admin.site.urls), path('index/', views.index), re_path('^edit/(\w+)/$',views.edit1), # 加上 $ re_path('^edit/(\w+).html$',views.edit2), re_path('^edit/(?P\w+)/(?P \w+).html$',views.edit3), # 按参数名传参 # def edit3(request,*args,**kwargs): # 不要将(\w+)与(?P \w+)混用 # 如果前面不加结尾符,则不能匹配此url path('index2/', views.index2,name='n2'), # 给url命名;在函数中通过别名反找到url re_path('index3/(\w+)', views.index3,name='n3'), # 可随意生成(\w+)位置的值 re_path('^index4/(?P \w+)/(?P \w+).html$', views.index4,name='n4'), # 可随意生成(?P \w+)位置的值 re_path('^', default), # 此规则放最后 # 什么都不输或者输错了,将会被匹配 # def default(request):return HttpResponse('url 错误')]views.pydef edit(request,a1): # a1 为re_path('^edit/(\w+)/$')括号中的字符,按位置传参, # 若url中有2个括号,函数就有request参数和另2个参数 return HttpResponse('...') # 通过别名反找到url,反生成urlfrom django.urls import reversedef index2(request): v = reverse('n2') return HttpResponse(v) def index3(request,*args): v = reverse('n3',args=(123,)) # 请求url:index3/3 生成url:index3/123 # 有多少(\w+),args=(,)就写多少个参数 return HttpResponse(v) def index4(request,**kwargs): v = reverse('n4',kwargs={ 'a2':666,'a1':777)) # /index4/666/777.html # 请求url:index3/3 生成url:index3/123 # 有多少(?P \w+),kwargs={,}就写多少个键值对 return HttpResponse(v) # 若是给url命名,在templates模板中可以直接使用名字{% url 'm1' %}# path('index10/', views.index10,name='m1'),#
路由分发: urls.py分配url到app from django.urls import path,re_path,include urlpatterns = [ path('app02/', include('app02.urls')), path('app01/', include('app01.urls')), # 只匹配开头,然后交与app01中的urls继续匹配 # 请求url为 http://127.0.0.1:8000/app01/index/ # -> 先匹配到app01 -> app01下的urls中匹配index ] 在app01.urls.py文件下匹配url from django.urls import path,re_path from app01 import views urlpatterns = [ path('index/', views.index), ]
ORM操作
ORM操作 Http请求: url -> 视图(模板+数据) 步骤: 1. 创建数据库 2. DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'s4day70db', 'USER': 'root', 'PASSWORD': '', 'HOST': 'localhost', 'PORT': 3306, } } 3. __init__文件中 import pymysql pymysql.install_as_MySQLdb() 4.注册app INSTALLED_APPS = [app01,] 5. from django.db import models class UserGroup(models.Model): title = models.CharField(max_length=32) class UserInfo(models.Model): nid = models.BigAutoField(primary_key=True) user = models.CharField(max_length=32) password = models.CharField(max_length=64) age = models.IntegerField(default=1) ug = models.ForeignKey('UserGroup',on_delete=models.CASCADE,null=True) # 联合唯一 class Meta: unique_together = [ ('b','g'),] 6.创建数据表,命令: python manage.py makemigrations python manage.py migrate # orm中,若不手动创建models.AutoField(primary_key=True),则自动创建id列。 # 已经创建好的数据库表,修改后重新在终端执行命令即可修改。 # 在已有列的表中增加列,设置值为空null=True,或者default=''设置默认值。 外键: UserInfo表中生成外键,列名为 ug_id ug(对象) 代表UserGroup中的一行数据 增 models.UserGroup.objects.create(title='销售部') obj = models.UserGroup.objects.create(title='销售部') print(obj.id) # 返回创建好的数据 obj = models.UserGroup(title='xxx') obj.save() # 批量插入数据 objs = [ models.UserGroup(name='name-1'), models.UserGroup(name='name-2'), ] models.UserGroup.objects.bulk_create(objs,10) 查 # 类->数据库表,对象->数据表行 group_list = models.UserGroup.objects.all() # 获取所有数据 # for row in group_list: # print(row.id,row.title) group_list = models.UserGroup.objects.filter(id__gt=1) # filter(筛选条件) QuerySet[obj,obj] group_list = models.UserGroup.objects.filter(id__gt=1).first() # 取第一个值,obj对象 obj = models.UserInfo.objects.filter(id__gt=1).first() obj.ug.title # 含外键表查寻,对象.外键表列名 即可获取主表的值。 models.UserGroup.objects.all().values('id','title') # 字典类型,两列。 models.UserGroup.objects.all().values_list('id','title') # 元组类型,两列。 obj = models.UserGroup.objects.filter(id__gt=1).first() obj.userinfo_set.all() # obj.userinfo_set.filter(nid=2)对另一张表的列做筛选 # 反向操作,获取已被关联外键项的所有与之关联的数据!? # obj.表名小写_set.all() for row in obj.userinfo_set.all(): # 获取到的是userinfo 中的数据 print(row.age,row.user) models.UserGroup.objects.all().values('id','title','userinfo__age') # 反向查找,跨表 models.UserInfo.objects.all().values('nid','ug__title',) # 正向查时跨表 models.UserInfo.objects.all().values_list('nid','ug__title',) # 正向查时跨表 # xxx.filter() 也可以跨表,跟value一样。 # 查询主动做连表 models.UserInfo.objects.all().select_related('ug') # 不做连表,做多次查询 models.UserInfo.objects.all().prefetch_related('ug') user_list = models.UserInfo.objects.all()[page_info.start():page_info.end()] # 分页,获取某段数据 # 排序 models.UserInfo.objects.order_by('nid') # 从大到小 models.UserInfo.objects.order_by('-nid','name') # 从小到大,id重复按name排序 # 分组 from django.db.models import Count,Sum,Min user_list = models.UserInfo.objects.values('ug_id').annotate(xxx = Count('nif')) # print(user_list,user_list.query) #SELECT `app01_userinfo`.`ug_id`, COUNT # (`app01_userinfo`.`nid`) AS `xxx` FROM `app01_userinfo` GROUP BY # `app01_userinfo`.`ug_id` ORDER BY NULL # user_list = models.UserInfo.objects.values('ug_id').annotate(xxx = Count('nid')).filter(xxx__gt=3) # 分组后筛选 # SELECT `app01_userinfo`.`ug_id`, COUNT # (`app01_userinfo`.`nid`) AS `xxx` FROM `app01_userinfo` GROUP BY # `app01_userinfo`.`ug_id` HAVING COUNT(`app01_userinfo`.`nid`) > 3 ORDER BY NULL # 其它 models.UserInfo.objects.filter(id__lt=1) # < models.UserInfo.objects.filter(id__gte=1) # >= models.UserInfo.objects.filter(id__in=[1,2,3]) # in[1,2,3,] models.UserInfo.objects.filter(id__range=[1,3]) models.UserInfo.objects.filter(id=1) models.UserInfo.objects.exclude(id=1) # id !=1 # Q # 方式一 models.UserInfo.objects.filter(Q(nid=8) | Q(nid__gt=10) & Q(caption='root')) # 方式二 组合查询 q1 = Q() q1.connector = 'OR' q1.children.append(('id', 1)) q1.children.append(('id', 9)) q2 = Q() q2.connector = 'OR' q2.children.append(('c1', 1)) q2.children.append(('c1', 10)) con = Q() con.add(q1, 'AND') con.add(q2, 'AND') models.Tb1.objects.filter(con) # extra # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) result = models.UserInfo.objects.filter(id__gt=1).extra( where=['app01_userinfo.id < %s'], params=[100,], tables=['app01_usertype'], order_by=['-app01_userinfo.id'], select={ 'uid':1,'sw':"select count(1) from app01_userinfo"} ) print(result.query) # SELECT (1) AS "uid", (select count(1) from app01_userinfo) AS "sw", "app01_userinfo"."id", "app01_userinfo"."name", "app01_userinfo"."age", "app01_userinfo"."ut_id" FROM "app01_userinfo" , "app01_usertype" WHERE ("app01_userinfo"."id" > 1 AND (app01_userinfo.id < 100)) ORDER BY ("app01_userinfo".id) DESC # 执行原生SQL from django.db import connection, connections cursor = connection.cursor() # cursor = connections['指定数据库'].cursor() cursor.execute("""SELECT * from auth_user where id = %s""", [1]) row = cursor.fetchone() - 原生SQL语句 - raw result = models.UserInfo.objects.raw('select * from userinfo') 删 models.UserGroup.objects.filter(id=2).delete() # 注意有外键的情况 更新 models.UserGroup.objects.filter(id=2).update(title='公关部') from django.db.models import F # F 用来获取原来的值 models.UserInfo.objects.all().update(age = F('age') +1) 反向:别名,不用小写表名做反向操作,而是用别名.all()取数据。 related_name = 'xxx' user_set ==> xxx related_query_name = 'xxx' user_set ==> xxx_set
# CBV
path('login.html',views.Login.as_view()),from django.views import Viewclass Login(View): def get(self,request): return HttpResponse('Login.get')
xss攻击 CSRF
xss攻击 - 慎用 safe和mark_safe 前端:{ { item|safe }} 后端:from django.utils.safestring import mark_safe tag = mark_safe(tag) - 非要用,一定要过滤关键字CSRF a. 基本应用 form表单中添加 { % csrf_token %} b. 全站禁用 # 'django.middleware.csrf.CsrfViewMiddleware', c. 局部禁用 'django.middleware.csrf.CsrfViewMiddleware', from django.views.decorators.csrf import csrf_exempt @csrf_exempt def csrf1(request): if request.method == 'GET': return render(request,'csrf1.html') else: return HttpResponse('ok') d. 局部使用 # 'django.middleware.csrf.CsrfViewMiddleware', from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_protect def csrf1(request): if request.method == 'GET': return render(request,'csrf1.html') else: return HttpResponse('ok') c. 特殊CBV from django.views import View from django.utils.decorators import method_decorator @method_decorator(csrf_protect,name='dispatch') class Foo(View): def get(self,request): pass def post(self,request): pass
PS:CBV中添加装饰器
def wrapper(func): def inner(*args,**kwargs): return func(*args,**kwargs) return inner # 1. 指定方法上添加装饰器 # class Foo(View): # # @method_decorator(wrapper) # def get(self,request): # pass # # def post(self,request): # pass # 2. 在类上添加 # @method_decorator(wrapper,name='dispatch') # class Foo(View): # # def get(self,request): # pass # # def post(self,request): # pass
Ajax提交数据时候,携带CSRF
a. 放置在data中携带b. 放在请求头中
模板
# 如果传入函数名,将会自动执行函数并取到值。 {% for a in page_info.pager %} { { a|safe }} #xss攻击 {% endfor %} index.html{ % for item in item_list %} { { item }} {% endfor %} { {forloop.counter}} { {forloop.first}} { {forloop.last}}{ % if ordered_warranty %} {% else %} {% endif %}result = {}for row in teacher_list: tid =row['tid'] if tid in result: result[tid]['titles'].append(row['title']) else: result[tid] = { 'tid': row['tid'],'name':row['name'],'titles': [row['title'],]}return render(request,'teacher.html',{ 'teacher_list':result.values()})母版: ... { % block s1 %} {%endblock%} ... { % block s2 %} {%endblock%} 子板: { % extends "layout.html "%} { % block s1 %}fff
{%endblock%} { % block s2 %}ffffff
{%endblock%}layout.html { % block x1 %}{%endblock%}ff
{ % block x2 %}{%endblock%}2
... { % block x3 %}{%endblock%}index.html { %extends 'layout'%} { % block x1 %}dfssssssdfsd{%endblock%} { % block x2 %}dfsdfsd{%endblock%} { % block x3 %}fff{%endblock%} 自定义模板语言函数创建templatetags目录,在其下创建xxx.py文件使用特殊方法要先导入:{ % load xx %}xxx.pyfrom django import templateregister = template.Library()@register.filter # 只能有2个参数def my_func(value,arg): return value+arg { { name|my_func:"666"}} # 冒号后不能有空格 {%if name |my_func%} 〈h3〉真〈/h3〉 { %else%} 〈h3〉假特别漂亮的组件
标题:{ { name}}内容:{ { name}}index.html {% include 'pub.html' %}
cookie session
Cookie a. 保存在客户端浏览器上的“键值对” b. 服务端可以向用户浏览器端写cookie c. 客户端每次方请求时,会携带cookie去set_cookie key, value='', max_age=None, expires=None, path='/', domain=None, secure=False, Https httponly=False 只能自Http请求中传入,js代码无法获取到cookie签名: obj = HttpResponse('...') obj.set_cookie('k1','v1') request.COOKIES.get('k1') obj.set_signed_cookie(k1,v1,max_age,salt='ff') request.get_signed_cookie('k1',salt='ff') session保持会话 Cookie是什么? 保存在客户端浏览器上的键值对 Session是什么? 保存在服务端的数据(本质是键值对) 应用:依赖cookie 作用:保持会话(Web网站) # 登陆成功返回时,在request中设置session键值对后,将通过cookie发送随机字符串 # session值保存在数据库表中的 # 在浏览器请求时,获取浏览器带来的session随机字符串,随后检测是否有这个用户登录 if 登陆成功: request.session['username']='name1' request.session['password']='pwd1' return render() 判断是否登陆 v = request.session.get('username') if v:return HttpResponse('%s,登陆成功'%v)