python Django 相关学习笔记
Django框架
pip3 install django 命令:
# 创建Django程序
django-admin startproject mysite
# 进入程序目录
cd mysite
# 启动socket服务端,等待用户发送请求
python manage.py runserver 127.0.0.1:8080
# 创建app
python manage.py starapp app01 pycharm
1. 创建project
2. 配置:
- 模板路径
template目录
TEMPLATES = [{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'template')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],},},]
- 静态文件路径
static目录
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'static'),
) 3. 额外配置
MIDDLEWARE = [#'django.middleware.csrf.CsrfViewMiddleware',]
Web框架本质
浏览器(socket客户端)
2. 发送IP和端口 http://www.baidu.com:80/index/
GET:
请求头 http1.1 /index?p=123
请求体(无内容)
POST:
请求头 http1.1 /index?p=123
请求体 ...
4. 接收响应
普通响应:页面直接显示
重定向响应:再一起一次Http请求 服务器(socket服务端)
1. 启动并监听ip和端口,等待用户连接
3. 接收请求进行处理,并返回
普通返回:
响应头:
Access-Control-Allow-Origin:* 响应体:
<html>...</html>
重定向返回:
响应头:
LOCATION: 'http://www.baidu.com'
Access-Control-Allow-Origin:*
路由系统:
urls.py
from django.urls import path,re_path
from app01 import views urlpatterns = [
# path('admin/', admin.site.urls),
path('index/', views.index),
re_path('^edit/(\w+)/$',views.edit1), # 加上 $
re_path('^edit/(\w+).html$',views.edit2),
re_path('^edit/(?P<a2>\w+)/(?P<a1>\w+).html$',views.edit3),
# 按参数名传参 # def edit3(request,*args,**kwargs):
# 不要将(\w+)与(?P<a2>\w+)混用
# 如果前面不加结尾符,则不能匹配此url path('index2/', views.index2,name='n2'),
# 给url命名;在函数中通过别名反找到url
re_path('index3/(\w+)', views.index3,name='n3'),
# 可随意生成(\w+)位置的值
re_path('^index4/(?P<a2>\w+)/(?P<a1>\w+).html$', views.index4,name='n4'),
# 可随意生成(?P<a2>\w+)位置的值 re_path('^', default),
# 此规则放最后
# 什么都不输或者输错了,将会被匹配 # def default(request):return HttpResponse('url 错误')
] views.py
def edit(request,a1):
# a1 为re_path('^edit/(\w+)/$')括号中的字符,按位置传参,
# 若url中有2个括号,函数就有request参数和另2个参数
return HttpResponse('...') # 通过别名反找到url,反生成url
from django.urls import reverse
def index2(request):
v = reverse('n2')
return HttpResponse(v) def index3(request,*args):
v = reverse('n3',args=(123,))
# 请求url:index3/3 生成url:index3/123
# 有多少(\w+),args=(,)就写多少个参数
return HttpResponse(v) def index4(request,**kwargs):
v = reverse('n4',kwargs={'a2':666,'a1':777)) # /index4/666/777.html
# 请求url:index3/3 生成url:index3/123
# 有多少(?P<a2>\w+),kwargs={,}就写多少个键值对
return HttpResponse(v) # 若是给url命名,在templates模板中可以直接使用名字{% url 'm1' %}
# path('index10/', views.index10,name='m1'),
# <form method="post" action="{% url 'm1' %}"> # -><form method="post" action="/index10/">
# re_path('index10/(\w+)/', views.index10,name='m2'),
# <form method="post" action="{% url 'm3' 'abc' %}"> # "补位"
url 的常用使用
路由分发:
urls.py分配url到app
from django.urls import path,re_path,include
urlpatterns = [
path('app02/', include('app02.urls')),
path('app01/', include('app01.urls')),
# 只匹配开头,然后交与app01中的urls继续匹配
# 请求url为 http://127.0.0.1:8000/app01/index/
# -> 先匹配到app01 -> app01下的urls中匹配index
] 在app01.urls.py文件下匹配url
from django.urls import path,re_path
from app01 import views urlpatterns = [
path('index/', views.index),
]
路由分发
ORM操作
ORM操作 (Django2.1.8)
Http请求:
url -> 视图(模板+数据)
步骤:
1. 创建数据库
2.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'s4day70db',
'USER': 'root',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': 3306,
}
}
3. __init__文件中
import pymysql
pymysql.install_as_MySQLdb() 4.注册app
INSTALLED_APPS = [app01,] 5. from django.db import models
class UserGroup(models.Model):
title = models.CharField(max_length=32) class UserInfo(models.Model):
nid = models.BigAutoField(primary_key=True)
user = models.CharField(max_length=32)
password = models.CharField(max_length=64)
age = models.IntegerField(default=1)
ug = models.ForeignKey('UserGroup',on_delete=models.CASCADE,null=True)
# 联合唯一
class Meta:
unique_together = [
('b','g'),] 6.创建数据表,命令:
python manage.py makemigrations
python manage.py migrate
# 报错django.db.utils.InternalError: (1366, "Incorrect string value: '\\xE8\\x8B\\xB1\\xE8\\xAF\\xAD...' for column 'name' at row 1")
# 解决方法,数据库设置默认编码 default charset=utf8 # orm中,若不手动创建models.AutoField(primary_key=True),则自动创建id列。
# 已经创建好的数据库表,修改后重新在终端执行命令即可修改。
# 在已有列的表中增加列,设置值为空null=True,或者default=''设置默认值。
外键:
UserInfo表中生成外键,列名为 ug_id
ug(对象) 代表UserGroup中的一行数据 增
models.UserGroup.objects.create(title='销售部')
obj = models.UserGroup.objects.create(title='销售部')
print(obj.id) # 返回创建好的数据 obj = models.UserGroup(title='xxx')
obj.save() # 批量插入数据
objs = [
models.UserGroup(name='name-1'),
models.UserGroup(name='name-2'),
]
models.UserGroup.objects.bulk_create(objs,10)
查
# 类->数据库表,对象->数据表行
group_list = models.UserGroup.objects.all() # 获取所有数据
# for row in group_list:
# print(row.id,row.title)
group_list = models.UserGroup.objects.filter(id__gt=1) # filter(筛选条件) QuerySet[obj,obj]
group_list = models.UserGroup.objects.filter(id__gt=1).first() # 取第一个值,obj对象 obj = models.UserInfo.objects.filter(id__gt=1).first()
obj.ug.title
# 含外键表查寻,对象.外键表列名 即可获取主表的值。 models.UserGroup.objects.all().values('id','title') # 字典类型,两列。
models.UserGroup.objects.all().values_list('id','title') # 元组类型,两列。 obj = models.UserGroup.objects.filter(id__gt=1).first()
obj.userinfo_set.all() # obj.userinfo_set.filter(nid=2)对另一张表的列做筛选
# 反向操作,获取已被关联外键项的所有与之关联的数据!? # obj.表名小写_set.all()
for row in obj.userinfo_set.all():
# 获取到的是userinfo 中的数据
print(row.age,row.user) models.UserGroup.objects.all().values('id','title','userinfo__age') # 反向查找,跨表
models.UserInfo.objects.all().values('nid','ug__title',) # 正向查时跨表
models.UserInfo.objects.all().values_list('nid','ug__title',) # 正向查时跨表
# xxx.filter() 也可以跨表,跟value一样。 # 查询主动做连表
models.UserInfo.objects.all().select_related('ug')
# 不做连表,做多次查询
models.UserInfo.objects.all().prefetch_related('ug') user_list = models.UserInfo.objects.all()[page_info.start():page_info.end()] # 分页,获取某段数据 # 排序
models.UserInfo.objects.order_by('nid') # 从大到小
models.UserInfo.objects.order_by('-nid','name') # 从小到大,id重复按name排序 # 分组
from django.db.models import Count,Sum,Min
user_list = models.UserInfo.objects.values('ug_id').annotate(xxx = Count('nif'))
# print(user_list,user_list.query)
# <QuerySet [{'xxx': 10, 'ug_id': 1}]> SELECT `app01_userinfo`.`ug_id`, COUNT
# (`app01_userinfo`.`nid`) AS `xxx` FROM `app01_userinfo` GROUP BY
# `app01_userinfo`.`ug_id` ORDER BY NULL
# user_list = models.UserInfo.objects.values('ug_id').annotate(xxx = Count('nid')).filter(xxx__gt=3)
# 分组后筛选
# <QuerySet [{'xxx': 10, 'ug_id': 1}]> SELECT `app01_userinfo`.`ug_id`, COUNT
# (`app01_userinfo`.`nid`) AS `xxx` FROM `app01_userinfo` GROUP BY
# `app01_userinfo`.`ug_id` HAVING COUNT(`app01_userinfo`.`nid`) > 3 ORDER BY NULL # 其它
models.UserInfo.objects.filter(id__lt=1) # <
models.UserInfo.objects.filter(id__gte=1) # >=
models.UserInfo.objects.filter(id__in=[1,2,3]) # in[1,2,3,]
models.UserInfo.objects.filter(id__range=[1,3])
models.UserInfo.objects.filter(id=1)
models.UserInfo.objects.exclude(id=1) # id !=1 # Q
# 方式一
models.UserInfo.objects.filter(Q(nid=8) | Q(nid__gt=10) & Q(caption='root'))
# 方式二 组合查询
q1 = Q()
q1.connector = 'OR'
q1.children.append(('id', 1))
q1.children.append(('id', 9)) q2 = Q()
q2.connector = 'OR'
q2.children.append(('c1', 1))
q2.children.append(('c1', 10)) con = Q()
con.add(q1, 'AND')
con.add(q2, 'AND')
models.Tb1.objects.filter(con) # extra
# extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
result = models.UserInfo.objects.filter(id__gt=1).extra(
where=['app01_userinfo.id < %s'],
params=[100,],
tables=['app01_usertype'],
order_by=['-app01_userinfo.id'],
select={'uid':1,'sw':"select count(1) from app01_userinfo"}
)
print(result.query)
# SELECT (1) AS "uid", (select count(1) from app01_userinfo) AS "sw", "app01_userinfo"."id", "app01_userinfo"."name", "app01_userinfo"."age", "app01_userinfo"."ut_id" FROM "app01_userinfo" , "app01_usertype" WHERE ("app01_userinfo"."id" > 1 AND (app01_userinfo.id < 100)) ORDER BY ("app01_userinfo".id) DESC # 执行原生SQL
from django.db import connection, connections
cursor = connection.cursor()
# cursor = connections['指定数据库'].cursor()
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
row = cursor.fetchone()
- 原生SQL语句
- raw
result = models.UserInfo.objects.raw('select * from userinfo') 删
models.UserGroup.objects.filter(id=2).delete() # 注意有外键的情况
更新
models.UserGroup.objects.filter(id=2).update(title='公关部')
from django.db.models import F
# F 用来获取原来的值
models.UserInfo.objects.all().update(age = F('age') +1) 反向:别名,不用小写表名做反向操作,而是用别名.all()取数据。
related_name = 'xxx'
user_set ==> xxx
related_query_name = 'xxx'
user_set ==> xxx_set
# CBV
path('login.html',views.Login.as_view()), from django.views import View
class Login(View):
def get(self,request):
return HttpResponse('Login.get')
xss攻击 CSRF
xss攻击
- 慎用 safe和mark_safe
前端:{{ item|safe }}
后端:from django.utils.safestring import mark_safe
tag = mark_safe(tag)
- 非要用,一定要过滤关键字 CSRF
a. 基本应用
form表单中添加
{% csrf_token %} b. 全站禁用
# 'django.middleware.csrf.CsrfViewMiddleware', c. 局部禁用
'django.middleware.csrf.CsrfViewMiddleware', from django.views.decorators.csrf import csrf_exempt @csrf_exempt
def csrf1(request): if request.method == 'GET':
return render(request,'csrf1.html')
else:
return HttpResponse('ok')
d. 局部使用
# 'django.middleware.csrf.CsrfViewMiddleware', from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_protect
def csrf1(request): if request.method == 'GET':
return render(request,'csrf1.html')
else:
return HttpResponse('ok') c. 特殊CBV
from django.views import View
from django.utils.decorators import method_decorator @method_decorator(csrf_protect,name='dispatch')
class Foo(View): def get(self,request):
pass def post(self,request):
pass
PS:CBV中添加装饰器
def wrapper(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
# 1. 指定方法上添加装饰器 # class Foo(View):
#
# @method_decorator(wrapper)
# def get(self,request):
# pass
#
# def post(self,request):
# pass
# 2. 在类上添加
# @method_decorator(wrapper,name='dispatch')
# class Foo(View):
#
# def get(self,request):
# pass
#
# def post(self,request):
# pass
Ajax提交数据时候,携带CSRF
a. 放置在data中携带 <form method="POST" action="/csrf1.html">
{% csrf_token %}
<input id="user" type="text" name="user" />
<input type="submit" value="提交"/>
<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> b. 放在请求头中 <form method="POST" action="/csrf1.html">
{% csrf_token %}
<input id="user" type="text" name="user" />
<input type="submit" value="提交"/>
<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>
模板
# 如果传入函数名,将会自动执行函数并取到值。
{% for a in page_info.pager %}
{{ a|safe }} #xss攻击
{% endfor %} index.html <select name="class_id">
<!-- 循环所有的班级 -->
{% for row in class_list %}
<!-- 如果是当前学生所在班级,则默认选中 -->
{% if row.id == current_student_info.class_id %}
<option selected value="{{ row.id }}">{{ row.title }}</option>
{% else %}
<option value="{{ row.id }}">{{ row.title }}</option>
{% endif %}
{% endfor %}
</select> {% for item in item_list %} <a>{{ item }}</a> {% endfor %}
{{forloop.counter}}
{{forloop.first}}
{{forloop.last}}
{% if ordered_warranty %} {% else %} {% endif %} result = {}
for row in teacher_list:
tid =row['tid']
if tid in result:
result[tid]['titles'].append(row['title'])
else:
result[tid] = {'tid': row['tid'],'name':row['name'],'titles': [row['title'],]}
return render(request,'teacher.html',{'teacher_list':result.values()}) 母版:
<html>
...
{% block s1 %} {%endblock%}
...
{% block s2 %} {%endblock%} </html> 子板:
{% extends "layout.html "%} {% block s1 %} <h1>fff</h1> {%endblock%}
{% block s2 %} <h1>ffffff</h1> {%endblock%} layout.html
{% block x1 %}{%endblock%}
<h1>ff</h1>
{% block x2 %}{%endblock%}
<h1>2</h1>...
{% block x3 %}{%endblock%}
index.html
{%extends 'layout'%} {% block x1 %}dfssssssdfsd{%endblock%} {% block x2 %}dfsdfsd{%endblock%} {% block x3 %}fff{%endblock%} 自定义模板语言函数
创建templatetags目录,在其下创建xxx.py文件
使用特殊方法要先导入:{% load xx %}
xxx.py
from django import template
register = template.Library() @register.filter # 只能有2个参数
def my_func(value,arg):
return value+arg
{{ name|my_func:""}} # 冒号后不能有空格
{%if name |my_func%}
〈h3〉真〈/h3〉
{%else%}
〈h3〉假</h3〉
{%endif%} #register.simple_tag # 可传多个参数
def my_func(value,a1,a2,a3):
return value+a1+a2+a3
{% my_func "a11" "a222" "a333" %} 小组件,可在页面多次加载,可不用{% load xx %}导入
{% include 'pub.html' %}
pub.html
<div>
<h3>特别漂亮的组件</h3>
<div class="title">标题:{{ name}}</div>
<div class="content">内容:{{ name}}</div>
</div>
index.html
<body>{% include 'pub.html' %}
cookie session
Cookie
a. 保存在客户端浏览器上的“键值对”
b. 服务端可以向用户浏览器端写cookie
c. 客户端每次方请求时,会携带cookie去 set_cookie
key,
value='',
max_age=None,
expires=None,
path='/',
domain=None,
secure=False, Https
httponly=False 只能自Http请求中传入,js代码无法获取到 cookie签名:
obj = HttpResponse('...')
obj.set_cookie('k1','v1')
request.COOKIES.get('k1') obj.set_signed_cookie(k1,v1,max_age,salt='ff')
request.get_signed_cookie('k1',salt='ff') session保持会话
Cookie是什么?
保存在客户端浏览器上的键值对
Session是什么?
保存在服务端的数据(本质是键值对)
应用:依赖cookie
作用:保持会话(Web网站) # 登陆成功返回时,在request中设置session键值对后,将通过cookie发送随机字符串
# session值保存在数据库表中的
# 在浏览器请求时,获取浏览器带来的session随机字符串,随后检测是否有这个用户登录 if 登陆成功:
request.session['username']='name1'
request.session['password']='pwd1'
return render()
判断是否登陆
v = request.session.get('username')
if v:return HttpResponse('%s,登陆成功'%v)
python Django 相关学习笔记的更多相关文章
- Django初识 学习笔记一
Django初识 学习笔记一 mvcviewsmodelstemplate. 一 MVC框架 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(c ...
- Django:学习笔记(4)——请求与响应
Django:学习笔记(4)——请求与响应 0.URL路由基础 Web应用中,用户通过不同URL链接访问我们提供的服务,其中首先经过的是一个URL调度器,它类似于SpringBoot中的前端控制器. ...
- Django:学习笔记(7)——模型进阶
Django:学习笔记(7)——模型进阶 模型的继承 我们在面向对象的编程中,一个很重要的的版块,就是类的继承.父类保存了所有子类共有的内容,子类通过继承它来减少冗余代码并进行灵活扩展. 在Djang ...
- Django:学习笔记(6)——模型
Django:学习笔记(6)——模型 快速上手 模型到底是什么呢?我们可以想,如果一张数据表的各个字段可以自动映射到一个类的各个属性,则每条记录对应这个类的一个对象.那我们通过类方法来操作对象(即表记 ...
- Django:学习笔记(2)——创建第一个应用
Django:学习笔记(2)——创建第一个应用 创建应用 在 Django 中,每一个应用都是一个 Python 包,并且遵循着相同的约定.Django 自带一个工具,可以帮你生成应用的基础目录结构, ...
- Django:学习笔记(1)——开发环境配置
Django:学习笔记(1)——开发环境配置 Django的安装与配置 安装Django 首先,我们可以执行python -m django --version命令,查看是否已安装django. 如果 ...
- Requests:Python HTTP Module学习笔记(一)(转)
Requests:Python HTTP Module学习笔记(一) 在学习用python写爬虫的时候用到了Requests这个Http网络库,这个库简单好用并且功能强大,完全可以代替python的标 ...
- python网络爬虫学习笔记
python网络爬虫学习笔记 By 钟桓 9月 4 2014 更新日期:9月 4 2014 文章文件夹 1. 介绍: 2. 从简单语句中開始: 3. 传送数据给server 4. HTTP头-描写叙述 ...
- 数论算法 剩余系相关 学习笔记 (基础回顾,(ex)CRT,(ex)lucas,(ex)BSGS,原根与指标入门,高次剩余,Miller_Rabin+Pollard_Rho)
注:转载本文须标明出处. 原文链接https://www.cnblogs.com/zhouzhendong/p/Number-theory.html 数论算法 剩余系相关 学习笔记 (基础回顾,(ex ...
随机推荐
- [POI2008]POD Subdivision of Kingdom
Description 给出一个具有N个结点的无向图,将其分成两个集合S1,S2. 这两个集合的点的个数一样多,但连接它们的边最少. Input 第一行给出数字N,M,代表有N个点,M条边. 下面M行 ...
- 贪心+stack Codeforces Beta Round #5 C. Longest Regular Bracket Sequence
题目传送门 /* 题意:求最长括号匹配的长度和它的个数 贪心+stack:用栈存放最近的左括号的位置,若是有右括号匹配,则记录它们的长度,更新最大值,可以在O (n)解决 详细解释:http://bl ...
- 光盘安装ubuntu出现busybox-initramfs不能继续安装的终极解决方法
我用的是Intel G45的主板,可能是板子太新的原因,kernel支持有问题 从光盘(官方寄来的光盘)安装ubuntu,出现提示: BusyBox V1.1.3 (Debian 1:1.1.3-5u ...
- Android推送服务(1)几种实现方式
1.几种常见的解决方案实现原理 1)轮询(Pull)方式:应用程序应当阶段性的与服务器进行连接并查询是否有新的消息到达,你必须自己实现与服务器之间的通信,例如消息排队等.而且你还要考虑轮询的频率,如果 ...
- Oracle对表空间无权限
有的时候我们在Oracle数据库中对执行insert.update之类的语句时会出错,Oracle说我们对表空间无权限.执行下面的语句就可以修改用户对表空间的权限了. 执行语句: alter user ...
- node入门(一)——安装
node可以让我们用js写服务器.此外还可以用来前端自动化开发,它找到特定服务要使用的包,然后下载.安装.管理. 首先安装node,进入官网下载需要的node版本,然后一键式傻瓜安装.(我的环境是wi ...
- wordpress在撰写新文章界面的显示选项按钮点击无反应的解决办法
原文链接:wordpress在撰写新文章界面的显示选项按钮点击无反应的解决办法 最近升级wordpress之后,发现在文章编辑界面的添加新媒体和可视化按钮点击无反应,如下: 然后就在网上找解决办法, ...
- Android一句代码给Activity定制标题栏
在此之前,使用过几种方法设置标题栏: 1.常规法:这个方法是最常用的了,哪个activity需要什么样的标题栏,就在对应的xml布局设计.缺点:此方法维护起来困难,没有将标题栏的共性抽取出来, 如果要 ...
- eclipse debug java 源码
当我们需要研究java SE的时候,debug 源码是个不错的选择,可以帮助我们清楚了解java 封装jar包的具体实现. 因为oracle 提供的源码jar包为了节省空间,所以没有将调试信息一起打包 ...
- Ubuntu Linux14 64位下在Android studio下用gradle编译Andrid项目时发生libz.so.1共享库找不到的解决方法。
---恢复内容开始--- 我在Ubuntu14 64为下安装了AS,但在用Gradle编译项目时总是报找不到 libz.so.1的错误. error while loading shared libr ...