• python的Web框架,会话保持及Form表单


    会话

    从打开浏览器访问到关闭浏览器,这就是一次会话。

    cookie是保存在浏览器的,安全度比较低。

     1 # 设置cookie范式,在view中设置
     2 
     3     def index(request):
     4         # 查看是否有num的这个cookie
     5         num = request.COOKIES.get('num')
     6         if num:
     7             num = str(int(num)+1)
     8         else:
     9             num = '1'
    10             
    11         response = render(request, 'teacher/index.html', context={
    12             'num':num
    13         })
    14         # 设置cookie字段,max_age为浏览器保留的cookie时间(过期时间)。
    15         response.set_cookie('num',num, max_age=10)
    16         return response

    session 技术

    在settings中注册,且是做了数据库迁移的。存储的数据默认存储在django_sessions表中

     1 INSTALLED_APPS = [
     2     'teacher.apps.TeacherConfig',
     3     'django.contrib.admin',
     4     'django.contrib.auth',
     5     'django.contrib.contenttypes',
     6     'django.contrib.sessions',  #最新的版本中是默认注册了的。但需要检查是否注册
     7     'django.contrib.messages',
     8     'django.contrib.staticfiles',
     9 ]
    10 
    11 MIDDLEWARE = [
    12     'django.middleware.security.SecurityMiddleware',
    13     'django.contrib.sessions.middleware.SessionMiddleware',  #默认是添加了的
    14     'django.middleware.common.CommonMiddleware',
    15     'django.middleware.csrf.CsrfViewMiddleware',
    16     'django.contrib.auth.middleware.AuthenticationMiddleware',
    17     'django.contrib.messages.middleware.MessageMiddleware',
    18     'django.middleware.clickjacking.XFrameOptionsMiddleware',
    19 ]

    设置session,view中配置

     1 def login(request):
     2     if request.method == 'POST'
     3     username = request.POST.get('username','')
     4     password = request.POST.get('password','')
     5     if username == 'aaa' and password == '123456':
     6         # 如果登录成功,则把当前的用户名保存在session中
     7         request.session['name'] = username
     8         
     9         # 设置过期时间set_expiry
    10         request.session.set_expiry(10)
    11         return redirect(reverse('teacher:index'))
    12         
    13     # 如果在index的html中需要展示用户名的信息,则需要在index中获取session
    14      #   name = request.session.get('name'),然后在通过context传送到html中
    15         
    16         
    17 # 设置退出
    18 def logout(request):
    19     request.session.flush()
    20     return redirect(reverse('teacher:index'))
    21     
    22     
    23     #应用于html的和之前的方式是一样的。{{ }}or{% %}

    session 依赖于cookie,cookie存在客户端,session存在服务端。


    简单的Form表单

    在app下面创建一个forms.py的文件

     1 # 导包
     2 from django import forms
     3 class RegisterForm(forms.Form):
     4     username = forms.CharField(label='用户名', max_length=20)
     5     password = forms.CharField(label='密码',max_length=10,min_length=6,
     6                                 widget=forms.PasswordInput(attrs={'placeholder':'请输入长度为6-10位的密码'}),
     7                                 error_messages={'min_length':'密码长度小于6位','max_length':'密码长度大于10位'})
     8     password_repeat = forms.CharField(label='请再次输入密码',widget=forms.PasswordInput())
     9     email = forms.EmailField(required=False)
    10     
    11     def clean(self):
    12         cleaned_data = super().clean()  #继承父类的clean方法
    13         
    14         # 从父类中检测处理过的数据
    15         password = cleaned_data.get('password')
    16         password_repeat = cleaned_data.get('password_repeat')
    17         
    18         if password != password_repeat:
    19             msg = '两次密码输入不一致'
    20             self.add_error('password_repeat', msg)  #把这个错误的信息加入到password_repeat这个字段中
    21         
    22     
    23     解析:
    24     form表单中的不同的字段将会生成不同的input类型,CharField默认对应text
    25     字段名(变量)对应的html中input中的name
    26     PasswordInput:被渲染成passwo的input标签,里面的内容可以和input一样的内容定制
    27     label:对应的html中的label标签中的内容
    28     error_messages:表示出错后的提示
    29     required=False:可以不填写,表示可以是不填的选项

    在view中应用:

     1 # 从APP中导入
     2 from teacher.forms import RegisterForm
     3 def register(request):
     4     # 判断method
     5     if request.method == 'GET':
     6         form = RegisterForm()  #实例
     7         
     8         
     9     if request.method == 'POST':
    10         form = RegisterForm(request.POST)
    11         if form.is_valid():
    12             return HttpResponse('注册成功')
    13     
    14     return render(requerst, 'teacher/register.html', context={'form':form})
    15     
    16     
    17     
    18     解析:
    19     RegisterForm(request.POST),会根据传进来的request的值来创建一个form,一个绑定的form
    20     is_valid:自动会去根据配置好的去验证,调用此方法的时候,就会默认调用form里面的clean方法。
    21         

    在html中应用:

    1 <form action="">
    2     {% csrf_token %}
    3     {{ form.as_p }}
    4     <input type="submit" value="注册">
    5 </form>
    form的标签和submit需要自己添加,其他的自己渲染。as_p代表用p标签包裹。
    

    查看渲染后,代码是什么样式。

    1 查看渲染后的代码
    2 <form action="" method="post">
    3     <p><label for="id_username">用户名:</label> <input type="text" name="username" required id="id_username" maxlength="20"></p>
    4 <p><label for="id_password">密码:</label> <input type="password" name="password" placeholder="请输入长度为6-10位的密码" required id="id_password" maxlength="10" minlength="6"></p>
    5 <p><label for="id_password_repeat">请再次输入密码:</label> <input type="password" name="password_repeat" required id="id_password_repeat"></p>
    6 <p><label for="id_email">Email:</label> <input type="email" name="email" required id="id_email"></p>
    7     <input type="submit" value="注册">
    8 </form>

    输出渲染的结果:

     密码的判断输出方式 


    模型Form表单

    同样写在forms.py的文件内

    1 # 把需要的models模型导入
    2 from teacher.models import Students,StudentsDetail

    定义表单

     1 # Students表单
     2 class StudentForm(forms.ModelForm):
     3     class Meta:
     4         #不需要一个一个的编辑了,只需要用自带的方法即可,即排除
     5         model = Students
     6         
     7         # 表单内除了'is_deleted'这个字段外,其他的都需要,使用exclude方法
     8         exclude = ['is_deleted']
     9         
    10 # StudentsDetail表单
    11 class StudentDetailForm(forms.ModelForm):
    12     class Meta:
    13         model = StudentsDetail
    14         
    15         # 表单内只需要这些字段,使用fields方法
    16         fields = ['num', 'college']

    在view中应用

    1 # 导入需要的form模型表单
    2 from teacher.forms import StudentForm, StudentDetailForm

    编辑学生信息页面

     1 def new_edit(request, pk):
     2     # 获取当前编辑字段的信息
     3     student = Students.objects.get(pk=pk)
     4     
     5     form = StudentForm(instance=student)
     6     
     7     try:
     8         # 这里做出捕获异常,防止这个学生字段没有相对应的studentsdetail字段。
     9         detail_form = StudentDetailForm(instance=student.studentsdetail)
    10     
    11     except:
    12         # 如果报错,说明这个学生还没有学生详情
    13         
    14         # 生产一个空的详情
    15         student_detail = StudentsDetail()
    16         
    17         # 把两个表相关联起来,保存
    18         student_detail.sudent = student
    19         student_detail.save()
    20         
    21         # 生成新的form表单
    22         detail_form = StudentDetailForm(instance=student_detail)
    23         
    24         *****此处的POST方法写在下面的POST请求方式操作中。
    25         
    26     return render(request, 'teacher/new_student_edit.html', context={
    27         'section': section,
    28         'student': student,
    29         'form': form,
    30         'detail_form': detail_form,
    31     })    
    32     
    33     
    34     解析:
    35     instance:绑定一个信息,用于修改。
    36     如果不写这个,则生成一个空的Form,用于添加。
    37     

    html中整体应用

    1  <form class="form-horizontal" method="post">
    2     {% csrf_token %}
    3         {{ form.as_p }}
    4         {{ detail_form.as_p }}
    5     <div class="col-sm-offset-2 col-sm-10">
    6       <button type="submit" class="btn btn-default">提交</button>
    7     </div>
    8 </form>

    html中分别渲染

     1 <form class="form-horizontal" method="post">
     2     {% csrf_token %}
     3 
     4     {% for field in form %}
     5       <div class="form-group">
     6       
     7       <!--渲染出报错信息-->
     8       {% for error in field.errors %}
     9         <label for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{ error }}</label>
    10       {% endfor %}
    11       
    12       <!--渲染出字段名-->
    13       <label for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{ field.label }}</label>
    14         <div class="col-sm-2">
    15         
    16         <!--渲染出input标签内容-->
    17           {{ field }}
    18         </div>
    19       </div>
    20     {% endfor %}
    21 
    22 
    23     {% for field in detail_form %}
    24       <div class="form-group">
    25       {% for error in field.errors %}
    26         <label for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{ error }}</label>
    27       {% endfor %}
    28       <label for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{ field.label }}</label>
    29         <div class="col-sm-2">
    30           {{ field }}
    31         </div>
    32       </div>
    33     {% endfor %}
    34 
    35     <div class="col-sm-offset-2 col-sm-10">
    36       <button type="submit" class="btn btn-default">提交</button>
    37     </div>

    当前样式:

     分别渲染样式: 

    添加css样式

    当前是没有css的样式的,那如何添加样式呢,有一个方法我们可以看下,input的内容是怎么来的

    # 通过这个方法可以看到,我们的input标签是什么样的,然后我们可以去操作他。
    
    >>> form['name'].as_widget()
    <input type="text" name="name" value="哈哈哈" id="id_name" required maxlength="20">
    
    
    # 如何给他添加class的属性?通过attrs字典的方式给他传入,就可以给这个input添加class
    
    >>> form['name'].as_widget(attrs={'class':'aaa'})
    <input type="text" name="name" value="哈哈哈" id="id_name" required class="aaa" maxlength="20">

    tags的添加方法

    因为在html中用了{% %}方式添加,所以不好给其添加class,只有给他tags方法才好添加,现在,我们写一个tags方法来实现添加class。

    1 # 在tags.py的文件中写添加方法
    2 
    3 from django.template import Library
    4 
    5 @register.simple_tag
    6 def add_class(field, class_str):
    7     return field.as_widget(attrs={'class':class_str})

    html 中应用

    1 <!--先load进来后,再使用标签-->
    2 {% load customer_tags %}
    3 
    4 <!--使用上面这个add_class标签,在for循环中添加使用-->
    5 {% add_class field 'form-control' %}

    使用之后样式: 

    GET输出的样式已经完成,那POST的样式如何完成的呢。

    POST请求方式操作

    view中的post判断

     1  接上面的代码来写POST方法
     2 
     3 if request.method == 'POST':
     4     # 此处的instance必须等于前面对应的信息(student = Students.objects.get(pk=pk)),以保证GET的字段信息和POST的信息是获取的同一个信息。
     5     form = StudentForm(request.POST, instance=student)
     6     
     7     detail_form = StudentDetailForm(request.POST,instance=student.studentdetail)
     8     
     9     # 验证,如果都验证成功,则保存。
    10     if form.is_valid() and detail_form.is_valid():
    11         form.save()
    12         detail_form.save()
    13         return redirect(reverse('teacher:students'))
    14         
    15     
    16     空Form保存示例:
    17     # instance:绑定一个信息,用于修改。
    18     # 如果不写这个,则生成一个空的Form,用于添加。
    19     
    20     # 生成一个空的Form时在保存数据的时候。关联表简单示例如下:
    21     
    22     if form.is_valid() and detail_form.is_valid():
    23         student = form.save()
    24         
    25         # 加上commit=False,则不会真的保存到数据库,需要还需要关联外键
    26         student_detail = detail.form.save(commit=False)
    27         student_detail.student = student
    28         student_detail.save()
    29         return redirect(reverse('teacher:students'))

    设置修改时的报错,model.py中配置,把英文报错修改为中文。

    1 加上error_messages方法,设置的是重复的地方报错,出错在unique。
    2 qq = models.CharField('QQ', max_length=20, unique=True, null=True, error_messages={'unique':'QQ号码重复'})

    html中的整体应用

     1 <form class="form-horizontal" method="post">
     2     {% csrf_token %}
     3 
     4     <!--循环迭代出需要的字段-->
     5     {% for field in form %}
     6     
     7         <!--如果有error的提示,则对这个div添加class中的has-error-->
     8       <div class="form-group {% if field.errors %}has-error{% endif %}">
     9       
    10       <!--对设置的error迭代循环添加-->
    11       {% for error in field.errors %}
    12         <label for="{{ field.id_for_label }}" class="control-label">{{ error }}</label>
    13       {% endfor %}
    14       
    15       循环生成展示的label字段
    16       <label for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{ field.label }}</label>
    17         <div class="col-sm-2">
    18         
    19             使用tag标签来给input标签添加class
    20           {% add_class field 'form-control' %}
    21         </div>
    22       </div>
    23     {% endfor %}
    24 
    25 
    26     {% for field in detail_form %}
    27       <div class="form-group {% if field.errors %}has-error{% endif %}">
    28       {% for error in field.errors %}
    29         <label for="{{ field.id_for_label }}" class="control-label">{{ error }}</label>
    30       {% endfor %}
    31       <label for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{ field.label }}</label>
    32         <div class="col-sm-2">
    33           {% add_class field 'form-control' %}
    34         </div>
    35       </div>
    36     {% endfor %}
    37 
    38     <div class="col-sm-offset-2 col-sm-10">
    39       <button type="submit" class="btn btn-default">提交</button>
    40     </div>
    41 </form>

    加上之后的效果,可以渲染出报错时的效果。 


    用另一种方式的验证,在forms.py中配置

     1 class StudentDetailForm(forms.ModelForm):
     2     class Meta:
     3         model = StudentsDetail
     4         fields = ['num', 'college']
     5 
     6     def clean_num(self):
     7         # 从验证之后的数据中获取num字段
     8         data = self.cleaned_data.get('num')
     9         
    10         # 一个简单的身份证验证,除最后一位数以外都是数字的,才是对的,其他则不对。
    11         if not data[:-1].isdigit():
    12             raise forms.ValidationError('您输入的身份证号码不正确')
    13         return data

    无需其他配置,直接在页面中反馈

  • 相关阅读:
    使用rpmbuild打包erlang和rabbitmq进行部署服务的方法
    Linux 通过yum 方式离线下载依赖rpm包的操作步骤
    影响产品运行性能的参数统计- 不能相信浏览器编辑器 一次崩溃数据全丢 垃圾的要死
    SpringMVC异步处理(Callable和DeferredResult)
    windows 服务自动启动脚本 监控windows服务,并且自动启动
    mysql中局部变量_MySQL中变量的总结
    CompletableFuture实现异步获取结果并且等待所有异步任务完成
    git合并分支上的多条commit为一条commit到master,合并多条commint.合并多条提交
    mysqldumpslow不是内部或外部命令,也不是可运行的程序,mysql慢查询日志工具
    @Validated和@Valid区别:Spring validation验证框架对入参实体进行嵌套验证必须在相应属性(字段)加上@Valid而不是@Validated
  • 原文地址:https://www.cnblogs.com/hua888/p/10570199.html
Copyright © 2020-2023  润新知