Django基本使用
Posted 123why
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django基本使用相关的知识,希望对你有一定的参考价值。
创建Django的最基本流程(在pycharm) (在命令行创建项目 django-admin startproject mysite) 1.创建app python manage.py startapp app01 2.添加app到settings文件 pycharm默认添加 ‘app01.apps.App01Config‘, INSTALLED_APPS = [ ‘django.contrib.admin‘, ‘django.contrib.auth‘, ‘django.contrib.contenttypes‘, ‘django.contrib.sessions‘, ‘django.contrib.messages‘, ‘django.contrib.staticfiles‘, ‘app01.apps.App01Config‘, ] 3.配置静态文件 STATICFILES_DIRS = ( os.path.join(BASE_DIR,"static") ) 在app文件夹中添加static文件夹
(在命令行)
django-admin startproject mysite # 创建django项目
python manage.py startapp app1 # 创建app
python manage.py runserver 127.0.0.1:8080 # 运行项目
Django请求生命周期 客户端请求服务端时,会向服务端发送有字符串组成的请求 这个请求包含 - 请求头 Request URL: https://www.cnblogs.com/ Request Method: GET Status Code: 200 Remote Address: 114.55.187.58:443 Referrer Policy: no-referrer-when-downgrade :authority: www.cnblogs.com :method: GET :path: / :scheme: https accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 accept-encoding: gzip, deflate, br accept-language: zh-CN,zh;q=0.9 cache-control: max-age=0 cookie: _ga=GA1.2.226328555.1568952902; __gads=ID=a7059762e3dc1aef:T=1568952901:S=ALNI_MYJ2gz_V2_CparYQryZQ6svvmFAog; _gid=GA1.2.1251713082.1570801454; _gat=1 sec-fetch-mode: navigate sec-fetch-site: none sec-fetch-user: ?1 upgrade-insecure-requests: 1 user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36 - 请求头和请求体之间由两个换行分隔 - 请求体 请求体就是网页内容 同理服务端的响应也是一连串的字符串,也分为响应头响应体 函数的return 就是响应 给响应赋一个变量,然后可以直接为变量以添加字典的形式添加响应头 send = HttpResponse("CBV_POST") send["v1"] = "s1" return send 此时的响应头中就包含了一组键值对"v1":"s1" ,像添加cookie也时这样 send.set_cookie("v2","s2") Content-Length: 8 Content-Type: text/html; charset=utf-8 Date: Sat, 12 Oct 2019 11:55:52 GMT Server: WSGIServer/0.2 CPython/3.7.3 v1: s1 # 被添加响应体 X-Frame-Options: SAMEORIGIN cookie和session COOKIE: 当在某站点登陆后,复制进入的页面url,然后再次在同一浏览器访问该链接,依然有效,但是在其他浏览器后设备 访问,返回的内容是未登录的内容,这是由Cookie实现的 Cookie:是一张身份证,它保存在客户端的某个文件中,信息由键值对构成,请求网站时会会自动发送,站点根据其中的某些信息,对用户进行身份判定 如是否已经登录过 cookie可以解决重复登录的问题,但是安全性差,所以一般使用cookie和sesion配合使用 session: 报错:no such table: django_session 因为sesion信息存储在数据库中,所以要先创建数据库 FBV 和CBV function base views class base views 路由分发时,对用户请求的url进行匹配(从上到下,一旦匹配不在向下继续),匹配成功则执行对应函数(FBV) 或者类(CBV) CBV urlpatterns = [ path(‘admin/‘, admin.site.urls), path(‘login/‘, views.login), path(‘index/‘, views.index), path(‘CBV/‘, views.CBV.as_view()), # 调用as_view()方法 ] from django.views import View class CBV(View): def get(self,request): # GET请求 return HttpResponse("CBV_GET") def post(self,request): # POST请求 return HttpResponse("CBV_POST") 分页组件 select * from table_name offset 50 limt 10 # 从第50个元素开始取,取10个 - Django内置分页 from django.core.paginator import Paginator,PageNotAnInteger,EmptyPage - PageNotAnInteger :输入的页码不是整数 - EmptyPage :空页码 - 两个对象 -paginator -创建paginator对象 paginator = Paginator(USER_LIST,10) (要分页所有数据,每页数据数) -per_page:每页显示条目数量 -count: 数据总个数 -num_pages:总页数 -page_range:总页数索引范围 -page:page对象 -page -创建page对象 posts = paginator.page(要显示的那一页页码) -has_next:是否有下一页 -next_page_number:下一页页码 -has_previous:是否有上一页 -previous_page_number:上一页页码 -object_list:切片后的数据列表 -number :当前页 -paginator: paginator对象 - 扩展内置分页 - 自定义分页 django 数据序列化 -在javascript JSON.parse(ret) 字符串转换字典 JSON.stringify() 字典转字符串 -在django 对于从数据库取出的数据 .values("字段名",......)或者.value_list()需要对这样的数据进行list() def serialize(request): return render(request,"serialize.html") from django.core import serializers def get_data(request): msg = {"status":True,"m":None} data = models.Student.objects.all() try: v = serializers.serialize("json",data) # 只能用这个方法序列化queryset对象,像数组,字典,元组可以直接使用json.dumps() msg["m"] = v except Exception as e: v = e msg["status"] = False msg["m"] = v return HttpResponse(json.dumps(msg)) $(function () { serialize() }); function serialize() { //alert(666); $.ajax({ url:"/get_data/", type:"POST", //datatype:"JSON", success:function (art) { var v = JSON.parse(art); console.log(JSON.parse(v.m)[0].fields.username); console.log(JSON.parse(v.m)[0].fields.email); var tr = document.createElement("tr"); var td = document.createElement("td"); td.innerHTML = JSON.parse(v.m)[0].fields.username; tr.append(td); # 这是JS的方法 $("#tb").append(tr); # 这是jquery的方法,必须找到代码中存在的标签 } }) } form组件 -用户登录信息验证 -导入模块 from django.forms import fields from django import forms -创建类 class User_Msg(forms.Form): user = fields.CharField(max_length=32,min_length=18,required=True) # requried = True 不能为空 age = fields.IntegerField(required=True) email = fields.EmailField(required=True) -属性 widgets widget=widgets.Select(choices=((1,"小明"),(2,"小红"))) # .HTML插件 (attrs = {"name":"c1"})为标签添加属性 -下拉框 # 单选下拉框 ff1 = fields.CharField( widget=widgets.Select(choices=((1,"小明"),(2,"小红"))) ) ff2 = fields.ChoiceField( choices=[(1,"小明"),(2,"小红")] ) # 多选下拉框 ff3 = fields.MultipleChoiceField( choices=[(1,"小明"),(2,"小红")], widget = widgets.SelectMultiple() ) -checkbox # 单选checkbox ff4 = fields.CharField( widget=widgets.CheckboxInput(), label="同意" ) #多选checkbox ff5 = fields.MultipleChoiceField( initial=[1,2], # 默认选中 choices=((1,"xiaoming"),(2,"xiaohong"),(3,"xiaogong")), widget=widgets.CheckboxSelectMultiple(), ) -radio # radio 互斥 ff6 = fields.ChoiceField( choices=[(1,"北京"),(2,"上海"),(3,"广州")], initial=[1,], widget=widgets.Radioselect() ) - 数据源的实时更新,上面的数据源都是自定义无法实时改变的,怎么在数据库去数据源?数据库数据改变,数据源怎么实时改变? ff7 = fields.ChoiceField( widget = widgets.Select() ) # 不能在静态属性中直接从数据库获取属性,因为类中静态属性在类加载完成之后就被固定,不会改变, # 所以从数据库中取出的数据永远是第一次取出来的 def __init__(self,*args,**kwargs): super(Form_type,self).__init__(*args,**kwargs) self.fields["ff7"].widget.choices = models.Userform.objects.all().values_list("id","username") """ self.fields取出所有静态属性,因为每次刷新都会重新创建实例,也就可以在数据库重新取数据赋值给choices """ - # 实时更新数据源的另一种实现方法,不推荐,显示的是objects对象,需要在models中增加 def __str__(self):return self.要显示的字段 ff8 = ModelChoiceField( queryset=models.Userform.objects.all(), empty_label="请选择", to_field_name="id", #value的值 ) #################### choices = 列表和元组,选项必须是元组 -属性error_messages{"invalid":....,"required":"不能为空"} -获取类返回的信息 if obj.is_valid(): # 输入是否有效 print("success",obj.cleaned_data) # 验证成功的数据,返回一个字典 else: print("errors",obj.errors) # 错误信息 -自动生成HTML代码 -创建一个实例obj = User_Msg(),但不传入数据,在HTML文件中{{obj.user}} - 自定义正则表达式 -a from django.core.validators import RegexValidator class Form_re(forms.Form): r1 = fields.CharField( error_messages={"invalid":"...."}, validators=[RegexValidator(r‘^[0-9]+$‘,‘请输入数字‘),RegexValidator(r‘159[0-9]+&‘,‘数字必须以159开头‘)] ) -b r2 = fields.RegexField(r‘^[0-9]+$‘,error_messages={"invalid":"..."}) #只能填入一个正则表达式 -Ajax 基于源码的 .errors 自定制 添加新的验证(非正则表达式) - self._clean_fields() -> clean_字段名 对单个字段进行验证 return cleaned_data["字段名"] self._clean_form() -> clean 对全部字段进行验证 return cleaned_data self._post_clean() from django.core.exceptions import ValidationError class Form_Ajax(forms.Form): username = fields.CharField() email = fields.EmailField() # 自定义方法clean_ + 字段名 # 正确 return self.cleaned_data["字段名"] # 错误 raise ValidationError("用户名错误") def clean_username(self): v = self.cleaned_data["username"] print(v) if models.Student.objects.filter(username = self.cleaned_data["username"]).count(): raise ValidationError("用户名已存在") else: return self.cleaned_data["username"] def clean_email(self): return self.cleaned_data["email"] ModelForm:form与表关联 from django import forms class model_form(forms.ModelForm): class Meta: model = models.User fields = "__all__" # 修改所有字段 修改部分["字段一","字段二"] 创建实例 user_form= model_form() 将user_form传至前端 去掉浏览器自带的错误信息 novalidate 后端发送给前端的字符串,默认不渲染,使它渲染的两种方式 - |safe - import django.utils.safestring import mark_safe mark_safe("要渲染的字符串") zip函数:分离列表中元组的元素,组成新的元组 l = [(1,2),(3,4),(5,6)] >>> list(zip(*l)) [(1, 3, 5), (2, 4, 6)] window.localtion.reload() 刷新页面 Ajax Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。 Ajax = 异步 JavaScript 和 XML 或者是 HTML(标准通用标记语言的子集)。 Ajax 是一种用于创建快速动态网页的技术。 Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。 通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。 这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。 传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页页面。 $.ajax( { url:"", type:"POST", data:{}, success: function ():{ } } ) $.ajax( { url:"", type:"POST", data:{}, datatype:"JSON" 服务端发送的数据进行JSON转换 success: function ():{ } } ) $.ajax( { url:"", type:"POST", data:{}, datatype:"JSON","TEXT","HTML","XML" 服务端发送的数据进行JSON转换 traditional:true, 当需要发送数组数据时使用 success: function ():{ } error:function (){ 数据因网络等原因未能成功发送,触发该回调函数 } } ) Ajax发送数据的几种情况 a. 字符串和数字 直接发送 b. 数组 添加traditional:true, c. 字典 默认情况下字典不能传送,但可以先将其转换为字符串 data:{"k1":JSON.stringify({"k1":12,"k2":13})}, form表单中的数据可以使用一个方法直接全部获取 data = $("#fm").serialize() $.ajax({ url:"", data:data, }) 不刷新页面添加学生,新添加的学生操作没有绑定事件 使用事件委托,点击操作时绑定事件,而不是在循环遍历中绑定 事件委托: django 3.x $(要绑定事件标签的上级标签).on("click","要绑定事件的标签",function (){}) django 1.x 2.x $(要绑定事件标签的上级标签).on("要绑定事件的标签","click",function (){}) find 用法 var text = $(‘select[name="cls_id"]‘).find(‘option[value="‘+ postData.cls_id +‘"]‘).text(); checked属性需要用prop获取 prop() 方法设置或返回被选元素的属性和值。 当该方法用于返回属性值时,则返回第一个匹配元素的值。 当该方法用于设置属性值时,则为匹配元素集合设置一个或多个属性/值对。 注意:prop() 方法应该用于检索属性值,例如 DOM 属性(如 selectedIndex, tagName, nodeName, nodeType, ownerDocument, defaultChecked, 和 defaultSelected)。 提示:如需检索 HTML 属性,请使用 attr() 方法代替。 提示:如需移除属性,请使用 removeProp() 方法。 {{}} 如果想使用这样的字符串,可以使用 转义 三种方法 1.在js的function外定义一个变量 var name=‘测试‘; function XX(){ alert(name); } 2.不使用var,直接给定义变量,隐式的声明了全局变量 name=‘测试‘; function XX(){ alert(name); } 这种方法,即使该变量是在一个function内,当该function被执行后它变成了全局变量 ---- 但是function不执行它就不被其他function知道,所以最好定义在function外 3.使用window.变量名定义为全局变量,但是注意:调用时候建议写上window.变量名,当然也可以不写;我们常用的document.getXXX的document对象就是window的 window.name=‘测试‘; function XX(){ alert(window.name); } 跨站请求 JSONP -因为同源策略的机制,浏览器会阻止另一个源返回给本源的文档,其实请求和响应都进行了,只是浏览器不接受,我们无法获得响应 这个策略只会制约XMLHttpResponse的跨站请求,有些标签不受制约,如img,script JSONP就是利用script标签不受制约的特性,进行跨站请求的 function req() { $.ajax({ url:"http://127.0.0.1:8080/index/", type:"GET", # 请求方式只能是GET,就算修改为POST也会自动改回来 dataType:"JSONP", jsonp:"callback", # 修改包裹数据的函数名 jsonCallback:"foo1", success:function (arg) { console.log(arg) } }) } function foo1(arg) { #返回的数据必须以一个函数参数的形式返回, console.log(arg) #即函数名(数据)这样函数会被请求端执行,数据作为参数被接收了 } -JSONP原理: function submitJsonp2() { var tag = document.createElement(‘script‘); tag.src = ‘http://127.0.0.1:9000/xiaokai.html‘; document.head.appendChild(tag); document.head.removeChild(tag); } function fuck(arg) { $(‘#content‘).html(arg); } 全局变量的优点: 可以减少变量的个数,减少由于实际参数和形式参数的数据传递带来的时间消耗。 全局变量的缺点: (1)全局变量保存在静态存贮区,程序开始运行时为其分配内存,程序结束释放该内存。与局部变量的动态分配、动态释放相比,生存期比较长,因此过多的全局变量会占用较多的内存单元。 (2)全局变量破坏了函数的封装性能。函数象一个黑匣子,一般是通过函数参数和返回值进行输入输出,函数内部实现相对独立。但函数中如果使用了全局变量,那么函数体内的语句就可以绕过函数参数和返回值进行存取,这种情况破坏了函数的独立性,使函数对全局变量产生依赖。同时,也降低了该函数的可移植性。 (3)全局变量使函数的代码可读性降低。由于多个函数都可能使用全局变量,函数执行时全局变量的值可能随时发生变化,对于程序的查错和调试都非常不利。 因此,如果不是万不得已,最好不要使用全局变量。 XSS攻击:跨站脚本攻击 用户在网页上进行如评论之类的输入,评论的是一段脚本代码,如果后端认为是安全的,就会渲染在页面上, 造成其他浏览该评论的用户被脚本攻击 - 文件上传 -普通上传,选择文件的标签样式无法修改 -NB上传,将标签透明,用其他标签盖住 -基于form上传 -基于Ajax上传 -form表单包含 enctype:"mutipart/form-data" - input标签选择 type:"file" -前端使用img = request.FILES.get("name属性名") -img.chunks()获取内容,这是一个迭代器 -img.name 获取文件名 -img.size 获取文件大小 urls.py中使用正则表达式 from django.urls import path,re_path re_path(r‘index/(?P<de_id>d+).html‘,views.index_get,name = "index_all") # 注意d+ 反斜杠 name是别名通过别名在views.py和html中都可以反向生成url 在views.py中 from django.urls import reverse 对于有分组名的url current_path = reverse("name",kwargs = {"分组名":参数}) 没有的 current_path = reverse("name",args = (参数1,参数2......)) 在html中 {% url "name" 分组名 = 参数%} 或者没有分组名的时候直接写参数 权限管理 基于角色的访问控制(RBAC)Role Bases Access Control 登录验证 from django.shortcuts import render,redirect from django.contrib.auth import authenticate,login,logout # 导入模块 def acc_login(request): if request.method == "GET": return render(request, "login.html") else: username = request.POST.get("username") password = request.POST.get("password") user = authenticate(username=username,password=password) #进行验证,返回的是一个对象 if user: login(request,user) # 验证成功并不是登陆成功,要写入session url = request.GET.get("next",default="/crm/") print(url) return redirect(".."+url) return render(request,"login.html") def acc_logout(request): # 清除session logout(request) return redirect("/login/") # 未登录,不显示首页 # 会访问 http://127.0.0.1:8000/accounts/login/?next=/crm/ # 在配置文件中修改LOGIN_URL = ‘../login/‘,?next=/crm/ 是登录成功要跳转的页面 from django.contrib.auth.decorators import login_required @login_required() def dashbase(request): return render(request,"crm/home_page.html") 定制模板中使用的函数 -创建一个包 Python Package -创建一个python文件 kingadmin_test.py -kingadmin_test.py from django.utils.template import Library register = Library() @register.simple_tag def bulid_ele(a,b): return a+b -在模板中使用,先load .py文件 {% load kingadmin_test %} -使用 {% bulid_ele a b %} SSO single sign on 单点登录 多套系统使用同一套账户,这个账户由单点也就是另一套系统维护,当多套系统登陆时,都会到这个单点进行验证,根据单点返回的结果 判断是否登陆成功,常用的有LDAP(轻型目录访问协议 (英文:Lightweight Directory Access Protocol,缩写:LDAP,/??ldæp/) 是一个开放的,中立的,工业标准的应用协议, 通过IP协议提供访问控制和维护分布式信息的目录信息。)
以上是关于Django基本使用的主要内容,如果未能解决你的问题,请参考以下文章
django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE的解决办法(转)(代码片段
django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE的解决办法(转)(代码片段