Django框架解析

前端相关

展示内容:浏览器接收后端返回的html文本(经过模板渲染)内容并在页面展示.
与用户交互信息:js将用户产生数据通过form表单形式或者ajax形式将数据传输到后台并接收返回信息,从而达到数据交互的作用.


请求的本质

CS架构:本质上django程序就是一个socket服务端,浏览器其实就是一个socket客户端.
django自带的wsgi模块处理浏览器的请求信息,用户只需要实现路由和视图函数、模板等代码部分.


django请求的生命周期

指当用户在浏览器上输入url到用户看到网页的这个时间段内,Django程序内部所发生的事情,具体步骤如下:

  1. 当用户在浏览器输入url时, 然后浏览器会生成请求头和请求体发送给服务器;
  2. url经过wsgi---中间件---最后到达路由映射表,随后按顺序进行正则匹配,若匹配到,则进入对应的视图函数或者类(CBV)中;
  3. 视图函数根据客户端的请求,取出数据并渲染到模板中,其中可能涉及ORM操作(增删改查)或从缓存取出数据, 最终以字符串的形式返回.
Django框架解析_第1张图片
image

Form

表单提交,页面与web服务器交互数据最重要的方式.
基础信息详见:http://www.cnblogs.com/fqh202/p/8483862.html.

Django之Form组件

根据创建的form类,可以在页面自动生成form的input标签.

创建form类:
可以直接在app目录下新建forms.py文件.
在类中定义input标签.

from django.forms import Form
from django.forms import widgets
from django.forms import fields


class MyForm(Form):
    username = fields.CharField(
        # 可以对输入的数据进行初步筛选
        max_length=6,
        min_length=2,
        widget=widgets.TextInput(attrs={'id': 'i1', 'class': 'c1'})
    )

    # 多选一
    gender = fields.ChoiceField(
        choices=((1, '男'), (2, '女'),),
        initial=2,
        widget=widgets.RadioSelect
    )

    city = fields.CharField(
        initial=2,
        widget=widgets.Select(choices=((1, '上海'), (2, '北京'),)) # 下拉框
    )

    pwd = fields.CharField(
        min_length=6,
        widget=widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
    )

构建views.py逻辑
导入自定义的form类并实例化:obj = MyForm()
若填充数据,is_valid()根据自定义的规则对表单数据进行验证,没有错误则通过obj.clean()以字典形式取出数据,若有错误,则错误信息以字典形式保存在obj.errors中.

from django.shortcuts import render, redirect
from .forms import MyForm


def login(request):
    if request.method == "GET":
        obj = MyForm()
        return render(request, 'login.html', {'form': obj})

    elif request.method == "POST":
        obj = MyForm(request.POST, request.FILES)
        errors={}
        if obj.is_valid():
            values = obj.clean()
            print(values)
        else:
            errors = obj.errors
            print(errors)
        return render(request, 'login.html', {'form': obj,'errors':errors})

    else:
        return redirect('http://www.baidu.com')

在login.html动态生成input标签:可以很方便的显示错误信息.




    
    登录页面
    




