分享

【Python之路】第二十三篇

 highoo 2019-03-20
文件配置

1.模版Templates文件配置:

TEMPLATE_DIRS = (
        os.path.join(BASE_DIR,'templates'),
    )

2.静态文件static配置:

STATICFILES_DIRS = (
        os.path.join(BASE_DIR,'static'),
    )

报错 

doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS\

这个问题出现没有在setting INSTALLED_APPS  添加项目名称引起

Q搜索示例

1.利用Q的特性,设计多条件搜索。

demo

前端HTML页面
后端

注意:

1.后端得到数据返回给前端ajax时,需要序列化操作,将字符串返回给前端。

2.序列化操作时,注意json默认只能转换字典,列表,元组等对象,如果为时间,小数等对象,需要自定义扩展转换成字符串。

3.表单提交中的url地址,末尾需要带上/。  如(action="/form1/")

序列化

1、serializers

1
2
3
4
5
from django.core import serializers
ret = models.BookType.objects.all()
  
data = serializers.serialize("json", ret)

2、json.dumps

1
2
3
4
5
6
7
8
import json
  
#ret = models.BookType.objects.all().values('caption')
ret = models.BookType.objects.all().values_list('caption')
  
ret=list(ret)
  
result = json.dumps(ret)

由于json.dumps时无法处理datetime日期,所以可以通过自定义处理器来做扩展,如:

View Code
Form

Django中的Form一般有两种功能、用途:

  • 生成标签,输入html

  • 验证用户输入

1. 后端创建input标签,输入html,浏览器不同,表现不同,步骤如下:

后端定义Form类型
后端生成Form
前端输出Form

生成的标签,可以设置属性值:

复制代码
user_type_choice = (
        (0, u'普通用户'),
        (1, u'高级用户'),
    )
user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,attrs={'class': "form-control"}))

title = forms.CharField(widget=forms.TextInput(attrs={'class': "form-control",'placeholder': u'标题5-20个字符'}))

memo = forms.CharField(widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': u'详细描述', 'rows': 3}))
复制代码
View Code

注意:

1.类里静态字段 只在第一遍执行!, 如果动态绑定了数据,生成后就不再修改了!

复制代码
class Form1(forms.Form):
    def __init__(self,*args, **kwargs):
        super(Form1, self).__init__(*args, **kwargs)

        self.fields['book_type'] =  forms.CharField(
            widget=forms.widgets.Select(choices=models.BookType.objects.values_list('id','caption'),attrs={'class': "form-control"}))
复制代码
完整demo

2. 验证用户输入

依据自定义的Form类,进行判断用户输入是否合法

自定义静态字段:

复制代码
class Form1(forms.Form):
    user = forms.CharField( required=True
                            max_length=20,
                            min_length=5,
                            error_messages={'required': u'标题不能为空',
                                           'min_length': u'标题最少为5个字符',
                                           'max_length': u'标题最多为20个字符',
                                           'invalid': u'标题格式错误'},
                            ) 
复制代码

自定义正则规则:

复制代码
from django import forms
import re
from django.core.exceptions import ValidationError

def mobile_validate(value):
    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not mobile_re.match(value):
        raise ValidationError('手机号码格式错误')

class Form1(forms.Form):
    phonenum= forms.CharField( validators=[mobile_validate, ],
                            )
复制代码

后端验证方法: (需要传入request.POST)

复制代码
from app01.forms import Form1

def form1(request):
    if request.method == 'POST':
        # 获取请求内容,做验证
        f = Form1(request.POST)
        if f.is_valid():
            print(f.cleaned_data)
        else:
            # print(f.errors.get('user',None))
            # print(f.errors['pwd'][0])
            # print(type(f.errors),f.errors)return render(request, 'account/form1.html',{'error': f.errors,'form':f})
    else:
        f = Form1()
        return render(request, 'account/form1.html',{'form':f})
复制代码
Cookie

1、获取Cookie:

1
2
3
4
5
6
7
8
# 普通Cookie
request.COOKIES['key']<br>
# 加密Cookie
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
    参数:
        default: 默认值
           salt: 加密盐 (获取Cookie解密时,需要写上,否则获取得值为None )
        max_age: 后台控制过期时间

2、设置Cookie:

1
2
3
4
5
6
7
8
9
10
11
12
13
rep = HttpResponse(...) 或 rep = render(request, ...)
  
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密盐',...)
    参数:
        key,              键
        value='',         值
        max_age=None,     超时时间 (单位s)  如果参数是None,这个cookie会延续到浏览器关闭为止
        expires=None,     超时时间(IE requires expires, so set it if hasn't been already.)  cookie失效的实际日期/时间,格式必须是:Wdy,DD-Mth-YY HH:MM:SS GMT,这个参数会覆盖max_age参数
        path='/',         Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
        domain=None,      Cookie生效的域名
        secure=False,     https传输
        httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。

1
2
<script src='/static/js/jquery.cookie.js'></script>
$.cookie("list_pager_num", 30,{ path: '/' });
Session

Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

  • 数据库(默认)

  • 缓存

  • 文件

  • 缓存+数据库

  • 加密cookie

1、数据库Session

配置 settings.py
使用示例

2、缓存Session

配置 settings.py

3、文件Session

配置 settings.py

4、缓存+数据库Session

配置 settings.py

5、加密cookie Session

配置 settings.py

更多参考:猛击这里 和 猛击这里

扩展:Session用户验证

1
2
3
4
5
6
7
def login(func):
    def wrap(request, *args, **kwargs):
        # 如果未登陆,跳转到指定页面
        if request.path == '/test/':
            return redirect('http://www.baidu.com')
        return func(request, *args, **kwargs)
    return wrap
分页

一、Django内置分页

二、自定义分页

csrf跨站请求伪造

django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

全局:

  中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

  • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。

  • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

注: 需要引入

1
from django.views.decorators.csrf import csrf_exempt,csrf_protect

二、应用

1、普通表单

1
2
3
4
5
6
7
veiw中设置返回值:
  return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))  
     或者
   return render(request, 'xxx.html', data)
   
