day48-表单校验及日志记录

2019-01-10  本文已影响0人  barriers

1form表单校验

1.1新建form表单

在当前应用下新建一个forms.py文件
在创建表单类的时候,form表单中的字段就是html中各标签中name对应的值
在form表单中对报错的信息进行修改,只需在字段的约束条件中添加error_messages={'required': '头像必填'}这样浏览器界面就能看见对应的错误类型,还可以如下同时添加多个错误类型

error_messages={'required': '姓名字段必填',
            'min_length': '不能少于2字符',
             'max_length': '不能超过10字符'})

from django import forms
from app.models import Student
class StuForm(forms.Form):
    username = forms.CharField(max_length=10, min_length=2, required=True,
                           error_messages={'required': '姓名字段必填',
                                           'min_length': '不能少于2字符',
                                           'max_length': '不能超过10字符'})
    icon = forms.ImageField(required=True, error_messages={'required': '头像必填'})

    gender = forms.CharField(required=True, error_messages={'required': '性别必填'
                                                        })

同时校验用户名的唯一性和对性别进行转换

    def clean(self):
     校验所有的
    转换性别为1或者是0
    gender = self.cleaned_data.get('gender')
    if gender == '男':
        self.cleaned_data['gender'] = 1
    else:
        self.cleaned_data['gender'] = 0
    校验姓名是唯一的
    username = self.cleaned_data.get('username')
    stu = Student.objects.filter(s_name=username).first()
    如果存在这个姓名的人,就不能创建
    if stu:
        raise forms.ValidationError({'username': '姓名重复'})
    return self.cleaned_data

分开校验用户名的唯一性和对性别进行转换

    def clean_username(self):
        只是校验姓名
        username = self.cleaned_data.get('username')
        stu = Student.objects.filter(s_name=username).first()
        如果存在这个姓名的人
        if stu:
            raise forms.ValidationError('姓名重复')
        return self.cleaned_data['username']

    def clean_gender(self):
       只是校验性别
        转换性别为1或者是0
        gender = self.cleaned_data.get('gender')
        if gender == '男':
            self.cleaned_data['gender'] = 1
        else:
            self.cleaned_data['gender'] = 0
        return self.cleaned_data['gender']

1.2视图函数

在视图层调用form表单对要进行校验的内容进行校验
form = StuForm(request.POST, request.FILES),传入参数,生成对象
form.is_valid(),对对象的属性进行校验,返回布尔值
stuform表单除了会对传入的username和icon进行校验还会对其进行优化,故一般从校验后的对象中取值,而不是再用POST和FILES进行取值;
username = form.cleaned_data['username']
icon = form.cleaned_data['icon']
其中上面的cleaned_data是一个字典;字典中的值是一个列表

<p>姓名:<input type="text" name="username">{{ errors.username.0 }}</p>

上面代码能将错误的原因反馈到浏览器;其中在后面如果不加.0,将是显示一个无序列表;加上后表示取出返回的字典中key为username对应的键的列表的下标为0的值

def add_stu_info(request):
if request.method == 'GET':
    return render(request, 'add_stu.html')
if request.method == 'POST':
    1.利用定义的stuform表单对页面提交的内容进行校验
    form = StuForm(request.POST, request.FILES)
    2.使用is_valid进行验证是否通过,校验成功返回True
    if form.is_valid():
        username = form.cleaned_data['username']
        icon = form.cleaned_data['icon']
       获取的gender字段为1或者0
        gender = form.cleaned_data['gender']
        Student.objects.create(s_name=username, icon=icon, s_gender=gender)
        return HttpResponseRedirect(reverse('app:all_stu'))
    else:
        errors = form.errors
        return render(request, 'add_stu.html', {'errors': errors})

2.页面上删除学生

def del_stu(request, id):
if request.method == 'GET':
    Student.objects.filter(pk=id).delete()
    return HttpResponseRedirect(reverse('app:all_stu'))

本处删应该用post请求;但用户没有从页面输入值传到后端,故只能用get请求代替
在html文件中的for循环内部取学生的后面加如下代码;即能删除对应的学生

    <td>
       <a href="{% url 'app:del_stu' stu.id %}">删除</a>
    </td>

3crsf使用