{# 1.常规制作input标签 #} {# #} {# #} {# #} {# 2.模板语言结合自定义form动态生成input标签 #}
用户名{{ form.username }}{{ form.username.errors.0 }}
{# 可以直接显示错误信息 #}
性别{{ form.gender }}
城市{{ form.city }}
密码{{ form.pwd }}{{ form.pwd.errors.0 }}
{% csrf_token %}

常用控件

// radio单选按钮,值为字符串==========================
gender = forms.ChoiceField(
    choices=((1, '男性'),(2, '女性'), (3, '中性'), ), initial=1, 
    widget=widgets.RadioSelect
)

gender = forms.CharField(
    initial=1, widget=widgets.RadioSelect(choices=((1, '男性'),(2, '女性'), (3, '中性'), ))
)


// 单select,值为字符串========================================
user = fields.CharField(
     initial=2,
     widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
)

user = fields.ChoiceField(
     choices=((1, '上海'), (2, '北京'),),
     initial=2,
     widget=widgets.Select
)
 

// 多选select,值为列表==========================================
user = fields.MultipleChoiceField(
     choices=((1,'上海'),(2,'北京'),),
     initial=[1,],
     widget=widgets.SelectMultiple
)
 

// 单checkbox
gender = forms.ChoiceField(initial=[2, ],choices=((1, '上海'), (2, '北京'),), widget=widgets.CheckboxInput)


// 多选checkbox,值为列表
user = fields.MultipleChoiceField(
     initial=[2, ],
     choices=((1, '上海'), (2, '北京'),),
     widget=widgets.CheckboxSelectMultiple
)

自定义不能为空的错误信息

class RegisterForm(forms.Form):
    username = forms.CharField(min_length=2,error_messages={'required':'用户名不能为空'},

正则自定义错误信息
1.存在多条验证时, 以列表或者元祖形式导入实例化的RegexValidator对象, django会按照顺序逐个验证,直到抛出错误信息;
2.传入两个参数: 匹配的正则表达式错误信息;
3.原理是若输入与正则不匹配,则抛出ValidationError(错误信息)

from django.form import Form
from django.core.validators import RegexValidator

class UserForm(Form):
    username = forms.CharField(
        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), 
                    RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
        widget=widgets.TextInput(attrs={'class': 'form-control'}))

自定义验证函数

from django.core.exceptions import ValidationError
import re

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 UserForm(forms.Form):
    username = forms.CharField(validators=[mobile_validate, ], widget=widgets.TextInput(attrs={'class': 'form-control'}),)

局部钩子:重载内置的clean_field()方法,在form字段中定义的验证完成后,会执行clean_field()方法,此时通过cleaned_data取出值进行判断.

from django import forms
from django.forms import widgets
from django.core.exceptions import ValidationError

class UserForm(Form):
    username = forms.CharField(widget=widgets.TextInput(attrs={'class': 'form-control'}),)
    
    def clean_username(self):
        value = self.cleaned_data['username']
        if value == 'alex':
            raise ValidationError('用户名已存在')
        return value

全局钩子
重载系统的clean()方法(clean(self)是在clean_field(self)之后运行的).
错误信息是保存在obj.errors.__all__中,可以通过自定义过滤器取出自定义的错误信息并在前端显示.

# forms.py
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator,ValidationError

class MyForm(Form):
   ....
    def clean(self):
        if self.cleaned_data.get('pwd1') != self.cleaned_data.get('pwd2'):
            raise ValidationError('密码不一致')
        else:
            return self.cleaned_data



// 自定义过滤器
from django import template
register = template.Library()

@register.filter
def get_error(error_dict):
    if error_dict.get('__all__'):
        return error_dict.get('__all__')[0]

// 前端显示自定义错误信息
 
{% if errors %} {{ errors|get_error }} {% endif %}
文件上传

指定传输数据处理方式: enctype="multipart/form-data"
取出文件:文件的二进制格式保存在request.FILES中,在后台直接以字典方式取出.

django配置media上传文件路径

// 1. setting.py配置
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media', "fileholder_name", ...) # 若存在多级目录,可以逐个写入文件夹名称即可

// 2. urls.py配置
from django.views.static import serve
from onlineLearningSys import settings
# 仅限于debug模式
urlpatterns += [
    url(r'^media/(?P.*)$', serve, {
        'document_root': settings.MEDIA_ROOT,
    }),
]


// 3. models.py
# 图片是以路径字符串的形式存储在数据库的;
image = models.ImageField(upload_to="user/%Y/%m", verbose_name='图片', max_length=100, default='static/images/xgt.jpg')


// 4. html文件,类似于imageField存储的格式是: organization/2018/03/1499239092.png, 必须在加上media前缀
 
    

后台取出文件并利用model方式保存

# views.py 保存用户图片信息
def ***()
    img = request.FILES.get('img')
    user = UerProfile.objects.create_user(
        username=username,
        password=password,
        img= img,
    )
    user.save()

手动保存文件:很少用到!

file_obj = request.FILES.get('upload_file')
f1 = open(file_obj.name, "wb")

# 方法1
for i in file_obj:
    f1.write(i)
    
# 方法2
for i in file_obj.chunks():
    f1.write(i)

补充

在form表单中,只有触发的事件不会自动提交表单,

你可能感兴趣的:(Django框架解析)