html 表单中设置Token:
  {% csrf_token %}

2、Ajax

1.对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,添加请求头

2.为了方便,获取cookie,需要用到 jquery.cookie.js 文件提供的$.cookie()方法

复制代码
var csrftoken = $.cookie('csrftoken');

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});
复制代码

更多:https://docs./en/dev/ref/csrf/#ajax

admin

django amdin是django提供的一个后台管理页面,改管理页面提供完善的html和css,使得你在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用django admin 则需要以下步骤:

  • 创建后台管理员

  • 配置url

  • 注册和配置django admin后台管理页面

1、创建后台管理员

1
python manage.py createsuperuser

2、配置后台管理url

1
url(r'^admin/', include(admin.site.urls))

3、注册和配置django admin 后台管理页面

a、在admin中执行如下配置

View Code

b、设置数据表名称

View Code

c、打开表之后,设定默认显示,需要在model中作如下配置

View Code
View Code

d、为数据表添加搜索功能

View Code

e、添加快速过滤

View Code

更多:http://docs./djangobook2/chapter06/

中间件 

django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。

在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下图。

复制代码
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
复制代码

中间件中可以定义方法,分别是:

  • process_request(self,request)

  • process_view(self, request, callback, callback_args, callback_kwargs)

  • process_template_response(self,request,response)

  • process_exception(self, request, exception)

  • process_response(self, request, response)

以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户。

自定义中间件

1、创建中间件类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from django.utils.deprecation import MiddlewareMixin
class middletest_rep(MiddlewareMixin):
    def process_request(self, request):
        print('process_request1  1111')
    def process_response(self, request, response):
        print('process_response  1111')
        return response
    def process_template_response(self, request, response):
        print('process_template_response 1111')
    def process_view(self, request, callback, callback_args, callback_kwargs):
        print('process_view  1111')
    def process_exception(self, request, exception):
        print('process_exception  1111')

2、注册中间件

1
2
3
4
MIDDLEWARE = [
    'middletest_class.t1.middleware',
  ...
]

3、执行流程 :

request -> view -> url 选择器 -> views 函数 -> response (倒序 return )

request => 下一个 request => .....

    => 如果有 return Httpresponse  => response => 用户页面

-> view -> url 选择器 -> views 函数 -> 没有 render -> response -> 用户

                            有 render -> template  -> response -> 用户

            -> 函数有异常 ->  exception (倒序 return ) -> response

缓存

由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

Django中提供了6种缓存方式:

  • 开发调试

  • 内存

  • 文件

  • 数据库

  • Memcache缓存(python-memcached模块)

  • Memcache缓存(pylibmc模块)

1、配置

a、开发调试

View Code

b、内存

View Code

c、文件

View Code

d、数据库

View Code

e、Memcache缓存(python-memcached模块)

View Code

f、Memcache缓存(pylibmc模块)

View Code

2、应用

a. 全站使用

View Code

b. 单独视图缓存

View Code

c、局部视图使用

View Code

更多:猛击这里

信号

Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。

1、Django内置信号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Model signals
    pre_init                    # django的modal执行其构造方法前,自动触发
    post_init                   # django的modal执行其构造方法后,自动触发
    pre_save                    # django的modal对象保存前,自动触发
    post_save                   # django的modal对象保存后,自动触发
    pre_delete                  # django的modal对象删除前,自动触发
    post_delete                 # django的modal对象删除后,自动触发
    m2m_changed                 # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
    class_prepared              # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
Management signals
    pre_migrate                 # 执行migrate命令前,自动触发
    post_migrate                # 执行migrate命令后,自动触发
Request/response signals
    request_started             # 请求到来前,自动触发
    request_finished            # 请求结束后,自动触发
    got_request_exception       # 请求异常后,自动触发
Test signals
    setting_changed             # 使用test测试修改配置文件时,自动触发
    template_rendered           # 使用test测试渲染模板时,自动触发
Database Wrappers
    connection_created          # 创建数据库连接时,自动触发

对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:

注册的信号放在__init__文件中即可实现.

View Code

views函数调用:

View Code

2、自定义信号

a. 定义信号

1
2
import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

b. 注册信号

1
2
3
4
5
def callback(sender, **kwargs):
    print("callback")
    print(sender,kwargs)
  
pizza_done.connect(callback)

c. 触发信号

1
2
3
from 路径 import pizza_done
  
pizza_done.send(sender='seven',toppings=123, size=456)

由于内置信号的触发者已经集成到Django中,所以其会自动调用,而对于自定义信号则需要开发者在任意位置触发。

更多:猛击这里

Form上传文件

a、自定义上传

复制代码
def upload_file(request):
    if request.method == "POST":
        obj = request.FILES.get('fafafa')
        f = open(obj.name, 'wb')
        for chunk in obj.chunks():          # chunks() 返回bytes类型
            f.write(chunk)
        f.close()
    return render(request, 'file.html')
复制代码

b、Form上传文件实例

Form
Model
view

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多