zoukankan      html  css  js  c++  java
  • Django之form组件!

     一.手动实现注册功能

            注册功能
                1.渲染前端标签获取用户输入      >>>       渲染标签
                2.获取用户输入传递到后端校验    >>>       校验数据
                3.校验未通过展示错误信息        >>>       展示信息
        
            
            校验数据(前后端都可以校验)
                校验前端后端都可以做,但是前端可以不做,后端必须得做!!!

         后端:

    def reg(request):
        errors={'username':'','password':''}
        if request.method == 'POST':
            username=request.POST.get('username')
            password=request.POST.get('password')
            if 'sb' in username:
                errors['username']='user is not valid'
            if password == '123':
                errors['password']='too easy'
    
        return render(request,'reg.html',locals())

         前端:

    <body>
    <h1>注册页面</h1>
    <form action="" method="post">
        <p>username:
            <input type="text" name="username">
            <span>{{ errors.username }}</span>
        </p>
        <p>password:
            <input type="password" name="password">
            <span>{{ errors.password }}</span>
        </p>
        <input type="submit">
    
    </form>
    </body>

    效果:

           

    二. django form组件

            1.渲染标签
            2.校验数据
            3.展示信息

        1.校验数据:

             测试小技巧:      

               

      

                第一步需要一个form类
                    from django import forms
    
                    class MyForm(forms.Form):
                        name = forms.CharField(max_length=6)
                        password = forms.CharField(max_length=8,min_length=3)
                        email = forms.EmailField(required=True)
                第二步实例化form对象
                    from app01 import views
                                    form_obj=views.MyForm({'name':'jasonhaha','password':'12','email':'123'})
                
                第三步查看数据校验是否合法
                    form_obj.is_valid()  # 只有当所有的字段都校验通过才会返回True
                
                第四步查看校验错误的信息
                    form_obj.errors  # 这个里面放的是所有校验未通过的字段及错误提示
                    """
                    {
                    'name': ['Ensure this value has at most 6 characters (it has 7).'], 
                    'password': ['Ensure this value has at least 3 characters (it has 2).'], 
                    'email': ['Enter a valid email address.']
                    }
    
                    """
                第五步查看校验通过的数据
                    form_obj.cleaned_data  # 符合校验规则数据都会被放到该对象中
                ps:form组件校验数据的规则从上往下依次取值校验
                    校验通过的放到cleaned_data
                    校验失败的放到errors

                  注意:
                       form中所有的字段默认都是必须传值的(required=True),不想传可以改成False
                       校验数据的时候可以都传(多传的数据不会做任何的校验>>>不会影响form校验规则)

    
    

          2.渲染标签:

                后端:

    from django import forms
    
    class MyForm(forms.Form):
        name = forms.CharField(max_length=6,label='用户名')
    #不写label,则在前端显示的是Name password
    = forms.CharField(max_length=8,min_length=3) email=forms.EmailField(required=False) def reg(request): form_obj = MyForm() render(request,'reg.html',locals())

             前端:

                form组件只帮你渲染获取用户输入的标签,不会帮你渲染提交按钮,需要手动添加
                <h1>第一种渲染方式(可扩展性较差)</h1>
                {{ form_obj.as_p }}
                {{ form_obj.as_ul }}
                <input type="submit">

    <h1>第二种渲染方式</h1> <form action=""> <p>{{ form_obj.name.label }}{{ form_obj.name }}</p>
    #label可标识前面的注释 <p>{{ form_obj.password.label }}{{ form_obj.password }}</p> <p>{{ form_obj.email.label }}{{ form_obj.email }}</p> <input type="submit"> </form>
    <h1>第三种渲染标签的方式</h1> <form action=""> {% for foo in form_obj %} <p>{{ foo.label }}{{ foo }}</p> {% endfor %}
                  <input type="submit">
                </form>

        

         前端取消校验:

    <form action="" method="post" novalidate>
    </form>

        3.form组件前后端综合使用

             后端:

    from django import forms
    
    class MyForm(forms.Form):
        name = forms.CharField(max_length=6)
        password = forms.CharField(max_length=8,min_length=3)
        email=forms.EmailField(required=True)
    
    def reg(request):
        form_obj = MyForm()
        if request.method == 'POST':
            print(request.POST)
            form_obj = MyForm(request.POST)
            if form_obj.is_valid():
                return HttpResponse('ok')
        return render(request,'reg.html',locals())

         前端:

    <h1>第三种渲染标签的方式</h1>
    <form action="" method="post" novalidate>
        {% for foo in form_obj %}   #foo是每一个输入框对象
            <p>
                {{ foo.label }}{{ foo }}
                <span>{{ foo.errors.0 }}</span>
            </p>
        {% endfor %}
    <input type="submit">

       

              form组件提交数据如果数据不合法,页面上会保留之前用户输入的信息
     

    效果:

      

     错误提示可以自定义成中文:

    class MyForm(forms.Form):
        name = forms.CharField(max_length=6,label='用户名',error_messages={
            'max_length':'用户名最长6位',
            'required':'用户名不能为空'
        })
        password = forms.CharField(max_length=8,min_length=3,error_messages={
            'max_length': '密码最长8位',
            'required': '密码不能为空',
            'min_length':'密码最少3位'
        }
    
        email = forms.EmailField(error_messages={
            'invalid':'邮箱格式不正确',
            'required':'邮箱不能为空'
        })

    效果:

     

      4.把注册信息写入数据库:

        models.py:

    from django.db import models
    
    # Create your models here.
    class User(models.Model):
        name = models.CharField(max_length=32)
        password = models.CharField(max_length=32)
        email = models.EmailField()

      后端:

    def reg(request):
        form_obj = MyForm()
        if request.method == 'POST':
            print(request.POST)
            form_obj = MyForm(request.POST)
            if form_obj.is_valid():
                data=form_obj.cleaned_data
                models.User.objects.create(**data)
        return render(request,'reg.html',locals())

    ps:

    在使用form组件对模型表进行数据校验的时候,只需要保证字段一致
    那么在创建的对象的时候,把校验通过后的字典键值对拿过来,就直接**form_obj.cleaned_data

    效果:

      

    三. form 钩子函数

                # 局部钩子函数  (单个字段的校验利用局部钩子函数)
                def clean_name(self):
                    name = self.cleaned_data.get('name')
                    if '666' in name:
                        self.add_error('name','光喊666是不行的,要有真实力!')
                    return name  # return还是要加上的,兼容性考虑
    
                # 全局钩子函数  (多个字段的校验利用全局钩子函数)
                def clean(self):
                    password = self.cleaned_data.get('password')
                    confirm_password = self.cleaned_data.get('confirm_password')
                    if not password == confirm_password:
                        self.add_error('confirm_password',"两次密码不一致,你这个dsb!")
                    return self.cleaned_data

    四. forms.widgets的相关用法(可设置标签样式)

    class MyForm(forms.Form):
        name = forms.CharField(max_length=6,label='用户名',error_messages={
            'max_length':'用户名最长6位',
            'required':'用户名不能为空'
        })
        password = forms.CharField(max_length=8,min_length=3,error_messages={
            'max_length': '密码最长8位',
            'required': '密码不能为空',
            'min_length':'密码最少3位'
        },widget=widgets.PasswordInput(attrs={'class':'c1 form-control'}))
        confirm_password = forms.CharField(max_length=8, min_length=3, error_messages={
            'max_length': '确认密码最长8位',
            'required': '确认密码不能为空',
            'min_length': '确认密码最少3位'
        },widget=widgets.PasswordInput())
        email = forms.EmailField(error_messages={
            'invalid':'邮箱格式不正确',
            'required':'邮箱不能为空'
        })
    
        gender = forms.ChoiceField(
            choices=((1, ""), (2, ""), (3, "保密")),
            label="性别",
            initial=3,  # 默认值
            widget=forms.widgets.RadioSelect()
        )
    
        hobby = forms.ChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
            label="爱好",
            initial=3,
            widget=forms.widgets.Select()
        )
        hobby1 = forms.MultipleChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
            label="爱好",
            initial=[1, 3],
            widget=forms.widgets.SelectMultiple()
        )
    
        keep = forms.ChoiceField(
            label="是否记住密码",
            initial="checked",
            widget=forms.widgets.CheckboxInput()
        )

    效果:

          

    五.django操作cookie,session

            http协议四大特性
                1.基于TCP/IP作用于应用层的协议
                2.基于请求响应
                3.无状态
                4.无连接
                
            cookie
                保存在客户端浏览器上的键值对
            
            
            session
                保存在服务端上的键值对
                服务端产生随机的串儿返回给客户端,服务端找一个地方将串儿与对应的信息存起来{'随机字符串':'敏感信息'}

      1.cookie:

            django
                return HttpResponse()
                return render()
                return redirect()
            
            
                obj = HttpResponse()
                return obj
                obj = render()
                return obj
                obj = redirect()
                return obj
            
                
                设置cookie
                    obj.set_cookie()  # 给浏览器设置cookie
                
                获取cookie
                    request.COOKIE.get('name')
                    request.COOKIE['name']

    cookie版登录认证:

    def login(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            if username == 'jason' and password == '123':
    #判断是否有想要跳转的页面,如果没有则跳到主页 old_path
    = request.GET.get('next') if old_path: obj = redirect(old_path) else: obj = redirect('/home/') # 用户登录成功 朝浏览器设置一个cookie # obj.set_cookie('name','jason',expires=7*24*3600) # obj.set_cookie('name','jason',max_age=5)
    注释:cookie生命周期为5s
    obj.set_cookie('name','jason') return obj return render(request,'login.html') from functools import wraps def login_auth(func): @wraps(func) def inner(request,*args,**kwargs): # 校验cookie # print(request.get_full_path()) old_path = request.get_full_path() if request.COOKIES.get('name'): return func(request,*args,**kwargs) return redirect('/login/?next=%s'%old_path) return inner @login_auth def index(request): print(request.COOKIES.get('name')) # if request.COOKIES.get('name'): return HttpResponse('我是index页面,只有登录了才能看') @login_auth def home(request): return HttpResponse('我是home页面,只有登录了才能看') @login_auth def xxx(request): return HttpResponse('我是xxx页面,只有登录了才能看') def logout(request): rep = redirect("/login/") rep.delete_cookie("user") # 删除用户浏览器上之前设置的usercookie值 return rep

    2.session:

                设置session
                    request.session['name'] = 'jason'
                    # 1.先生成一个随机的字符串
                    # 2.在django session表中存储该随机字符串与数据的记录
                    # 3.将随机的字符串发送给客户端浏览器
                    
                获取session
                    request.session.get('name')
                    # 1.django自动获取浏览器随机字符串取django session表里面比对
                    # 2.如果比对成功 会将当前随机字符串对应的数据赋值给request.session
                    # 3.通过request.session操作该数据(数据不存在也不会影响我们的业务逻辑)

    django默认的session存活时间是两周(14天),每个浏览器只有一条数据:

    def set_session(request):
        request.session['name'] = 'jason'
        request.session['name1'] = 'egon'
        request.session['name2'] = 'tank'
        request.session['name3'] = 'nick'
        request.session['name4'] = 'sean'
        return HttpResponse('ok')
    
    def get_session(request):
        print(request.session.get('name'))
        print(request.session.get('name1'))
        print(request.session.get('name2'))
        print(request.session.get('name3'))
        print(request.session.get('name4'))
        return HttpResponse('ok')
    
    
    def delete_session(request):
        request.session.delete()
        return HttpResponse('ok')
    
    
    def flush_session(request):
        request.session.flush()
        return HttpResponse('ok')
            浏览器会设置一个键为sessionid来存放session值
                    
            
            # 删除当前会话的所有Session数据
            request.session.delete()
              
            # 删除当前的会话数据并删除会话的Cookie。
            request.session.flush() 
            这用于确保前面的会话数据不可以再次被用户的浏览器访问
            例如,django.contrib.auth.logout() 函数中就会调用它。
       浏览器会设置一个键为sessionid来存放session值,可在settings.py文件中配置session参数

    SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)

    SESSION_COOKIE_NAME ="xxxxx" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)

    SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认)
    SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认)
    SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认)
    SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认)
    SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)

     

    session版登录认证:

    from functools import wraps
    
    
    def check_login(func):
        @wraps(func)
        def inner(request, *args, **kwargs):
            next_url = request.get_full_path()
            if request.session.get("user"):
                return func(request, *args, **kwargs)
            else:
                return redirect("/login/?next={}".format(next_url))
        return inner
    
    
    def login(request):
        if request.method == "POST":
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
    
            if user == "alex" and pwd == "alex1234":
                # 设置session
                request.session["user"] = user
                # 获取跳到登陆页面之前的URL
                next_url = request.GET.get("next")
                # 如果有,就跳转回登陆之前的URL
                if next_url:
                    return redirect(next_url)
                # 否则默认跳转到index页面
                else:
                    return redirect("/index/")
        return render(request, "login.html")
    
    
    @check_login
    def logout(request):
        # 删除所有当前请求相关的session
        request.session.delete()
        return redirect("/login/")
    
    
    @check_login
    def index(request):
        current_user = request.session.get("user", None)
        return render(request, "index.html", {"user": current_user})
  • 相关阅读:
    聊天demo SignalR
    通过NSXMLParser来解析XML
    项目中遇到的问题
    iOS网络: 把Array和Dictionaries序列化成JSON对象
    通过 NSURLConnection 发送 HTTP GET /HTTP POST /HTTP DELETE /HTTP PUT 请求
    iOS网络: 通过NSMutableURLRequest修改一个URL的请求
    iOS网络: NSURLConnection进行同步下载
    iOS网络: NSURLConnection进行异步请求
    swipe Rotation Pan Press Tap Pinch
    手势识别1:
  • 原文地址:https://www.cnblogs.com/sima-3/p/11051834.html
Copyright © 2011-2022 走看看