csrf产生背景:在访问网站时,有可能被恶意的注入代码,执行某些请求,由于浏览器中可能存在之前未退出的页面,cookie依然有效,故常会在用户不知情的情况下一些操作,造成损失;故常在页面的form表单下配置:{% crsf_token %}代码来解决这个问题

<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
        <p>姓名:<input type="text" name="username">{{ errors.username.0 }}</p>
</form>

crsf原理:用户发送请求渲染页面的时候浏览器会自己产生一个随机字符串并一起上传到后台,只有在有输入信息的情况下,才能再次提交并交由后端验证;当为其他恶意网站诱导发起请求时,由于没有输入信息,不能对csrf进行验证,故不能进行相关操作。
校验的时候:settings中的MIDDLEWARE中的django.middleware.csrf.CsrfViewMiddleware中间件会自己对其进行校验,不需要额外写代码

4日志记录

日志记录分为4块,有loggers,handlers,filters,formatters
其中loggers:接收日志
日志的接收有等级的区分,其中日志等级:CRITICAL>ERROR>WARNING>INFO>DEBUG>NOTEST
handlers:处理日志
handler决定如何处理logger中的每条消息。他表示一个特定的日志行为
如果消息的日志级别小于handler的级别,handler将忽略该消息,一般设置为info
filters:过滤(一般用的较少)
formatters:格式化
%(message)s :记录的信息

4.1settings文件中配置日志

配置日志
LOG_PATH = os.path.join(BASE_DIR, 'log')
LOGGING = {
    'version': 1,
     禁用日志,False
    'disable_existing_loggers': False,
    'formatters': {
        默认(时间、日志信息)
        'default': {
            'format': '%(asctime)s %(message)s'
        },
        'simple': {
            'format': '%(message)s'
        }
    },
    接收日志
    'loggers': {
        空代表接收所有系统信息的错误
        '': {
            接收日志,并交给名为console的处理handlers去处理
            'handlers': ['console'],
            日志处理级别
            'level': 'INFO'
        }
    },
   处理日志
    'handlers': {
        'console': {
            'level': 'INFO',
             写日志的文件夹
            'filename': '%s/sys.log' % LOG_PATH,
             写日志的格式
            'formatter': 'default',
            'class': 'logging.handlers.RotatingFileHandler',
            文件大小超过5兆就进行备份
            'maxBytes': 5*1024*1024
        }
    }
}

4.2添加中间件

class LoggingMiddleware(MiddlewareMixin):
    def process_request(self, request):
        request.init_time = time.time()

    def process_response(self, request, resposne):
        try:
            请求到响应之间消耗时长
            count_times = time.time() - request.init_time
            请求地址和请求方式
            path = request.path
            method = request.method
            响应的状态码和内容
            status = resposne.status_code
            content = resposne.content
            日志记录的信息
            message = '%s %s %s %s %s' % (path, method, status, content, count_times)
            logger.info(message)
        except Exception as e:
           logger.critical('log error: %s' % e)
        return resposne

然后将中间件添加到settings文件中。

5前后端分离

django中前后端分离需要使用到restful库
在使用前先安装两个三方库
pip install djangorestframework==3.4.6
pip install django-filter
REST是所有Web应用都应该遵守的架构设计指导原则。核心是资源、状态转移、统一接口
Representational State Transfer,翻译是”表现层状态转化”。
资源:是REST最明显的特征,是指对某类信息实体的抽象,资源是服务器上一个可命名的抽象概念,资源是以名词为核心来组织的,首先关注的是名词。
状态转移:是指客户端痛服务端进行交互的过程中,客户端能够通过对资源的表述,实现操作资源的目的
统一接口:REST要求,必须通过统一的接口来对资源执行各种操作。对于每个资源只能执行一组有限的操作。 比如,客户端通过HTTP的4个请求方式(POST, GET, PUT, PATCH)来操作资源,也就意味着不管你的url是什么,不管请求的资源是什么但操作的资源接口都是统一的。
在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的"集合"(collection),所以API中的名词也应该使用复数
http请求方式有GET(SELECT):从服务器取出资源(一项或多项);POST(CREATE):在服务器新建一个资源;PUT(UPDATE):在服务器更新资源(客户端提供改变后的全部资源);PATCH(UPDATE):在服务器更新资源(客户端提供改变的部分属性);DELETE(DELETE):从服务器删除资源

上一篇 下一篇

猜你喜欢

热点阅读