框架----Django框架知识点整理
一、cbv
- cbv(class-base-view) 基于类的视图
- fbv(func-base-view) 基于函数的视图
a.基本演示
- urlpatterns = [
- url(r'^login.html$', views.Login.as_view()),
- ]
urls.py
- from django.views import View
- class Login(View):
- """
- get 查
- post 创建
- put 更新
- delete 删除
- """
- def dispatch(self, request, *args, **kwargs):
- print('before')
- obj = super(Login,self).dispatch(request,*args,**kwargs)
- print("after")
- return obj
- def get(self,request):
- return render(request,"login.html")
- def post(self,request):
- print(request.POST)
- return HttpResponse("Login.post")
- view.py
views.py
二、分页
a.Django分页
- #浏览器访问
- http://127.0.0.1:8000/index.html/?page=9
- urlpatterns = [
- #django分页
- url(r'^index', views.index),
- ]
urls
- #django 分页
- from django.core.paginator import Paginator,Page,PageNotAnInteger,EmptyPage
- def index(request):
- current_page = request.GET.get("page")
- user_list = models.User_info.objects.all()
- paginator = Paginator(user_list,10) #每页显示10条
- """
- # count: 数据总个数
- # num_pages:总页数
- # page_range:总页数的索引范围,如: (1,10),(1,200)
- # page: page对象
- """
- try:
- posts = paginator.page(current_page) #当前页
- except PageNotAnInteger as e: #http://127.0.0.1:8000/index.html/?page=qqq 处理这种异常
- posts = paginator.page(1)
- except EmptyPage as e: #http://127.0.0.1:8000/index.html/?page=-10 捕获这种异常
- posts = paginator.page(1)
- """
- # has_next 是否有下一页
- # next_page_number 下一页页码
- # has_previous 是否有上一页
- # previous_page_number 上一页页码
- # object_list 分页之后的数据列表
- # number 当前页
- # paginator paginator对象
- """
- return render(request,"index.html",{"posts":posts})
- views.py
views.py
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <h1>用户列表</h1>
- <ul>
- {% for row in posts.object_list %}
- <li>{{ row.name }}</li>
- {% endfor %}
- </ul>
- <div>
- {% if posts.has_previous %}
- <a href="/index.html/?page={{ posts.previous_page_number }}">上一页</a>
- {% endif %}
- {% for num in posts.paginator.page_range %}
- <a href="/index.html/?page={{ num }}">{{ num }}</a>
- {% endfor %}
- {% if posts.has_next %}
- <a href="/index.html/?page={{ posts.next_page_number }}">下一页</a>
- {% endif %}
- </div>
- </body>
- </html>
- index.html
index.html
b.自定义分页
- #浏览器访问
- http://127.0.0.1:8000/custom/?page=6
- urlpatterns = [
- #自定义分页
- url(r'^custom/', views.custom),
- ]
urls
- from utils.pager import PageInfo
- #自定义分页
- def custom(request):
- #总页数
- all_count = models.User_info.objects.all().count()
- #用户当前想要访问的页码
- current_page = request.GET.get("page")
- page_info = PageInfo(current_page,all_count,10,"/custom",11)
- user_list = models.User_info.objects.all()[page_info.start():page_info.end()]
- return render(request,"custom.html",{"user_list":user_list,"page_info":page_info})
- views.py
views.py
- class PageInfo(object):
- def __init__(self,current_page,all_count,per_page,base_url,show_page=11):
- #如果传值错误进入第一页
- try:
- self.current_page = int(current_page)
- except Exception as e:
- self.current_page = 1
- self.per_page = per_page #每页显示的个数
- a,b = divmod(all_count,per_page) #页数 余数
- if b:
- a = a + 1
- self.all_page = a #总页码
- self.show_page = show_page
- self.base_url = base_url
- def start(self):
- # 1 0: 10
- # 2 10:20
- # 3 20:30
- return (self.current_page-1) * self.per_page
- def end(self):
- return self.current_page * self.per_page
- def pager(self):
- page_list = []
- half = int((self.show_page-1)/2)
- if self.all_page < self.show_page:
- begin = 1
- stop = self.all_page + 1
- else:
- if self.current_page < half:
- begin = 1
- stop = self.show_page + 1
- else:
- if self.current_page + half > self.all_page:
- begin = self.all_page - 10 +1
- stop = self.all_page + 1
- else:
- begin = self.current_page - half
- stop = self.current_page + half +1
- if self.current_page <=1:
- prev = "<li><a href='#'>上一页</a></li>"
- else:
- prev = "<li><a href='%s/?page=%s'>上一页</a></li>"%(self.base_url,self.current_page - 1)
- page_list.append(prev)
- for i in range(begin,stop):
- if i == self.current_page:
- temp = "<li class='active'><a href='/custom/?page=%s'>%s</a></li>"%(i,i)
- else:
- temp = "<li><a href='%s/?page=%s'>%s</a></li>"%(self.base_url,i,i)
- page_list.append(temp)
- if self.current_page >= self.all_page:
- nex = "<li><a href='#'>下一页</a></li>"
- else:
- nex = "<li><a href='%s/?page=%s'>下一页</a></li>" % (self.base_url,self.current_page + 1)
- page_list.append(nex)
- return "".join(page_list)
- utils/pager.py
utils/pager.py
- from django.db import models
- # Create your models here.
- class User_type(models.Model):
- uid = models.BigAutoField(primary_key=True)
- title = models.CharField(max_length=32)
- class User_info(models.Model):
- name = models.CharField(max_length=32)
- age = models.CharField(max_length=32)
- ut = models.ForeignKey("User_type")
- models.py
models.py
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css" />
- </head>
- <body>
- {% for row in user_list %}
- <li>{{ row.name }}</li>
- {% endfor %}
- <nav aria-label="Page navigation">
- <ul class="pagination">
- {{ page_info.pager |safe }}
- </ul>
- </nav>
- </body>
- </html>
- custom.html
custom.html
三、ORM正反向连表操作
- #ORM正反向连表操作
- - models
- from django.db import models
- class Foo(models.Model):
- """
- 第三个表
- """
- caption = models.CharField(max_length=16)
- class UserType(models.Model):
- """
- 用户类型
- """
- title = models.CharField(max_length=32)
- fo = models.ForeignKey('Foo')
- class UserInfo(models.Model):
- """
- 用户表
- """
- name = models.CharField(max_length=16)
- age = models.IntegerField()
- ut = models.ForeignKey('UserType')
- - views
- ----#跨表(正向操作)---UserInfo----含ForeignKey字段 PS: 一个用户只有一个用户类型
- # 获取
- # QuerySet[obj,obj,obj]
- result = models.UserInfo.objects.all()
- for obj in result:
- print(obj.name,obj.age,obj.ut_id,obj.ut.title,obj.ut.fo.caption)
- ----#跨表(反向操作)---UserType----不含ForeignKey字段 PS: 一个用户类型下可以有很多用户
- obj = models.UserType.objects.all().first()
- print('用户类型',obj.id,obj.title)
- for row in obj.userinfo_set.all(): #使用的是与之关联的表名小写加_set.all()这个方法取到所有东西
- print(row.name,row.age)
四、数据获取多个数据时(注意3种情况的不同之处<跨表查询、跨表取值>)
- # 数据获取多个数据时(注意3种情况的不同之处<跨表查询、跨表取值>)
- 1. [obj,obj,obj,] # .all()和.filter()拿到的结果是QuerySet对象
- models.UserInfo.objects.all()
- models.UserInfo.objects.filter(id__gt=1)
- result = models.UserInfo.objects.all()
- for item in result:
- print(item.name,item.ut.title) # 取值方式:item.name,item.ut.title 可以跨表
- 2. [{id:1,name:fd},{id:1,name:fd},{id:1,name:fd},] # .values()拿到的结果是字典
- models.UserInfo.objects.all().values('id','name')
- models.UserInfo.objects.filter(id__gt=1).values('id','name')
- #无法跨表
- result = models.UserInfo.objects.all().values('id','name')
- for item in result:
- print(item['id'],item['name']) # 取值方式:item['id'],item['name'] #无法跨表
- #跨表 使用__(双下划线)
- result = models.UserInfo.objects.all().values('id','name',"ut__title") # 这里查询时跨表使用的是ut__title 双下划线
- for item in result:
- print(item['id'],item['name'],item['ut__title']) # 跨表取值时也用的是双下滑线__
- 3. [(1,df),(2,'df')] # .values_list()拿到的结果是元组
- models.UserInfo.objects.all().values_list('id','name')
- models.UserInfo.objects.filter(id__gt=1).values_list('id','name')
- #无法跨表
- result = models.UserInfo.objects.all().values_list('id','name')
- for item in result:
- print(item[0],item[1]) # 取值方式: item[0],item[1] #无法跨表
- #跨表 使用__(双下划线)
- result = models.UserInfo.objects.all().values_list('id','name',"ut__title") # 这里要跨表使用的是ut__title 双下划线
- for item in result:
- print(item[0],item[1],item[2]) # 跨表取值时用的是下标
五、CSRF(跨站请求伪造)
- CSRF(Cross-site request forgery)跨站请求伪造,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS)
- 但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。
- 理解:csrf_token防止从别的网站向自己网站发post请求, 客户来访问网站,网站会向客户发送随机字符串,然后客户带随机字符串发送post请求
- 只有带随机字符串来,网站才认,一般是post请求才要求带随机字符串,其它网站第一次来不会带随机字符串。
a. django开启csrf
- MIDDLEWARE = [
- 'django.middleware.csrf.CsrfViewMiddleware',
- ]
b.HTML中使用
- {% csrf_token %} #只要写上{% csrf_token %} 会有一个隐藏的input随机字符串,在cookie也有一个随机的字符串,form表单提交数据时,一般会使用
- {{ csrf_token }} #生成随机的字符串
c.django中设置防跨站请求伪造功能有分为全局和局部
- #局部
- from django.views.decorators.csrf import csrf_exempt,csrf_protect
- @csrf_protect settings中没有设置全局中间件,为当前函数强制设置防跨站请求伪造功能。
- @csrf_exempt settings中设置了全局中间件,取消当前函数防跨站请求伪造功能。
- #fbv
- @csrf_protect
- def func(object):
- pass
- #cbv
- from django.views import View
- from django.utils.decorators import method_decorator
- @method_decorator(csrf_exempt,name="dispatch")
- class foo(View)
- pass
- fbv和cbv应用装饰器
fbv和cbv应用装饰器
- #方式一 类上加装饰器:
- def wrapper(func):
- def inner(*args,**kwargs):
- return func(*args,**kwargs)
- return inner
- @method_decorator(wrapper,name="get")
- @method_decorator(wrapper,name="post")
- class foo(View):
- def get(self,request):
- pass
- def post(self,request):
- pass
- #方式二 类上“dispatch”加装饰器:
- def wrapper(func):
- def inner(*args,**kwargs):
- return func(*args,**kwargs)
- return inner
- @method_decorator(wrapper,name="dispatch")
- class foo(View):
- def dispatch(self,request,*args,**kwargs):
- return xxx
- def get(self,request):
- pass
- def post(self,request):
- pass
- #方式三 方法上加装饰器:
- def wrapper(func):
- def inner(*args,**kwargs):
- return func(*args,**kwargs)
- return inner
- class foo(View):
- @method_decorator(wrapper)
- def get(self,request):
- pass
- def post(self,request):
- pass
- cbv应用其它装饰器
cbv应用其它装饰器
d. Ajax提交数据 携带CSRF
1. 通过获取隐藏的input标签中的字符串,放置在data中发送
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <form method="POST" action="/csrf1.html">
- {% csrf_token %}
- <input id="user" type="text" name="user"/>
- <a onclick="submitForm();">Ajax提交</a>
- </form>
- <script src="/static/jquery-1.12.4.js"></script>
- <script>
- function submitForm() {
- var csrf = $('input[name="csrfmiddlewaretoken"]').val();
- var user = $("#user").val();
- $.ajax({
- url:'/csrf1.html',
- type:'POST',
- data:{"user":user,"csrfmiddlewaretoken":csrf},
- success:function (arg) {
- console.log(arg);
- }
- })
- }
- </script>
- </body>
- </html>
- csrf1.html
csrf1.html
- urlpatterns = [
- url(r'^csrf1.html', views.csrf1),
- ]
urls.py
- def csrf1(request):
- if request.method == 'GET':
- return render(request,'csrf1.html')
- else:
- return HttpResponse('ok')
views.py
2. 通过获取返回的cookie中的字符串,放置在请求头中发送
- 通过在console中 document.cookie可以获取 csrftoken=JPv1gIdrBiAlK2RCrgFs0OKwsncPXvwPfMhEWIVzMdMFymIayiuGu2GkBAu57moL
- 但需要切割字符串,通过引入jquery.cookie.js对cookie操作,使用$.cookie("csrftoken")
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <form method="POST" action="/csrf1.html">
- {% csrf_token %}
- <input id="user" type="text" name="user"/>
- <a onclick="submitForm();">Ajax提交</a>
- </form>
- <script src="/static/jquery-1.12.4.js"></script>
- <script src="/static/jquery.cookie.js"></script>
- <script>
- function submitForm() {
- var token = $.cookie("csrftoken");
- var user = $("#user").val();
- $.ajax({
- url:'/csrf1.html',
- type:'POST',
- headers:{"X-CSRFToken":token},
- data:{"user":user},
- success:function (arg) {
- console.log(arg);
- }
- })
- }
- </script>
- </body>
- </html>
- csrf1.html
csrf1.html
六、Django框架最最最最基础的3+5基本使用步骤 。◕‿◕。
- 1,创建项目文件夹
- 在终端Terminal执行命令:
- django-admin startproject 项目名
- 2,配置3个地方
- (1)模板路径配置
- TEMPLATES = [
- {
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [os.path.join(BASE_DIR,'templates')], # 这一步
- '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',
- ],
- },
- },
- ]
- (2) 静态文件配置
- STATIC_URL = '/static/'
- STATICFILES_DIRS = (
- os.path.join(BASE_DIR,'static'),
- )
- (3) # 'django.middleware.csrf.CsrfViewMiddleware', 注释这一行
- 3,Django框架5步
- 在终端Terminal执行命令创建app模块:
- python manage.py startapp 模块名
- (1)连接数据库
- DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.mysql',
- 'NAME': "studentPro",
- 'USER':'yangzai',
- 'PASSWORD':'Oldsyang=5201314@yangzai',
- 'HOST':'mypy.me',
- 'PORT':3306,
- }
- }
- (2)导入pymysql
- 在__init__中写入
- import pymysql
- pymysql.install_as_MySQLdb()
- (3)创建model
- from django.db import models
- class UserInfo(models.Model):
- id =
- name =
- password =
- (4)注册模块
- INSTALLED_APPS = [
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- 'app01' -----这一步
- ]
- (5)初始化数据库
- python manage.py makemigrations --先执行
- python manage.py migrate --后执行
- 基本使用步骤
基本使用步骤
七、Django框架里面return的3种返回
- return render() - 返回页面
- - return render(request,'index.html',{'std_list':std_list})
- 3个参数含义:
- request:用户的请求信息
- 'index.html':需要返回的模板html页面
- {'std_list':std_list}:存放模板文件里面要被替换的占位符所对应的值
- return HttpResponse() - 返回字符串
- - return HttpResponse(json.dumps(ret))
- return redirect() - 返回url请求
- - return redirect('/teachers/')
- 提示点:redirect,href,action,这3中url请求,都要在地址前加/斜杠
- 例子:return redirect('/classes.html')
- <a href="/edit_class/{{ row.id }}.html">
- <form method="POST" action="/edit_class/{{ id }}.html">
- return的3中返回
return的3中返回
八、cookie
a. 简单应用
- def login(request):
- if request.method=="GET":
- return render(request,"login.html")
- else:
- name = request.POST.get("name")
- password = request.POST.get("password")
- if name == "alex" and password == "":
- obj = redirect("/classes/")
- obj.set_cookie("ticket","",max_age=10)
- return obj
- else:
- return redirect("/login/")
- def classes(request):
- sk = request.COOKIES
- print(sk)
- if not sk:
- return redirect("/login/")
b. 过期时间的两种格式
- 方式一:
- obj.set_cookie("ticket","",max_age=10)
- 方式二:
- import datetime
- from datetime import timedelta #时间的加减
- ct = datetime.datetime.utcnow() #获取当前日期
- v= timedelta(seconds=10) #10秒
- value = ct + v
- obj.set_cookie("ticket","",expires=value)
c. 限制路径
- obj.set_cookie("ticket","",max_age=10,path="/") #所有路径都可以访问
- obj.set_cookie("ticket","",max_age=10,path="/class") #只有class访问
d. cookie签名
- #加
- obj.set_signed_cookie("ticket","",salt="abc")
- #解
- sk = request.get_signed_cookie("ticket",salt="abc")
九、session
- 流程:客户登录网址,验证成功后,服务端生成一个随机字符串和随机字符串对应的键值,然后把随机字符串通过cookie发送给客户端
- 客户端拿着随机字符串通过cookir再次登陆,服务端拿着随机字符串和保存在本地的数据对应,以确定用户的登录状态
- Cookie是什么?
- 保存在客户端浏览器上的键值对
- Session是什么?
- 保存在服务端的数据(本质是键值对)
- {
- “aaaaa":{'id':1,'name':'于浩',email='xxxx'}
- "bbbbb":{'id':2,'name':'陈涛',email=''}
- }
- 应用:依赖cookie
- 作用:保持会话(Web网站)
- 好处:敏感信息不会直接给客户端
- 梳理:
- 1. 保存在服务端的数据(本质是键值对)
- 2. 配置文件中:
- - 存储位置
- - 超时时间、每次刷新更新时间
session是什么
a. 简单示例
- 用户访问http://127.0.0.1:8000/login/
- urlpatterns = [
- url(r'^index/', views.index),
- url(r'^login/', views.login),
- ]
urls
- def login(request):
- if request.method == 'GET':
- return render(request,'login.html')
- else:
- u = request.POST.get('user')
- p = request.POST.get('pwd')
- obj = models.UserAdmin.objects.filter(username=u,password=p).first()
- if obj:
- # 1. 生成随机字符串
- # 2. 通过cookie发送给客户端
- # 3. 服务端保存
- # {
- # 随机字符串1: {'username':'alex','email':x''...}
- # }
- request.session['username'] = obj.username
- return redirect('/index/')
- else:
- return render(request,'login.html',{'msg':'用户名或密码错误'})
- def index(request):
- # 1. 获取客户端端cookie中的随机字符串
- # 2. 去session中查找有没有随机字符
- # 3. 去session对应key的value中查看是否有 username
- v = request.session.get('username')
- if v:
- return HttpResponse('登录成功:%s' %v)
- else:
- return redirect('/login/')
- views.py
views.py
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <form action="/login/" method="POST">
- <input type="text" name="user">
- <input type="text" name="pwd">
- <input type="submit" value="提交">{{ msg }}
- </form>
- </body>
- </html>
- login.html
login.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <h1>index page</h1>
- </body>
- </html>
- index.html
index.html
自己的基于session登陆代码:
- def login(request):
- if request.method == "GET":
- return render(request, "login.html")
- else:
- input_code = request.POST.get('code')
- session_code = request.session.get('code')
- username=request.POST.get("user")
- password=request.POST.get("pwd")
- if input_code.upper() == session_code.upper():
- # obj = models.UserInfo.objects.filter(username=username,password=password).first()
- obj = models.UserInfo.objects.filter(username=username,password=password).values("nid","avatar",
- "nickname",
- "blog__title",
- "blog__site").first()
- print("obj:",obj)
- # print("obj.nid:",obj.nid)
- if obj:
- # nid=obj.nid
- # request.session["userinfo"]={"id":nid}
- request.session["userinfo"]={"id":obj.get("nid"),"avatar":obj.get("avatar"),
- "blogname":obj.get("blog__title"),
- "nickname":obj.get("nickname"),"site":obj.get("blog__site")}
- # print('.................',request.session['userinfo'])
- return redirect("/home_page/home_page.html/")
- else:
- return render(request, 'login.html', {"msg": "用户名或者密码不对"})
- else:
- return render(request, 'login.html', {"msg": "验证码错误"})
- # 退出登陆
- def logout(request):
- request.session.clear() # 清除session
- return redirect('/home_page/home_page.html/')
views
十、URL(路由配置系统)
- URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于这个URL调用这段代码<br>对于那个URL调用那段代码
- urlpatterns = [
- url(正则表达式, views视图函数,参数,别名),
- ]
- 参数说明:
- 一个正则表达式字符串
- 一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
- 可选的要传递给视图函数的默认参数(字典形式)
- 一个可选的name参数
1. 单一路由对应
- url(r'^index$', views.index)
2. 基于正则的路由
- # $
- url(r'^index/(\d{4})$',views.index)
- #无命名分组
- url(r'^index/(\d{4})/(\d{2})',views.index)
- #有命名分组
- url(r'^index/(?P<year>\d{4})/(?P<month>\d{2})',views.index)
- ############################无命名
- #-----------------() 相当于传参数
- url(r'^index/(\d{4})',views.index)
- def index(request,arg):
- return HttpResponse(arg)
- #url访问http://127.0.0.1:8000/index/1113
- #-----------------() 接受两个参数
- url(r'^index/(\d{4})/(\d{2})',views.index)
- def index(request,arg,arg1):
- return HttpResponse("year: %s month: %s"%(arg,arg1))
- #url访问http://127.0.0.1:8000/index/2017/06
- year: 2017 month: 06
- ############################有命名
- url(r'^index/(?P<year>\d{4})/(?P<month>\d{2})',views.index)
- def index(request,year,month):
- return HttpResponse("year: %s month: %s"%(year,month))
- #url访问http://127.0.0.1:8000/index/2017/06
- year: 2017 month: 06
- 有无命名分组 演示
有无命名分组 演示
3. 为路由映射设置名称
- #应用一:
- url(r'^index',views.index,name="arg")
- {{ url "arg" }} 匹配index
- {{ url "arg" i}}
- #应用二:
- reverse反向获取url
- ##############根据url反生成名字
- from django.shortcuts import reverse
- url(r'^index',views.index,name="arg")
- def index(request):
- v = reverse("arg")
- print(v)
- return HttpResponse()
- #用户访问http://127.0.0.1:8000/index
- /index
- ##############根据url改变url
- url(r'^index/(\d+)/',views.index,name="n1")
- def index(request,xx):
- v = reverse('n1',args=(1,))
- print(v)
- return HttpResponse("...")
- #访问http://127.0.0.1:8000/index/222/
- /index/1/
- reverse示例 演示
reverse示例 演示
4. 路由分发
- url(r'^app01/',include("app01.urls"))
- url(r'^app02/',include("app02.urls"))
- #没有匹配成功,返回默认页面
- url(r'^',include("views.default"))
十一、Model
a. 创建表
- from django.db import models
- class User_type(models.Model):
- uid = models.BigAutoField(primary_key=True)
- title = models.CharField(max_length=32)
- class User_info(models.Model):
- name = models.CharField(max_length=32)
- age = models.CharField(max_length=32)
- ut = models.ForeignKey("User_type")
- python3 manage.py makemigrations
- python3 manage.py migrate
- ---------------------其它---------------------
- class part(models.Model):
- cid = models.BigAutoField(primary_key=True)
- title = models.CharField(max_length=32,null=False)
- class student(models.Model):
- sid = models.BigAutoField(primary_key=True)
- name = models.CharField(max_length=32,null=False)
- pub_data=models.DateField()
- age = models.IntegerField(default=18)
- # 新增加的列 如果原先表里有值,写default
- ug = models.ForeignKey("part",null=True) #如果新增加外键,加null=True
b. ORM操作
- #增
- # models.User_type.objects.create(title="黑金用户")
- # obj = models.User_type(title="小白用户")
- # obj.save()
- #删
- #models.User_type.objects.filter(title="小白用户").delete() # 删除指定条件的数据
- #改
- #models.User_type.objects.filter(title="黑金用户").update(title="黑卡用户") # 修改指定条件的数据
- #查
- # models.User_type.objects.get(title="大白用户") # 获取单条数据,不存在则报错(不建议)
- # models.User_type.objects.all() # 获取全部
- # models.User_type.objects.filter(title="小白用户") # 获取指定条件的数据
- # models.User_type.objects.exclude(title="黄金用户") # 排除指定条件的数据
- 基本增删改查
基本增删改查
- # 获取个数
- models.User_info.objects.filter(age=18).count()
- # 大于 小于
- # models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值
- # models.Tb1.objects.filter(id__gte=1) # 获取id大于等于1的值
- # models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值
- # models.Tb1.objects.filter(id__lte=10) # 获取id小于10的值
- # models.Tb1.objects.filter(id__gt=1,id__lt=10) # 获取id大于1 且 小于10的值
- #in
- models.User_info.objects.filter(age__in=[19]) # in
- models.User_info.objects.exclude(age__in=[19]) # not in
- # isnull
- models.User_info.objects.filter(age__isnull=True) # age列为不为空
- models.User_info.objects.filter(age__isnull=False) # age列是不是 不为空
- # contains
- # models.Tb1.objects.filter(name__contains="ven")
- # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
- # models.Tb1.objects.exclude(name__icontains="ven")
- # range
- # models.Tb1.objects.filter(id__range=[1, 5]) # 范围bettwen and
- #开始 结束
- # startswith,istartswith, endswith, iendswith
- #order_by
- #models.User_info.objects.all().order_by("id") # asc
- #models.User_info.objects.all().order_by("-id") # desc
- # models.Tb1.objects.filter(name='seven').order_by('id') # asc
- # models.Tb1.objects.filter(name='seven').order_by('-id') # desc
- #group by #后面出现filter代表having
- from django.db.models import Count
- #models.User_info.objects.values("name","age").annotate() #没有起作用
- #SELECT "app01_user_info"."name", "app01_user_info"."age" FROM "app01_user_info"
- #models.User_info.objects.values("age").annotate(xxx=Count("age"))
- #SELECT "app01_user_info"."age", COUNT("app01_user_info"."age") AS "xxx" FROM "app01_user_info" GROUP BY "app01_user_info"."age"
- #models.User_info.objects.values("age").annotate(xxx=Count("age")).filter(xxx__gt=2) #年龄相同次数大于2的查出来
- #SELECT "app01_user_info"."age", COUNT("app01_user_info"."age") AS "xxx" FROM "app01_user_info" GROUP BY "app01_user_info"."age" HAVING COUNT("app01_user_info"."age") > 2
- #注意两次filter 第一次代表where 第二次代表having
- #models.User_info.objects.filter(id__gt=2).values("age").annotate(xxx=Count("age")).filter(xxx__gt=2)
- #SELECT "app01_user_info"."age", COUNT("app01_user_info"."age") AS "xxx" FROM "app01_user_info" WHERE "app01_user_info"."id" > 2 GROUP BY "app01_user_info"."age" HAVING COUNT("app01_user_info"."age") > 2
- 常用方法
常用方法
- # F
- # from django.db.models import F
- # models.User_info.objects.all().update(age=F("age")+5) # age列加5
- # Q
- # 方式一:
- # Q(nid__gt=10)
- # Q(nid=8) | Q(nid__gt=10)
- # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
- #-------------------------------以下三种查找方式相同效果
- # obj = models.User_info.objects.filter(id=307,name="egon")
- # condition ={
- # 'id':307,
- # 'name':'egon',
- # }
- # obj = models.User_info.objects.filter(**condition)
- #obj = models.User_info.objects.filter(Q(id=307) & Q(name="egon"))
- ---------------------------------
- # 方式二:
- # q1 = Q()
- # q1.connector = 'OR'
- # q1.children.append(('id', 1))
- # q1.children.append(('id', 10))
- # q1.children.append(('id', 9))
- # q2 = Q()
- # q2.connector = 'OR'
- # q2.children.append(('c1', 1))
- # q2.children.append(('c1', 10))
- # q2.children.append(('c1', 9))
- # q3 = Q()
- # q3.connector = 'AND'
- # q3.children.append(('id', 1))
- # q3.children.append(('id', 2))
- # q1.add(q3, 'OR')
- # con = Q()
- # con.add(q1, 'AND')
- # con.add(q2, 'AND')
- #(id=1 or id=10 or id=9 or (id=1 and id=2)) and (c1=1 or c1=10 or c1=9) #等于上面
- # models.Tb1.objects.filter(con)
- # Q演示
- condition_dict = {
- 'k1':[1,2,3,4],
- 'k2':[1,],
- 'k3':[11,]
- }
- con = Q()
- for k,v in condition_dict.items():
- q = Q()
- q.connector = 'OR'
- for i in v:
- q.children.append(('id',1))
- con.add(q,'AND')
- models.User_info.objects.filter(con)
- F Q 演示
F Q 演示
c. 多对多操作
方式一:通过外键创建第三张表
- class Boy(models.Model):
- name = models.CharField(max_length=32)
- class Girl(models.Model):
- nick = models.CharField(max_length=32)
- class Love(models.Model):
- b = models.ForeignKey("Boy")
- g = models.ForeignKey("Girl")
- class Meta:
- unique_together = [
- ("b","g"),
- ]
- #表里插入数据
- objs = [
- models.Boy(name='方少伟'),
- models.Boy(name='游勤斌'),
- models.Boy(name='于浩'),
- models.Boy(name='陈涛'),
- ]
- models.Boy.objects.bulk_create(objs,4)
- result = [
- models.Girl(nick='于浩姐姐'),
- models.Girl(nick='景甜'),
- models.Girl(nick='刘亦非'),
- models.Girl(nick='苍老师'),
- ]
- models.Girl.objects.bulk_create(result, 4)
- models.Love.objects.create(b_id=1,g_id=1)
- models.Love.objects.create(b_id=1,g_id=2)
- models.Love.objects.create(b_id=1,g_id=3)
- models.Love.objects.create(b_id=2,g_id=4)
- ################### 查找和我有关系的女孩 四种方式 ################
- obj = models.Boy.objects.filter(name="方少伟").first()
- love_list = obj.love_set.all()
- for row in love_list:
- print(row.g.nick)
- love_list = models.Love.objects.filter(b__name="方少伟")
- for row in love_list:
- print(row.g.nick)
- #下面两个效果好
- love_list = models.Love.objects.filter(b__name="方少伟").values("g__nick")
- for item in love_list:
- print(item["g__nick"])
- love_list = models.Love.objects.filter(b__name="方少伟").select_related("g")
- for obj in love_list:
- print(obj.g.nick)
- SQL演示
SQL演示
方式二:通过 ManyToManyField 创建第三张表
- class Boy(models.Model):
- name = models.CharField(max_length=32)
- m = models.ManyToManyField("Girl")
- class Girl(models.Model):
- nick = models.CharField(max_length=32)
- obj = models.Boy.objects.filter(name="方少伟").first()
- # print(obj.id,obj.name)
- # obj.m.add(2)
- # obj.m.add(1,3)
- # obj.m.add(*[4,])
- # obj.m.remove(2)
- # obj.m.remove(1,3)
- # obj.m.remove(*[4,])
- # obj.m.set([1,4,])
- # girl_list = obj.m.all()
- # girl_list = obj.m.filter(nick="苍老师")
- # obj.m.clear()
- obj = models.Girl.objects.filter(nick="苍老师").first()
- v = obj.boy_set.all()
- SQL 演示
SQL 演示
方式三:通过 外键 和 ManyToManyField 创建
- class Boy(models.Model):
- name = models.CharField(max_length=32)
- m = models.ManyToManyField("Girl",through="Love",through_fields=("b","g",))
- class Girl(models.Model):
- nick = models.CharField(max_length=32)
- class Love(models.Model):
- b = models.ForeignKey("Boy")
- g = models.ForeignKey("Girl")
- class Meta:
- unique_together = [
- ("b","g"),
- ]
- obj = models.Boy.objects.filter(name="方少伟").first()
- #只可以查或清空
- obj.m.clear()
- obj.m.all()
- SQL 操作
SQL 操作
d. 一对多
- 正向:
- filter() values,values_list() -> 跨表 fk__xxx
- objs = all()
- for obj in objs:
- obj.fk.
- 反向:
- filter() values,values_list() -> 跨表 表名称__xxx
- objs = all()
- for obj in objs:
- obj.表名称_set.all()
1.连表操作演示
- urlpatterns = [
- url(r'^test/', views.test),
- ]
urls
- class User_type(models.Model):
- uid = models.BigAutoField(primary_key=True)
- title = models.CharField(max_length=32)
- class User_info(models.Model):
- name = models.CharField(max_length=32)
- age = models.CharField(max_length=32)
- ut = models.ForeignKey("User_type")
- models.py
models.py
- def test(request):
- models.User_type.objects.create(title="普通用户")
- models.User_type.objects.create(title="白金用户")
- models.User_type.objects.create(title="黄金用户")
- models.User_info.objects.create(name="小鸡",age=18,ut_id=1)
- models.User_info.objects.create(name="小狗",age=18,ut_id=2)
- models.User_info.objects.create(name="小猫",age=18,ut_id=2)
- models.User_info.objects.create(name="小雨",age=18,ut_id=3)
- models.User_info.objects.create(name="大雨",age=18,ut_id=1)
- for i in range(300):
- name = "root" + str(i)
- models.User_info.objects.create(name=name, age=18, ut_id=1)
- #正向操作
- obj = models.User_info.objects.all().first()
- print(obj.name,obj.age,obj.ut.title)
- #反向操作 obj.表名小写_set.all()
- obj = models.User_type.objects.all().first()
- for row in obj.user_info_set.all():
- print(row.name,row.age)
- result = models.User_type.objects.all()
- for item in result:
- print(item.title,item.user_info_set.all())
- print(item.user_info_set.filter(name="小雨"))
- #字典格式
- result = models.User_info.objects.all().values("id","name")
- for row in result:
- print(row)
- #字典格式查的时候跨表
- result = models.User_info.objects.all().values("id","name","ut__title")
- for row in result:
- print(row["id"],row["name"],row["ut__title"])
- # 元组格式
- # result = models.User_info.objects.all().values_list("id","name")
- # for row in result:
- # print(row)
- return HttpResponse(".....")
- views.py
views.py
十二、ORM操作
- 操作数据行:---------(在views中操作)
- 增
- models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs
- obj = models.Tb1(c1='xx', c2='oo')
- obj.save()
- 删
- models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据
- 改
- models.Tb1.objects.filter(name='seven').update(gender='') # 将指定条件的数据更新,均支持 **kwargs
- obj = models.Tb1.objects.get(id=1)
- obj.c1 = ''
- obj.save() # 修改单条数据
- 查
- models.Tb1.objects.get(id=123) # 获取单条数据,不存在则报错(不建议)
- models.Tb1.objects.all() # 获取全部
- models.Tb1.objects.filter(name='seven') # 获取指定条件的数据
基本增、删、改、查
- # 获取个数
- #
- # models.Tb1.objects.filter(name='seven').count()
- # 大于,小于
- #
- # models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值
- # models.Tb1.objects.filter(id__gte=1) # 获取id大于等于1的值
- # models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值
- # models.Tb1.objects.filter(id__lte=10) # 获取id小于10的值
- # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值
- # in
- #
- # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
- # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in
- # isnull
- # Entry.objects.filter(pub_date__isnull=True)
- # contains
- #
- # models.Tb1.objects.filter(name__contains="ven")
- # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
- # models.Tb1.objects.exclude(name__icontains="ven")
- # range
- #
- # models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and
- # 其他类似
- #
- # startswith,istartswith, endswith, iendswith,
- # order by
- #
- # models.Tb1.objects.filter(name='seven').order_by('id') # asc
- # models.Tb1.objects.filter(name='seven').order_by('-id') # desc
- # group by
- #
- # from django.db.models import Count, Min, Max, Sum
- # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
- # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
- # limit 、offset
- #
- # models.Tb1.objects.all()[10:20]
- # regex正则匹配,iregex 不区分大小写
- #
- # Entry.objects.get(title__regex=r'^(An?|The) +')
- # Entry.objects.get(title__iregex=r'^(an?|the) +')
- # date
- #
- # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
- # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))
- # year
- #
- # Entry.objects.filter(pub_date__year=2005)
- # Entry.objects.filter(pub_date__year__gte=2005)
- # month
- #
- # Entry.objects.filter(pub_date__month=12)
- # Entry.objects.filter(pub_date__month__gte=6)
- # day
- #
- # Entry.objects.filter(pub_date__day=3)
- # Entry.objects.filter(pub_date__day__gte=3)
- # week_day
- #
- # Entry.objects.filter(pub_date__week_day=2)
- # Entry.objects.filter(pub_date__week_day__gte=2)
- # hour
- #
- # Event.objects.filter(timestamp__hour=23)
- # Event.objects.filter(time__hour=5)
- # Event.objects.filter(timestamp__hour__gte=12)
- # minute
- #
- # Event.objects.filter(timestamp__minute=29)
- # Event.objects.filter(time__minute=46)
- # Event.objects.filter(timestamp__minute__gte=29)
- # second
- #
- # Event.objects.filter(timestamp__second=31)
- # Event.objects.filter(time__second=2)
- # Event.objects.filter(timestamp__second__gte=31)
操作---进阶
- # extra #额外查询条件以及相关表,排序
- #
- # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
- # a. 映射
- # select
- # select_params=None
- # select 此处 from 表
- # b. 条件
- # where=None
- # params=None,
- # select * from 表 where 此处
- # c. 表
- # tables
- # select * from 表,此处
- # c. 排序
- # order_by=None
- # select * from 表 order by 此处
- # Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
- # Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
- # Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
- # Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])
- # F #更新时用于获取原来的值
- from django.db.models import F
- models.Tb1.objects.update(num=F('num')+1)
- # Q #用于构造复杂查询条件
- # 应用一:
- models.UserInfo.objects.filter(Q(id__gt=1))
- models.UserInfo.objects.filter(Q(id=8) | Q(id=2))
- models.UserInfo.objects.filter(Q(id=8) & Q(id=2))
- # 应用二:
- # con = Q()
- # q1 = Q()
- # q1.connector = 'OR'
- # q1.children.append(('id', 1))
- # q1.children.append(('id', 10))
- # q1.children.append(('id', 9))
- # q2 = Q()
- # q2.connector = 'OR'
- # q2.children.append(('c1', 1))
- # q2.children.append(('c1', 10))
- # q2.children.append(('c1', 9))
- # con.add(q1, 'AND')
- # con.add(q2, 'AND')
- #
- # models.Tb1.objects.filter(con)
- # 执行原生SQL
- #
- # from django.db import connection, connections
- # cursor = connection.cursor() # cursor = connections['default'].cursor()
- # cursor.execute("""SELECT * from auth_user where id = %s""", [1])
- # row = cursor.fetchone()
操级---高级
- ##################################################################
- # PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET #
- ##################################################################
- def all(self)
- # 获取所有的数据对象
- def filter(self, *args, **kwargs)
- # 条件查询
- # 条件可以是:参数,字典,Q
- def exclude(self, *args, **kwargs)
- # 条件查询
- # 条件可以是:参数,字典,Q
- def select_related(self, *fields)
- 性能相关:表之间进行join连表操作,一次性获取关联的数据。
- model.tb.objects.all().select_related()
- model.tb.objects.all().select_related('外键字段')
- model.tb.objects.all().select_related('外键字段__外键字段')
- def prefetch_related(self, *lookups)
- 性能相关:多表连表操作时速度会慢,使用其执行多次SQL查询在Python代码中实现连表操作。
- # 获取所有用户表
- # 获取用户类型表where id in (用户表中的查到的所有用户ID)
- models.UserInfo.objects.prefetch_related('外键字段')
- from django.db.models import Count, Case, When, IntegerField
- Article.objects.annotate(
- numviews=Count(Case(
- When(readership__what_time__lt=treshold, then=1),
- output_field=CharField(),
- ))
- )
- students = Student.objects.all().annotate(num_excused_absences=models.Sum(
- models.Case(
- models.When(absence__type='Excused', then=1),
- default=0,
- output_field=models.IntegerField()
- )))
- def annotate(self, *args, **kwargs)
- # 用于实现聚合group by查询
- from django.db.models import Count, Avg, Max, Min, Sum
- v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id'))
- # SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id
- v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')).filter(uid__gt=1)
- # SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1
- v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id',distinct=True)).filter(uid__gt=1)
- # SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1
- def distinct(self, *field_names)
- # 用于distinct去重
- models.UserInfo.objects.values('nid').distinct()
- # select distinct nid from userinfo
- 注:只有在PostgreSQL中才能使用distinct进行去重
- def order_by(self, *field_names)
- # 用于排序
- models.UserInfo.objects.all().order_by('-id','age')
- def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
- # 构造额外的查询条件或者映射,如:子查询
- Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
- Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
- Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
- Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])
- def reverse(self):
- # 倒序
- models.UserInfo.objects.all().order_by('-nid').reverse()
- # 注:如果存在order_by,reverse则是倒序,如果多个排序则一一倒序
- def defer(self, *fields):
- models.UserInfo.objects.defer('username','id')
- 或
- models.UserInfo.objects.filter(...).defer('username','id')
- #映射中排除某列数据
- def only(self, *fields):
- #仅取某个表中的数据
- models.UserInfo.objects.only('username','id')
- 或
- models.UserInfo.objects.filter(...).only('username','id')
- def using(self, alias):
- 指定使用的数据库,参数为别名(setting中的设置)
- ##################################################
- # PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS #
- ##################################################
- def raw(self, raw_query, params=None, translations=None, using=None):
- # 执行原生SQL
- models.UserInfo.objects.raw('select * from userinfo')
- # 如果SQL是其他表时,必须将名字设置为当前UserInfo对象的主键列名
- models.UserInfo.objects.raw('select id as nid from 其他表')
- # 为原生SQL设置参数
- models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,])
- # 将获取的到列名转换为指定列名
- name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
- Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)
- # 指定数据库
- models.UserInfo.objects.raw('select * from userinfo', using="default")
- ################### 原生SQL ###################
- from django.db import connection, connections
- cursor = connection.cursor() # cursor = connections['default'].cursor()
- cursor.execute("""SELECT * from auth_user where id = %s""", [1])
- row = cursor.fetchone() # fetchall()/fetchmany(..)
- def values(self, *fields):
- # 获取每行数据为字典格式
- def values_list(self, *fields, **kwargs):
- # 获取每行数据为元祖
- def dates(self, field_name, kind, order='ASC'):
- # 根据时间进行某一部分进行去重查找并截取指定内容
- # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日)
- # order只能是:"ASC" "DESC"
- # 并获取转换后的时间
- - year : 年-01-01
- - month: 年-月-01
- - day : 年-月-日
- models.DatePlus.objects.dates('ctime','day','DESC')
- def datetimes(self, field_name, kind, order='ASC', tzinfo=None):
- # 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间
- # kind只能是 "year", "month", "day", "hour", "minute", "second"
- # order只能是:"ASC" "DESC"
- # tzinfo时区对象
- models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC)
- models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai'))
- """
- pip3 install pytz
- import pytz
- pytz.all_timezones
- pytz.timezone(‘Asia/Shanghai’)
- """
- def none(self):
- # 空QuerySet对象
- ####################################
- # METHODS THAT DO DATABASE QUERIES #
- ####################################
- def aggregate(self, *args, **kwargs):
- # 聚合函数,获取字典类型聚合结果
- from django.db.models import Count, Avg, Max, Min, Sum
- result = models.UserInfo.objects.aggregate(k=Count('u_id', distinct=True), n=Count('nid'))
- ===> {'k': 3, 'n': 4}
- def count(self):
- # 获取个数
- def get(self, *args, **kwargs):
- # 获取单个对象
- def create(self, **kwargs):
- # 创建对象
- def bulk_create(self, objs, batch_size=None):
- # 批量插入
- # batch_size表示一次插入的个数
- objs = [
- models.DDD(name='r11'),
- models.DDD(name='r22')
- ]
- models.DDD.objects.bulk_create(objs, 10)
- def get_or_create(self, defaults=None, **kwargs):
- # 如果存在,则获取,否则,创建
- # defaults 指定创建时,其他字段的值
- obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '','u_id': 2, 't_id': 2})
- def update_or_create(self, defaults=None, **kwargs):
- # 如果存在,则更新,否则,创建
- # defaults 指定创建时或更新时的其他字段
- obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '','u_id': 2, 't_id': 1})
- def first(self):
- # 获取第一个
- def last(self):
- # 获取最后一个
- def in_bulk(self, id_list=None):
- # 根据主键ID进行查找
- id_list = [11,21,31]
- models.DDD.objects.in_bulk(id_list)
- def delete(self):
- # 删除
- def update(self, **kwargs):
- # 更新
- def exists(self):
- # 是否有结果
- 其他操作
其他操作
十三、多表关系以及参数
- ForeignKey(ForeignObject) # ForeignObject(RelatedField)
- to, # 要进行关联的表名
- to_field=None, # 要关联的表中的字段名称
- on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为
- - 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(可执行对象)
- def func():
- return 10
- class MyModel(models.Model):
- user = models.ForeignKey(
- to="User",
- to_field="id"
- on_delete=models.SET(func),)
- related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
- related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
- limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件:
- # 如:
- - limit_choices_to={'nid__gt': 5}
- - limit_choices_to=lambda : {'nid__gt': 5}
- from django.db.models import Q
- - limit_choices_to=Q(nid__gt=10)
- - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
- - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
- db_constraint=True # 是否在数据库中创建外键约束
- parent_link=False # 在Admin中是否显示关联数据
- OneToOneField(ForeignKey)
- to, # 要进行关联的表名
- to_field=None # 要关联的表中的字段名称
- on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为
- ###### 对于一对一 ######
- # 1. 一对一其实就是 一对多 + 唯一索引
- # 2.当两个类之间有继承关系时,默认会创建一个一对一字段
- # 如下会在A表中额外增加一个c_ptr_id列且唯一:
- class C(models.Model):
- nid = models.AutoField(primary_key=True)
- part = models.CharField(max_length=12)
- class A(C):
- id = models.AutoField(primary_key=True)
- code = models.CharField(max_length=1)
- ManyToManyField(RelatedField)
- to, # 要进行关联的表名
- related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
- related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
- limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件:
- # 如:
- - limit_choices_to={'nid__gt': 5}
- - limit_choices_to=lambda : {'nid__gt': 5}
- from django.db.models import Q
- - limit_choices_to=Q(nid__gt=10)
- - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
- - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
- symmetrical=None, # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段
- # 做如下操作时,不同的symmetrical会有不同的可选字段
- models.BB.objects.filter(...)
- # 可选字段有:code, id, m1
- class BB(models.Model):
- code = models.CharField(max_length=12)
- m1 = models.ManyToManyField('self',symmetrical=True)
- # 可选字段有: bb, code, id, m1
- class BB(models.Model):
- code = models.CharField(max_length=12)
- m1 = models.ManyToManyField('self',symmetrical=False)
- through=None, # 自定义第三张表时,使用字段用于指定关系表
- through_fields=None, # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
- from django.db import models
- class Person(models.Model):
- name = models.CharField(max_length=50)
- class Group(models.Model):
- name = models.CharField(max_length=128)
- members = models.ManyToManyField(
- Person,
- through='Membership',
- through_fields=('group', 'person'),
- )
- class Membership(models.Model):
- group = models.ForeignKey(Group, on_delete=models.CASCADE)
- person = models.ForeignKey(Person, on_delete=models.CASCADE)
- inviter = models.ForeignKey(
- Person,
- on_delete=models.CASCADE,
- related_name="membership_invites",
- )
- invite_reason = models.CharField(max_length=64)
- db_constraint=True, # 是否在数据库中创建外键约束
- db_table=None, # 默认创建第三张表时,数据库中表的名称
多表关系以及参数
十四、MVC,MTV
- models(数据库,模型) views(html模板) controllers(业务逻辑处理) --> MVC
- models(数据库,模型) templates(html模板) views(业务逻辑处理) --> MTV
- Django -----基于-----> MTV
十五、事务
示例一:
- try:
- from django.db import transaction
- with transaction.atomic():
- models.UpDown.objects.create(user_id=user_id,article_id=article_id,up=False)
- models.Article.objects.filter(nid=article_id).update(down_count=F('down_count')+1)
- except Exception as e:
- response['status'] = False
- response['msg'] = str(e)
示例二:
- #函数里面有数据库操作,加在函数上
- from django.db.transaction import atomic
- @atomic
- def cmd(self):
- model.....
- model.....
十六、随机生成验证码
- # import random
- # print(random.random()) #0-1的小数
- # print(random.randint(1,3)) #包括1和3
- # print("--",random.randrange(1,3)) #不包括1和3
- #随机生成四位验证码
- import random
- checkcode = ''
- for i in range(4):
- current = random.randrange(0,4)
- if current != i:
- temp = chr(random.randint(65,90))
- else:
- temp = random.randint(0,9)
- checkcode += str(temp)
- print(checkcode)
- #KS3G
- #随机生成8位验证码
- import string
- print(string.ascii_lowercase)
- #abcdefghijklmnopqrstuvwxyz
- print(string.digits)
- #
- obj = random.sample(string.ascii_lowercase+string.digits,8)
- print(obj)
- #['i', 'm', 'o', '9', '6', 'p', 'g', '0']
- row = "".join(random.sample(string.ascii_lowercase+string.digits,8))
- print(row)
- #417x6kyt
十七、AEC(高级加密)
- #3.6安装 pip3 install pycryptodome
- #mac pip3 install pycrypto
示例:
- ############################### 加密 ##############################
- from Crypto.Cipher import AES
- def encrypt(message):
- key = b'dfdsdfsasdfdsdfs' #key必须是16的整数倍
- cipher = AES.new(key, AES.MODE_CBC, key) #创建对象
- ----------------------------------------------
- #先转成字节,把数据拼够16字节的整数倍
- ba_data = bytearray(message,encoding='utf-8') #把数据转成bytearray(byte的数组),bytearray只能追加数字,默认把数字转成字节
- v1 = len(ba_data)
- v2 = v1 % 16
- if v2 == 0:
- v3 = 16
- else:
- v3 = 16 - v2 #v3是追加的长度
- for i in range(v3):
- ba_data.append(v3) #bytearray只能追加数字,默认把数字转成字节
- final_data = ba_data.decode('utf-8')
- ----------------------------------------------
- msg = cipher.encrypt(final_data) #要加密的字符串,必须是16个字节或16个字节的倍数,加密后是byte格式
- return msg
- ############################### 解密 ##############################
- def decrypt(msg):
- key = b'dfdsdfsasdfdsdfs'
- cipher = AES.new(key, AES.MODE_CBC, key)
- result = cipher.decrypt(msg) #把加密后的字节解密成不加密的字节
- data = result[0:-result[-1]]
- return str(data,encoding='utf-8')
十八、前端Format方法
为字符串创建Format方法,用于字符串格式化
- String.prototype.Format=function (arg) {
- //console.log(this,arg); //this,当前调用方法的字符串,arg为Format方法传入的参数
- //return ''; //return,格式化之后获取的新内容,return啥就替换为啥
- var temp = this.replace(/\{(\w+)\}/g,function (k,kk) {
- // k相当于{(\w+)},kk相当于(\w+)要替换的东西,arg一般是一个字典
- return arg[kk];
- });
- return temp;
- };
- #调用
- a = {nid}
- b = {"nid":""}
- a.Format(b)
十九、高级使用----反射
- 反射:
- getattr(obj,'xxx')
- 导入模块:
- import re
- 'django.middleware.clickjacking.XFrameOptionsMiddleware'
- m = importlib.import_module('django.middleware.clickjacking')
- cls = getattr(m,'XFrameOptionsMiddleware')
- cls()
- 面向对象:
- #示例一: 之后爬虫使用
- class Foo:
- def __init__(self):
- pass
- @classmethod
- def instance(cls):
- return cls()
- def process(self):
- pass
- if hasattr(Foo,'instance'):
- obj = Foo.instance()
- else:
- obj = Foo()
- obj.process()
- #示例二:
- class A:
- def f1(self):
- self.f2()
- def f2(self):
- print('A.f2')
- class B(A):
- def f2(self):
- print("B.f2")
- obj = B()
- obj.f1()
二十、request
1 客户端向服务端发送多层字典的值
- obj = {
- 'data':{
- "k1":"v1",
- "k2":"v2"
- },
- 'status': True
- }
- #json发送
- requests.post("http://www.baidu.com",json=obj)
- #发送数据内部默认处理(会在内部把字典obj json.dumps序列成字符串,发送给服务端)
- #body: json.dumps(obj)
- #headers= {'content-type':'application/json'} #默认加入
- #只有设置如下请求头request.post才能接受,但不能接受多层字典的数据,接受第二层字典只能接受key,不能接受value
- #headers= {'content-type':"application/x-www-form-urlencoded"}
- #接受上面格式发送的数据
- if request.method == 'POST':
- obj = json.loads(request.body.decode('utf-8'))
2 request.post 和request.body
- #接受
- requests.boby
- - 请求体原生的值
- requests.POST
- - 根据特殊的请求头从requests.boby获取数据,不能接受多层字典的数据
3 三者相等
- #方式一:
- requests.post("http://www.baidu.com",json=obj)
- #方式二:
- requests.post(
- url="http://www.baidu.com",
- headers={'content-type':'application/json'},
- data=json.dumps(obj)
- )
- #方式三():
- requests.post(
- url="http://www.baidu.com",
- headers={'content-type':'application/json'},
- data=bytes(json.dumps(obj),encoding="utf-8")
- )
二十一、hashlib加密(md5)
md5加密
- m = hashlib.md5()
- m.update(bytes(new_key,encoding='utf-8')) #里面是字节数据
- md5_key = m.hexdigest() #返回值是字符窜类型
二十二、命令行执行Django脚本
- - #效仿manage.py加入的环境变量在脚本的文件加入
- - #手动注册django所有的APP
- import sys,os
- -----------------------举例
- from audit.backend import user_interactive
- if __name__ == "__main__":
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "LuffyAudit.settings")
- import django
- django.setup() #手动注册django所有的APP
- -----------------------举例
- obj = user_interactive.UserShell(sys.argv)
- obj.start()
二十三、API验证
- API验证:
- a. 发令牌: 静态
- PS: 隐患 key被别人获取
- b. 动态令牌
- PS: (问题越严重)用户生成的每个令牌被黑客获取到,都会破解
- c. 高级版本
- PS: 黑客网速快,会窃取, so要对数据加密
- d. 终极版本
- 特点:
- 为什么要用API ?
- - 数据在传输过程中,保证数据安全
- 你是如何设计的 ?
- - Tornado 中的加密Cookie类似
- - 创建动态key md5(key + time)|time (Tornado中也是这么做)
- - 限制
- - 第一关: 时间
- - 第二关: 算法规则
- - 第三关: 已访问的记录
- PS: 黑客网速快,会窃取, so要对数据加密
1 客户端和服务端都有一个相同的key
- 客户端把key发给服务端,服务端拿着自己的key和客户端的key做比较
- ###客户端
- import time
- import requests
- key = "asdfasdfasdfasdf098712sdfs"
- response = requests.get("http://127.0.0.1:8000/api/asset.html",headers={'OpenKey':key})
- print(response.text)
- ###服务端
- #print(request.META)
- key = request.META.get("HTTP_OPENKEY")
- if key != settings.AUTH_KEY:
- return HttpResponse("验证失败")
2 key和时间
- #客户端和服务端都有一个相同的key
- #客户端把加密key和当前时间发给服务端,服务端收到后把客户端发来的时间和自己的key加密
- #然后把加密后的字串和客户端的字串比较
- #客户端
- import time
- import requests
- import hashlib
- ctime = time.time()
- key = "asdfasdfasdfasdf098712sdfs"
- new_key = "%s|%s" %(key,ctime,)
- m = hashlib.md5()
- m.update(bytes(new_key,encoding='utf-8')) #里面是字节数据
- md5_key = m.hexdigest() #返回值是字符串类型
- md5_time_key = "%s|%s" %(md5_key,ctime)
- response = requests.get("http://127.0.0.1:8000/api/asset.html",headers={'OpenKey':md5_time_key})
- print(response.text)
- #服务端
- client_md5_time_key = request.META.get("HTTP_OPENKEY")
- client_md5_key,client_ctime = client_md5_time_key.split("|")
- temp = "%s|%s"%(settings.AUTH_KEY,client_ctime)
- m = hashlib.md5()
- m.update(bytes(temp, encoding='utf-8'))
- server_md5_key = m.hexdigest()
- if server_md5_key != client_md5_key:
- return HttpResponse("验证失败")
3 高级版本
- #客户端和服务端都有一个相同的key
- #客户端把加密key和当前时间发给服务端
- #服务端验证:
- #1)服务端判断服务器当前的时间是否比客户端时间快10s,如果在10s内通过,有效的杜绝了案例二成千上万的key
- #2)服务器获取客户端时间和自己key加密然后和 客户端获取到的key比较
- #3)删除与现在时间相差10s的数据(之后用memcache,redis)
- #3)在字典里判断是否有这个key,如果有不通过,没有加入字典(之后用memcache,redis)
- #客户端
- import time
- import requests
- import hashlib
- ctime = time.time()
- key = "asdfasdfasdfasdf098712sdfs"
- new_key = "%s|%s" %(key,ctime,)
- m = hashlib.md5()
- m.update(bytes(new_key,encoding='utf-8')) #里面是字节数据
- md5_key = m.hexdigest() #返回值是字符串类型
- md5_time_key = "%s|%s" %(md5_key,ctime)
- print(md5_time_key)
- response = requests.get("http://127.0.0.1:8000/api/asset.html",headers={'OpenKey':md5_time_key})
- #黑客获取调用
- #response = requests.get("http://127.0.0.1:8000/api/asset.html",headers={'OpenKey':"f610077a7001c53b5a74868c5544b388|1501514254.455578"})
- print(response.text)
- #服务端
- api_key_record ={
- "76942d662d98ebe3b920a7b791bf5040|1501510243.92804":1501510243.92804,
- }
- def asset(request):
- client_md5_time_key = request.META.get("HTTP_OPENKEY")
- client_md5_key,client_ctime = client_md5_time_key.split("|")
- client_ctime = float(client_ctime)
- server_ctime = time.time()
- #第一关 时间关
- if server_ctime - client_ctime > 10:
- return HttpResponse("第一关 小伙子,别虎我,太长了")
- #第二关 客户端时间和服务端key加密和 客户端的密钥对比
- temp = "%s|%s"%(settings.AUTH_KEY,client_ctime)
- m = hashlib.md5()
- m.update(bytes(temp, encoding='utf-8'))
- server_md5_key = m.hexdigest()
- if server_md5_key != client_md5_key:
- return HttpResponse("第二关 规则正确")
- #以后基于memcache,目前先写入内存删除超过10s的值
- for k in list(api_key_record.keys()):
- v = api_key_record[k]
- if server_ctime > v:
- del api_key_record[k]
- #第三关 判断字典里是否有之前访问的key,如果有不通过,没有加入字典
- if client_md5_time_key in api_key_record:
- return HttpResponse("第三关 已经有人来过了")
- else:
- api_key_record[client_md5_time_key] = client_ctime + 10
4 终极版本
- 注意: key 是从配置文件获取的
- 装饰器要返回Httpresponse对象
- __author__ = 'Administrator'
- from Crypto.Cipher import AES
- from lib.conf.config import settings
- def encrypt(message):
- """
- 数据加密
- :param message:
- :return:
- """
- key = settings.DATA_KEY
- cipher = AES.new(key, AES.MODE_CBC, key)
- ba_data = bytearray(message,encoding='utf-8')
- v1 = len(ba_data)
- v2 = v1 % 16
- if v2 == 0:
- v3 = 16
- else:
- v3 = 16 - v2
- for i in range(v3):
- ba_data.append(v3)
- final_data = ba_data.decode('utf-8')
- msg = cipher.encrypt(final_data) # 要加密的字符串,必须是16个字节或16个字节的倍数
- return msg
- def decrypt(msg):
- """
- 数据解密
- :param message:
- :return:
- """
- from Crypto.Cipher import AES
- key = settings.DATA_KEY
- cipher = AES.new(key, AES.MODE_CBC, key)
- result = cipher.decrypt(msg) # result = b'\xe8\xa6\x81\xe5\x8a\xa0\xe5\xaf\x86\xe5\x8a\xa0\xe5\xaf\x86\xe5\x8a\xa0sdfsd\t\t\t\t\t\t\t\t\t'
- data = result[0:-result[-1]]
- return str(data,encoding='utf-8')
- def auth():
- """
- API验证
- :return:
- """
- import time
- import requests
- import hashlib
- ctime = time.time()
- key = "asdfasdfasdfasdf098712sdfs"
- new_key = "%s|%s" %(key,ctime,)
- m = hashlib.md5()
- m.update(bytes(new_key,encoding='utf-8')) #里面是字节数据
- md5_key = m.hexdigest() #返回值是字符窜类型
- md5_time_key = "%s|%s" %(md5_key,ctime)
- return md5_time_key
lib/utils.py
- from Crypto.Cipher import AES
- import requests
- import json
- from lib.utils import encrypt
- from lib.utils import auth
- #对数据加密字典
- v1 = encrypt(json.dumps({"k1":"v1"})) #获取的是加密后的字节
- print(v1)
- response = requests.post(
- url="http://127.0.0.1:8000/api/asset.html",
- headers={'OpenKey':auth(),'content-type':'application/json'},
- data=v1
- )
- print(response.text)
客户端调用
- import json
- import hashlib
- from django.shortcuts import render,HttpResponse
- from repository import models
- from django.conf import settings
- from api.service import PluginManager
- import time
- import json
- from Crypto.Cipher import AES
- api_key_record ={
- "76942d662d98ebe3b920a7b791bf5040|1501510243.92804":1501510243.92804,
- }
- def decrypt(msg):
- key = b'dfdsdfsasdfdsdfs'
- cipher = AES.new(key, AES.MODE_CBC, key)
- result = cipher.decrypt(msg) # 把加密后的字节解密成不加密的字节
- data = result[0:-result[-1]]
- return str(data, encoding='utf-8')
- def outer(func):
- def wrapper(request):
- client_md5_time_key = request.META.get("HTTP_OPENKEY")
- client_md5_key, client_ctime = client_md5_time_key.split("|")
- client_ctime = float(client_ctime)
- server_ctime = time.time()
- # 第一关 时间关
- if server_ctime - client_ctime > 30:
- return HttpResponse("第一关 小伙子,别虎我,太长了")
- # 第二关 客户端时间和服务端key加密和 客户端的密钥对比
- temp = "%s|%s" % (settings.AUTH_KEY, client_ctime)
- m = hashlib.md5()
- m.update(bytes(temp, encoding='utf-8'))
- server_md5_key = m.hexdigest()
- if server_md5_key != client_md5_key:
- return HttpResponse("第二关 规则正确")
- # 以后基于memcache,目前先写入内存删除超过10s的值
- for k in list(api_key_record.keys()):
- v = api_key_record[k]
- if server_ctime > v:
- del api_key_record[k]
- # 第三关 判断字典里是否有之前访问的key,如果有不通过,没有加入字典
- if client_md5_time_key in api_key_record:
- return HttpResponse("第三关 已经有人来过了")
- else:
- api_key_record[client_md5_time_key] = client_ctime + 10
- obj = func(request)
- return obj
- return wrapper
- @outer
- def asset(request):
- if request.method == 'GET':
- ys = '重要的不能被闲杂人等看的数据'
- return HttpResponse(ys)
- elif request.method == 'POST':
- server_info = decrypt(request.body)
- server_info = json.loads(server_info)
- # # 新资产信息
- # server_info = json.loads(request.body.decode('utf-8'))
- hostname = server_info['basic']['data']['hostname']
- # 老资产信息
- server_obj = models.Server.objects.filter(hostname=hostname).first()
- if not server_obj:
- return HttpResponse('当前主机名在资产中未录入')
- PluginManager(server_info,server_obj,hostname).exec_plugin()
- return HttpResponse("...")
服务端代码
二十四、KindEditor
1 进入官网
2 下载
官网下载:http://kindeditor.net/down.php
3 文件夹说明
- ├── asp asp示例
- ├── asp.net asp.net示例
- ├── attached 空文件夹,放置关联文件attached
- ├── examples HTML示例
- ├── jsp java示例
- ├── kindeditor-all-min.js 全部JS(压缩)
- ├── kindeditor-all.js 全部JS(未压缩)
- ├── kindeditor-min.js 仅KindEditor JS(压缩)
- ├── kindeditor.js 仅KindEditor JS(未压缩)
- ├── lang 支持语言
- ├── license.txt License
- ├── php PHP示例
- ├── plugins KindEditor内部使用的插件
- └── themes KindEditor主题
4 基本使用
- <textarea name="content" id="content"></textarea>
- <script src="/static/jquery-1.12.4.js"></script>
- <script src="/static/plugins/kind-editor/kindeditor-all.js"></script>
- <script>
- $(function () {
- initKindEditor();
- });
- function initKindEditor() {
- var kind = KindEditor.create('#content', {
- width: '100%', // 文本框宽度(可以百分比或像素)
- height: '300px', // 文本框高度(只能像素)
- minWidth: 200, // 最小宽度(数字)
- minHeight: 400 // 最小高度(数字)
- });
- }
- </script>
5 详细参数
http://kindeditor.net/docs/option.html
6 上传文件示例
- <!DOCTYPE html>
- <html>
- <head lang="en">
- <meta charset="UTF-8">
- <title></title>
- </head>
- <body>
- <div>
- <h1>文章内容</h1>
- {{ request.POST.content|safe }}
- </div>
- <form method="POST">
- <h1>请输入内容:</h1>
- {% csrf_token %}
- <div style="width: 500px; margin: 0 auto;">
- <textarea name="content" id="content"></textarea>
- </div>
- <input type="submit" value="提交"/>
- </form>
- <script src="/static/jquery-1.12.4.js"></script>
- <script src="/static/plugins/kind-editor/kindeditor-all.js"></script>
- <script>
- $(function () {
- initKindEditor();
- });
- function initKindEditor() {
- var a = 'kind';
- var kind = KindEditor.create('#content', {
- width: '100%', // 文本框宽度(可以百分比或像素)
- height: '300px', // 文本框高度(只能像素)
- minWidth: 200, // 最小宽度(数字)
- minHeight: 400, // 最小高度(数字)
- uploadJson: '/kind/upload_img/',
- extraFileUploadParams: {
- 'csrfmiddlewaretoken': '{{ csrf_token }}'
- },
- fileManagerJson: '/kind/file_manager/',
- allowPreviewEmoticons: true,
- allowImageUpload: true
- });
- }
- </script>
- </body>
- </html>
HTML
- import os
- import json
- import time
- from django.shortcuts import render
- from django.shortcuts import HttpResponse
- def index(request):
- """
- 首页
- :param request:
- :return:
- """
- return render(request, 'index.html')
- def upload_img(request):
- """
- 文件上传
- :param request:
- :return:
- """
- dic = {
- 'error': 0,
- 'url': '/static/imgs/20130809170025.png',
- 'message': '错误了...'
- }
- return HttpResponse(json.dumps(dic))
- def file_manager(request):
- """
- 文件管理
- :param request:
- :return:
- """
- dic = {}
- root_path = '/Users/wupeiqi/PycharmProjects/editors/static/'
- static_root_path = '/static/'
- request_path = request.GET.get('path')
- if request_path:
- abs_current_dir_path = os.path.join(root_path, request_path)
- move_up_dir_path = os.path.dirname(request_path.rstrip('/'))
- dic['moveup_dir_path'] = move_up_dir_path + '/' if move_up_dir_path else move_up_dir_path
- else:
- abs_current_dir_path = root_path
- dic['moveup_dir_path'] = ''
- dic['current_dir_path'] = request_path
- dic['current_url'] = os.path.join(static_root_path, request_path)
- file_list = []
- for item in os.listdir(abs_current_dir_path):
- abs_item_path = os.path.join(abs_current_dir_path, item)
- a, exts = os.path.splitext(item)
- is_dir = os.path.isdir(abs_item_path)
- if is_dir:
- temp = {
- 'is_dir': True,
- 'has_file': True,
- 'filesize': 0,
- 'dir_path': '',
- 'is_photo': False,
- 'filetype': '',
- 'filename': item,
- 'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path)))
- }
- else:
- temp = {
- 'is_dir': False,
- 'has_file': False,
- 'filesize': os.stat(abs_item_path).st_size,
- 'dir_path': '',
- 'is_photo': True if exts.lower() in ['.jpg', '.png', '.jpeg'] else False,
- 'filetype': exts.lower().strip('.'),
- 'filename': item,
- 'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path)))
- }
- file_list.append(temp)
- dic['file_list'] = file_list
- return HttpResponse(json.dumps(dic))
views
7 XSS过滤特殊标签
处理依赖
- pip3 install beautifulsoup4
- from bs4 import BeautifulSoup
- class XSSFilter(object):
- __instance = None
- def __init__(self):
- # XSS白名单
- self.valid_tags = {
- "font": ['color', 'size', 'face', 'style'],
- 'b': [],
- 'div': [],
- "span": [],
- "table": [
- 'border', 'cellspacing', 'cellpadding'
- ],
- 'th': [
- 'colspan', 'rowspan'
- ],
- 'td': [
- 'colspan', 'rowspan'
- ],
- "a": ['href', 'target', 'name'],
- "img": ['src', 'alt', 'title'],
- 'p': [
- 'align'
- ],
- "pre": ['class'],
- "hr": ['class'],
- 'strong': []
- }
- @classmethod
- def instance(cls):
- if not cls.__instance:
- obj = cls()
- cls.__instance = obj
- return cls.__instance
- def process(self, content):
- soup = BeautifulSoup(content, 'lxml')
- # 遍历所有HTML标签
- for tag in soup.find_all(recursive=True):
- # 判断标签名是否在白名单中
- if tag.name not in self.valid_tags:
- tag.hidden = True
- if tag.name not in ['html', 'body']:
- tag.hidden = True
- tag.clear()
- continue
- # 当前标签的所有属性白名单
- attr_rules = self.valid_tags[tag.name]
- keys = list(tag.attrs.keys())
- for key in keys:
- if key not in attr_rules:
- del tag[key]
- return soup.renderContents()
- if __name__ == '__main__':
- html = """<p class="title">
- <b>The Dormouse's story</b>
- </p>
- <p class="story">
- <div name='root'>
- Once upon a time there were three little sisters; and their names were
- <a href="http://example.com/elsie" class="sister c1" style='color:red;background-color:green;' id="link1"><!-- Elsie --></a>
- <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
- <a href="http://example.com/tillie" class="sister" id="link3">Tilffffffffffffflie</a>;
- and they lived at the bottom of a well.
- <script>alert(123)</script>
- </div>
- </p>
- <p class="story">...</p>"""
- v = XSSFilter.instance().process(html)
- print(v)
XSS示例
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- from bs4 import BeautifulSoup
- class XSSFilter(object):
- __instance = None
- def __init__(self):
- # XSS白名单
- self.valid_tags = {
- "font": ['color', 'size', 'face', 'style'],
- 'b': [],
- 'div': [],
- "span": [],
- "table": [
- 'border', 'cellspacing', 'cellpadding'
- ],
- 'th': [
- 'colspan', 'rowspan'
- ],
- 'td': [
- 'colspan', 'rowspan'
- ],
- "a": ['href', 'target', 'name'],
- "img": ['src', 'alt', 'title'],
- 'p': [
- 'align'
- ],
- "pre": ['class'],
- "hr": ['class'],
- 'strong': []
- }
- def __new__(cls, *args, **kwargs):
- """
- 单例模式
- :param cls:
- :param args:
- :param kwargs:
- :return:
- """
- if not cls.__instance:
- obj = object.__new__(cls, *args, **kwargs)
- cls.__instance = obj
- return cls.__instance
- def process(self, content):
- soup = BeautifulSoup(content, 'lxml')
- # 遍历所有HTML标签
- for tag in soup.find_all(recursive=True):
- # 判断标签名是否在白名单中
- if tag.name not in self.valid_tags:
- tag.hidden = True
- if tag.name not in ['html', 'body']:
- tag.hidden = True
- tag.clear()
- continue
- # 当前标签的所有属性白名单
- attr_rules = self.valid_tags[tag.name]
- keys = list(tag.attrs.keys())
- for key in keys:
- if key not in attr_rules:
- del tag[key]
- return soup.renderContents()
- if __name__ == '__main__':
- html = """<p class="title">
- <b>The Dormouse's story</b>
- </p>
- <p class="story">
- <div name='root'>
- Once upon a time there were three little sisters; and their names were
- <a href="http://example.com/elsie" class="sister c1" style='color:red;background-color:green;' id="link1"><!-- Elsie --></a>
- <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
- <a href="http://example.com/tillie" class="sister" id="link3">Tilffffffffffffflie</a>;
- and they lived at the bottom of a well.
- <script>alert(123)</script>
- </div>
- </p>
- <p class="story">...</p>"""
- obj = XSSFilter()
- v = obj.process(html)
- print(v)
基于__new__实现单例模式示例
8 示例图
二十五、Django多级评论
1 原理
- #多级评论原理简单原理,弄完之后发现基础白学了
- msg_list = [
- {'id':1,'content':'xxx','parent_id':None},
- {'id':2,'content':'xxx','parent_id':None},
- {'id':3,'content':'xxx','parent_id':None},
- {'id':4,'content':'xxx','parent_id':1},
- {'id':5,'content':'xxx','parent_id':4},
- {'id':6,'content':'xxx','parent_id':2},
- {'id':7,'content':'xxx','parent_id':5},
- {'id':8,'content':'xxx','parent_id':3},
- ]
- #python里面的apend之类的东西都是引用的原来数据的内从地址,对原数据进行操作的话
- #我们引用的数据也会发生一样的变化(字典列表之类的)
- #骗子的方法
- # for i in msg_list:
- # i['child']=[]
- # for i in range(len(msg_list)-1,-1,-1):
- # if msg_list[i]['parent_id']:
- # msg_list[msg_list[i]['parent_id'] - 1]['child'].append(msg_list[i])
- # new_msg_list = [i for i in msg_list if i['parent_id'] is None]
- # print(new_msg_list)
- #老师讲的方法
- # v=[row.setdefault('child',[]) for row in msg_list] #这和地下的第一个for循环的作用是一样的,给每一个元素加一个'child':[]
- # print(msg_list)
- #如果我们想加快索引(快点找到数据的话)就建一个字典的数据结构
- msg_list_dict={} #加快索引,节省时间
- for item in msg_list:
- item['child']=[]
- msg_list_dict[item['id']]=item #字典中key为item['id'],value为item
- #把字典数据结构填上数据,能够加快索引,而且我们数据还是占得原来的内从空间
- #我们只是引用了数据的内容空间,所以不存在新的数据结构浪费空间一说
- result=[]
- for item in msg_list:
- pid=item['parent_id']
- if pid: #如果parent_id不为空,说明它是子级,要把自己加入对应的父级
- msg_list_dict[pid]['child'].append(item)
- else: #如果为空,说明他是父级,要把它单独领出来用
- result.append(item)
- #result就是我们最终要的结果,因为这里面全是引用,所有数据的内存地址都没有变
- #只不过被多个数据结构引用了而已
- print(result)
2 精简版
- def comments(request,nid):
- res={'status':True,'data':None,'msg':None}
- try:
- comment_list = models.Comment.objects.filter(article_id=nid).values()
- com_list = list(comment_list) # 所有的评论,列表套字典
- com_list_dict = {} # 建立一个方便查找的数据结构字典
- for item in com_list: # 循环评论列表,给每一条评论加一个child:[]就是让他装对他回复的内容
- item['create_time'] = str(item['create_time'])
- item['child'] = []
- com_list_dict[item['nid']] = item
- result = []
- for item in com_list:
- rid = item['reply_id']
- if rid: # 如果reply_id不为空的话,那么就是说明他是子评论,我们要把他加入对应的评论后面
- com_list_dict[rid]['child'].append(item)
- else:
- result.append(item)
- print(result)
- # comment_str = comment_tree(result)
- # 这是在服务器上递归完之后,然后在传到前端,但是这样会增加服务器压力
- #所以这种方式我们直接就不用了
- res['data']=result
- except Exception as e:
- res['status']=False
- res['mag']=str(e)
- return HttpResponse(json.dumps(res))
views
- <style>
- .comment{
- margin-left:20px;
- }
- </style>
- <body>
- <div id="commentArea">
- </div>
- </body>
- <script src="/static/jquery-3.2.1.js"></script>
- <script>
- //自定义JS中字符串格式化方法
- String.prototype.Format=function (arg) {
- //console.log(this,arg); //this,当前调用方法的字符串,arg为Format方法传入的参数
- //return '666'; //return,格式化之后获取的新内容,return啥就替换为啥
- var temp = this.replace(/\{(\w+)\}/g,function (k,kk) {
- // k相当于{(\w+)},kk相当于(\w+)要替换的东西,arg一般是一个字典
- return arg[kk];
- });
- return temp;
- };
- $(function () {
- //发送Ajax请求,获取所有评论的信息
- //列表
- //JS生成结构
- var token=$.cookie('csrftoken');
- $.ajax({
- url:"/comments-{{ article_obj.nid }}.html",
- type:"GET",
- dataType:"JSON",
- success:function (arg) {
- if (arg.status){
- var comment=commentTree(arg.data);
- $('#commentArea').append(comment);
- }else{
- alert(arg.msg);
- }
- }
- })
- });
- //多级评论递归函数,js函数里面也有return,自己写js字符串格式化
- //pyhton中字符串的方法都是str下的,js中是String.prototype下找的
- function commentTree(commentList) {
- var comment_str="<div class='comment'>";
- $.each(commentList,function (k,row) {
- var temp="<div class='content'>{content}</div>".Format({content:row.content});
- comment_str += temp;
- if (row.child.length>0){
- comment_str += commentTree(row.child);
- }
- });
- comment_str += '</div>';
- return comment_str
- }
- </script>
html
二十六、REST framework
1. 什么是REST
- REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
- REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态
- REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
- 所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性
- 对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)
设计参考:http://www.ruanyifeng.com/blog/2014/05/restful_api.html
2. 目前如何实现 REST API ?
按照规则,根据不同的请求方式做出不同的处理,并且返回内容以及相应状态码
3. 什么是 Django REST framework?
Django REST framework是一个基于Django开发的app,用于快速搭建REST API。
安装:
- pip3 install djangorestframework
a. 快速使用
- INSTALLED_APPS = [
- ...
- 'rest_framework',
- ]
1.注册APP
- from rest_framework import routers
- from . import views
- router = routers.DefaultRouter()
- router.register(r'users', views.UserInfoViewSet)
- urlpatterns = [
- url(r'^', include(router.urls)),
- ]
2.注册路由
- from rest_framework import viewsets
- from . import models
- from . import serializers
- # ########### 1. 基本处理方式 ###########
- class UserInfoViewSet(viewsets.ModelViewSet):
- """
- API endpoint that allows users to be viewed or edited.
- """
- queryset = models.UserInfo.objects.all().order_by('-id')
- serializer_class = serializers.UserInfoSerializer
3.编写ViewSet,视图函数
- from rest_framework import serializers
- from . import models
- class UserInfoSerializer(serializers.HyperlinkedModelSerializer):
- class Meta:
- model = models.UserInfo
- # fields = ('id', 'username', 'pwd','ug') # fields = '__all__'
- exclude = ('ug',)
- depth = 1 # 0<=depth<=10
4.编写serializers,form验证以及数据库操作
PS:最终访问路径
- [GET] http://127.0.0.1:8000/api/users/
- [POST] http://127.0.0.1:8000/api/users/
- [GET] http://127.0.0.1:8000/api/users/7/
- [PUT] http://127.0.0.1:8000/api/users/7/
- [DELETE] http://127.0.0.1:8000/api/users/7/
b. 基于CBV
- from django.conf.urls import url,include
- from django.contrib import admin
- from . import views
- urlpatterns = [
- url(r'^users/$', views.UserList.as_view()),
- url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),
- ]
1.URL
- from rest_framework.views import APIView
- from rest_framework.response import Response
- from rest_framework.request import Request
- from rest_framework.parsers import JSONParser
- from . import models
- from . import serializers
- class UserList(APIView):
- def get(self, request, *args, **kwargs):
- user_list = models.UserInfo.objects.all()
- serializer = serializers.MySerializer(instance=user_list, many=True)
- return Response(serializer.data)
- def post(self, request, *args, **kwargs):
- data = JSONParser().parse(request)
- serializer = serializers.MySerializer(data=data)
- if serializer.is_valid():
- # print(serializer.data)
- # print(serializer.errors)
- # print(serializer.validated_data)
- # 如果有instance,则执行update方法;否则,执行create
- serializer.save()
- return Response(serializer.data, status=201)
- return Response(serializer.errors, status=400)
- class UserDetail(APIView):
- def get(self, request, *args, **kwargs):
- obj = models.UserInfo.objects.filter(pk=kwargs.get('pk')).first()
- serializer = serializers.MySerializer(obj)
- return Response(serializer.data)
- def delete(self, request, *args, **kwargs):
- obj = models.UserInfo.objects.filter(pk=kwargs.get('pk')).first()
- obj.delete()
- return Response(status=204)
- def put(self, request, *args, **kwargs):
- data = JSONParser().parse(request)
- obj = models.UserInfo.objects.filter(pk=kwargs.get('pk')).first()
- serializer = serializers.MySerializer(obj, data=data)
- if serializer.is_valid():
- serializer.save()
- return Response(serializer.data)
- return Response(serializer.errors, status=400)
2.编写视图函数
- from rest_framework import serializers
- from rest_framework.exceptions import ValidationError
- from . import models
- class MySerializer(serializers.Serializer):
- id = serializers.IntegerField(read_only=True)
- username = serializers.CharField(required=False, allow_blank=True, max_length=100)
- pwd = serializers.CharField()
- def validate_username(self, value):
- if value == '中国':
- raise ValidationError('用户名中存在敏感字符')
- return value
- def validate_pwd(self, value):
- print(value)
- return value
- def validate(self, attrs):
- print(attrs)
- return attrs
- def create(self, validated_data):
- """
- 当执行save方法时,自动调用。instance未传值
- :param validated_data:
- :return:
- """
- print(validated_data)
- return models.UserInfo.objects.create(**validated_data)
- def update(self, instance, validated_data):
- """
- 当执行save方法时,自动调用。instance传值
- :param instance:
- :param validated_data:
- :return:
- """
- instance.username = validated_data.get('username', instance.username)
- instance.save()
- return instance
3.编写serializers
c. 基于CBV
- from django.conf.urls import url,include
- from django.contrib import admin
- from . import views
- urlpatterns = [
- url(r'^users/$', views.user_list),
- url(r'^users/(?P<pk>[0-9]+)/$', views.user_detail),
- ]
1.URL
- from django.http import JsonResponse,HttpResponse
- from rest_framework.response import Response
- from rest_framework.parsers import JSONParser
- from rest_framework.decorators import api_view
- from .serializers import MySerializer
- from . import models
- @api_view(['GET',"POST"])
- def user_list(request):
- """
- List all code snippets, or create a new snippet.
- """
- if request.method == 'GET':
- user_list = models.UserInfo.objects.all()
- serializer = MySerializer(user_list,many=True)
- return Response(serializer.data)
- elif request.method == 'POST':
- data = JSONParser().parse(request)
- serializer = MySerializer(data=data)
- if serializer.is_valid():
- print(serializer.data)
- print(serializer.errors)
- print(serializer.validated_data)
- # 如果有instance,则执行update方法;否则,执行create
- serializer.save()
- return Response(serializer.data, status=201)
- return Response(serializer.errors, status=400)
- @api_view(['GET',"POST","PUT"])
- def user_detail(request, pk):
- """
- Retrieve, update or delete a code snippet.
- """
- obj = models.UserInfo.objects.filter(pk=pk).first()
- if not obj:
- return HttpResponse(status=404)
- if request.method == 'GET':
- serializer = MySerializer(obj)
- # return JsonResponse(serializer.data,json_dumps_params={'ensure_ascii':False},content_type='application/json;charset=utf-8')
- return Response(serializer.data)
- elif request.method == 'PUT':
- data = JSONParser().parse(request)
- serializer = MySerializer(obj, data=data)
- if serializer.is_valid():
- serializer.save()
- return Response(serializer.data)
- return Response(serializer.errors, status=400)
- elif request.method == 'DELETE':
- obj.delete()
- return Response(status=204)
2.视图函数
- from rest_framework import serializers
- from rest_framework.exceptions import ValidationError
- from . import models
- class MySerializer(serializers.Serializer):
- id = serializers.IntegerField(read_only=True)
- username = serializers.CharField(required=False, allow_blank=True, max_length=100)
- pwd = serializers.CharField()
- def validate_username(self, value):
- if value == '中国':
- raise ValidationError('用户名中存在敏感字符')
- return value
- def validate_pwd(self, value):
- print(value)
- return value
- def validate(self, attrs):
- print(attrs)
- return attrs
- def create(self, validated_data):
- """
- 当执行save方法时,自动调用。instance未传值
- :param validated_data:
- :return:
- """
- print(validated_data)
- return models.UserInfo.objects.create(**validated_data)
- def update(self, instance, validated_data):
- """
- 当执行save方法时,自动调用。instance传值
- :param instance:
- :param validated_data:
- :return:
- """
- instance.username = validated_data.get('username', instance.username)
- instance.save()
- return instance
3.编写serializers
d. 权限控制
- REST_FRAMEWORK = {
- 'DEFAULT_PERMISSION_CLASSES': [
- 'permissi.MyPermission',
- ]
- }
1.settings配置文件
- class MyPermission(object):
- """
- A base class from which all permission classes should inherit.
- """
- def has_permission(self, request, view):
- """
- Return `True` if permission is granted, `False` otherwise.
- """
- return True
- def has_object_permission(self, request, view, obj):
- return True
2.权限控制
- - 全局配置
- Highcharts.setOptions({
- global: {
- useUTC: false
- }
- });
- - 主配置
- var chart = new Highcharts.Chart('id1', {
- title: {
- text: '不同城市的月平均气温',
- x: 0
- },
- subtitle: {
- text: '数据来源: WorldClimate.com',
- x: 0
- },
- chart: {
- events: {
- load: function (e) {
- // 图标加载时,执行的函数
- }
- }
- },
- credits: {
- enable: true,
- position: {
- align: 'right',
- verticalAlign: 'bottom'
- },
- text: '老男孩',
- href: 'http://www.oldboyedu.com'
- },
- legend: {
- layout: 'vertical',
- align: 'right',
- verticalAlign: 'middle',
- borderWidth: 1
- },
- xAxis: {
- // categories: ['1.1', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
- type: 'datetime',
- labels: {
- formatter: function () {
- return Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.value);
- },
- rotation: 30
- }
- },
- yAxis: {
- title: {
- text: '数值'
- }
- },
- tooltip: {
- valueSuffix: '个',
- xDateFormat: "%Y-%m-%d %H:%M:%S",
- pointFormatter: function (e) {
- var tpl = '<span style="color:' + this.series.color + '">●</span> ' + this.series.name + ': <b>' + this.y + '</b><br/>';
- return tpl;
- },
- valueDecimals: 1,
- useHTML: true
- },
- plotOptions: {
- series: {
- cursor: 'pointer',
- events: {
- click: function (event) {
- // 点击某个指定点时,执行的事件
- console.log(this.name, event.point.x, event.point.y);
- }
- }
- }
- },
- series: [{
- name: '东京',
- // data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
- data: [
- [1501689804077.358, 8.0],
- [1501689814177.358, 6.9],
- [1501689824277.358, 16.9],
- [1501689834377.358, 11.9]
- ]
- },
- {
- name: '洛杉矶',
- // data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
- data: [
- [1501689804077.358, 18.0],
- [1501689814177.358, 16.9],
- [1501689824277.358, 26.9],
- [1501689834377.358, 9.9]
- ]
- }]
- });
- // chart.addSeries({name:'北京',data: [216.4, 194.1, 95.6, 54.4, 29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5]});
- // 参数:数值;是否重绘; isShift; 是否动画
- // chart.series[0].addPoint(18);
- // chart.series[0].addPoint([12]);
- // chart.series[0].addPoint([v.x, v.y]);
- // 参数:是否重绘
- // chart.series[0].remove(false);
- // 更新饼图
- // $('#id1').highcharts().series[0].data[0].update({x: 0, y: 100})
临时放一下
框架----Django框架知识点整理的更多相关文章
- WEB框架-Django框架学习-预备知识
今日份整理,终于开始整个阶段学习的后期了,今日开始学习Django的框架,加油,你是最胖的! 1.web基础知识 1.1 web应用 Web应用程序是一种可以通过Web访问的应用程序,程序的最大好处是 ...
- web 框架的本质及自定义web框架 模板渲染jinja2 mvc 和 mtv框架 Django框架的下载安装 基于Django实现的一个简单示例
Django基础一之web框架的本质 本节目录 一 web框架的本质及自定义web框架 二 模板渲染JinJa2 三 MVC和MTV框架 四 Django的下载安装 五 基于Django实现的一个简单 ...
- day64 django django零碎知识点整理
本文转载自紫金葫芦,哪吒,liwenzhou.cnblog博客地址 简单了解mvc框架和MTV框架, mvc是一种简单的软件架构模式: m----model,模型 v---view,视图 c---co ...
- 框架----Django框架(基础篇)
一.基本配置 一.创建django程序 终端命令:django-admin startproject sitename IDE创建Django程序时,本质上都是自动执行上述命令 其他常用命令: pyt ...
- python 之 Django框架(Django框架简介、视图装饰器、request对象、Response对象)
12.33 Django框架简介: MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器( ...
- beego 框架基本使用 && 知识点整理
beego 官网的教程已经整理的非常详细了,但作为一个刚接触的学习者,还是有必要做一下整理,这样在后面使用的时候遇到了不太熟悉的地方,还能反过头来看下自己整理的内容,快速的把知识再捞回来,下面是对官网 ...
- WEB框架-Django框架学习(二)- 模型层
今日份整理为模型层 1.ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库, ...
- 框架----Django框架(进阶篇)
一.Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层 ...
- WEB框架-Django框架学习-关联管理器(RelatedManager)
一.class RelatedManager "关联管理器"是在一对多或者多对多的关联上下文中使用的管理器.它存在于下面两种情况: 1.一对多 ForeignKey关系的“另一边” ...
随机推荐
- 接口自动化之接口工具选取(jmeter)
jmeter进行接口测试,网上简易教程很多 其实关于HTTP接口测试的实现,网上还有很多其他工具诸如:http在线请求测试/谷歌插件postman/火狐插件等. 至于选择jmeter的原因,其实没有原 ...
- TW实习日记:第五天
今天可以说是非常忙的一天了,要再项目中实现微信相关的功能:授权登录以及扫码登录,还有就是自建应用的发送消息.首先功能代码其实在经过了几天的学习之后并没有很难,但是最让我难受的是在项目中去加代码,首先s ...
- 《图解 HTTP 》阅读 —— 第五章
第5章 与HTTP协作的web服务器 一台服务器可以托管多个域名. 在相同的IP地址下,虚拟主机可以寄存多个不同主机名和域名的网站,所以在发送HTTP请求时,必须在Host首部内指定完整的主机名和域名 ...
- hdu6447
YJJ's Salesman Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)To ...
- log4j 配置使用
使用log4j来管理日志信息,非常方便,下面简单介绍一下整个使用流程: 1.创建简单java项目 2.在类路径下新建log4j.properties文件 3.配置log4j.properties文件 ...
- 关于jsonp跨域的 实现
1.实现原理 1.把接口写在 script标签的src 中 这个接口就可以访问(不会存在跨域问题 因为接口在浏览器地址栏是可以访问的 会返回json字符串); 2.直接写不可以 因为正常情 ...
- Live Love(思维)
DreamGrid is playing the music game Live Love. He has just finished a song consisting of n notes and ...
- “取件帮”微信小程序宣传视频链接及内容介绍
1.视频链接 视频上传至优酷自频道,地址链接:http://v.youku.com/v_show/id_XMzg2NTM3OTc5Ng==.html?spm=a2hzp.8253869.0.0 2.视 ...
- Oracle数据库表空间常用操作
1. 查看所有表空间大小 SQL> select tablespace_name,sum(bytes)/1024/1024 from dba_data_files group by tables ...
- 使用ASP.NET Identity 实现WebAPI接口的Oauth身份验证
使用ASP.NET Identity 实现WebAPI接口的Oauth身份验证 目前WEB 前后端分离的开发模式比较流行,之前做过的几个小项目也都是前后分离的模式,后端使用asp.net weba ...