django之forms组件,cookie与session

多对多表的创建

1 全自动

优点: 不需要手动创建第三张表, orm查询简单

缺点: 第三张表无法扩展.当第三张表需要增加字段是无法操作.

# 全自动创建第三张表, 利用①语句经行创建.
class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    authors = models.ManyToManyField(to='Author')  #
class Author(models.Model):
    name = models.CharField(max_length=32)

2 手动创建

优点: 第三张表可以扩展

缺点: 查询不方便, 当连表查询的时候复杂

# 手动创建第三张关系表.
class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
​
class Author(models.Model):
    name = models.CharField(max_length=32)
                
class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
    create_time = models.DateField(auto_now_add=True)

3 半自动

结合全自动与手动的优点

class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    authors =models.ManyToManyField(to='Author',through='Book2Author',through_fields=('book','author'))
    # through 告诉django orm 书籍表和作者表的多对多关系是通过Book2Author来记录的
    # through_fields 告诉django orm记录关系时用过Book2Author表中的book字段和author字段来#记录的
    # 注意 这种情况下不支持 add, set, remove, clear等语法
    
class Author(models.Model):
    name = models.CharField(max_length=32)
    through_fields=('author', 'book')
​
class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
    create_time = models.DateField(auto_now_add=True)

 

Django中forms组件

forms组件

针对于django前端的form表单进行处理.处理目的围绕三个方面:1,渲染页面. 2, 数据效验. 3 展示数据

2,forms组件基本用法

1, 首先调用forms组件

from django import forms

2, 自定义类

这个类是forms组件类,每个属性就是要校验的字段, 字段内部,有限制条件.如:max_length=8,最大长度为8.

EmailField()这个默认限定格式是邮件格式.

class MyForms(forms.Form):
    username = forms.CharField(max_length=8, min_length=3, )
    password = forms.CharField(max_length=8, min_length=3)
    email = forms.EmailField()

限制条件的属性修改

限制条件是可以有其他修改,比如报错信息, 正则匹配, 控制标签属性等

# widget        控制标签属性和样式
widget=widgets.PasswordInput()
# 控制标签属性
widget=widgets.PasswordInput(attrs={'class':'form-control c1 c2','username':'jason'})
​
# 正则匹配
from django.core.validators import RegexValidator
phone = forms.CharField(
    validators = [RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '必须以数字159开头')]
)

钩子函数(HOOK)

是组件类中的函数,一种是局部函数,一种是全局函数.


  # 局部钩子(针对某一个字段做额外的校验)
    def clean_username(self):
        username = self.cleaned_data.get('username')
        if '111' in username:
            self.add_error('username', '什么鬼密码!重来')
        return username
​
    # 全局钩子(针对多个字段做额外的校验)
    def clean(self):
        password = self.cleaned_data.get('password')
        if '111' in password:
            self.add_error('password', '什么鬼密码')
        return self.cleaned_data

前端显示效果

django之forms组件,cookie与session

django之forms组件,cookie与session

调试组件类

在pycharm中python Console经行组件调试

django之forms组件,cookie与session

from app01 import views  # 导入调试模块
form_obj = views.MyForms({'username':'meKing', 'password': '15523', 'email':'123456@qq.com'})   # 实例化组件类,得到对象
form_obj.errors  # 错误信息
# 结果: {}
form_obj.is_valid() # 是否正确
# 结果: True
form_obj.cleaned_data  # 正确信息内容
# {'username': 'meKing', 'password': '15523', 'email': '123456@qq.com'}

forms组件api

def login(request):
    obj = MyForms()
    if request.method == 'POST':
        obj = MyForms(request.POST)
    return render(request, 'login.html', locals())

前端页面

<form action="" method="post" novalidate>   // novalidate: 取消前端校验
    {% for foo in obj %}
        <p>
            {{ foo.label }}:{{ foo }}
            <span>{{ foo.errors.0 }}</span>  // 显示报错信息
        </p>
    {% endfor %}
    <input type='submit'>
</form>

ps: 自定义类中所有字段都要出传值比对.

forms组件其他信息

常用字段与插件

创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;

initial

初始值,input框里面的初始值。

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三"  # 设置默认值
    )
    pwd = forms.CharField(min_length=6, label="密码")

error_messages

重写错误信息。

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三",
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密码")

password

class LoginForm(forms.Form):
    ...
    pwd = forms.CharField(
        min_length=6,
        label="密码",
        widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
    )

radioSelect

单radio值为字符串

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三",
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密码")
    gender = forms.fields.ChoiceField(
        choices=((1, "男"), (2, "女"), (3, "保密")),
        label="性别",
        initial=3,
        widget=forms.widgets.RadioSelect()
    )

单选Select

class LoginForm(forms.Form):
    ...
    hobby = forms.ChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=3,
        widget=forms.widgets.Select()
    )

多选Select

class LoginForm(forms.Form):
    ...
    hobby = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )

单选checkbox

class LoginForm(forms.Form):
    ...
    keep = forms.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )

多选checkbox

class LoginForm(forms.Form):
    ...
    hobby = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    )

choice字段注意事项

在使用选择标签时,需要注意choices的选项可以配置从数据库中获取,但是由于是静态字段 获取的值无法实时更新,需要重写构造方法从而实现choice实时更新。

 

方式一
from django.forms import Form
from django.forms import widgets
from django.forms import fields
​
 
class MyForm(Form):
 
    user = fields.ChoiceField(
        # choices=((1, '上海'), (2, '北京'),),
        initial=2,
        widget=widgets.Select
    )
 
    def __init__(self, *args, **kwargs):
        super(MyForm,self).__init__(*args, **kwargs)
        # self.fields['user'].choices = ((1, '上海'), (2, '北京'),)
        #
        self.fields['user'].choices = models.Classes.objects.all().values_list('id','caption')
方式二:
from django import forms
from django.forms import fields
from django.forms import models as form_model
​
 
class FInfo(forms.Form):
    authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())  # 多选
    # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())  # 单选

cookie与session

由于HTTP协议是无状态的, 无法记录用户状态.cookie与session是记录用户状态

cookie就是保存在客户端浏览器上的键值对. 工作原理:当你登陆成功之后 浏览器上会保存一些信息
下次再访问的时候 就会带着这些信息去访问服务端  服务端通过这些信息来识别出你的身份, cookie虽然是写在客户端浏览器上的  但是是服务端设置的, 浏览器可以选择不服从命令 禁止写cookie.

session就是保存在服务器上的键值对, session虽然是保存在服务器上的键值对, 但是它是依赖于cookie工作的, 服务端返回给浏览器一个随机的字符串, 浏览器以键值对的形式保存, sessionid:随机字符串, 浏览器在访问服务端的时候  就会将随机字符串携带上, 后端获取随机串与后端的记录的做比对
随机字符串1:数据1
随机字符串2:数据2

设置cookie利用的就是HttpResponse对象

 obj1.set_cookie('k1','v1')

获取cookie

request.COOKIE.get()

删除cookie

obj1.delete_cookie("k1")

设置超时时间
max_age=None, 超时时间
expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)

登陆功能

设置session

request.session['name'] = 'jason'

"""
上面这一句话发生了三件事
1.django 内部自动生成一个随机字符串
2.将随机字符串和你要保存的数据 写入django_session表中(现在内存中生成一个缓存记录 等到经过中间件的时候才会执行)
3.将产生的随机字符串发送给浏览器写入cookie
sessionid:随机字符串
"""
获取session

request.session.get('name')

"""
上面这一句话发生了三件事
1.django内部会自动从请求信息中获取到随机字符串
2.拿着随机字符串去django_session表中比对
3.一旦对应上了就将对应的数据解析出来放到request.session中
"""

django session默认的超时时间是14天

django_session表中的一条记录针对一个浏览器

删除当前会话的所有Session数据

request.session.delete()  # 删除的是浏览器的sessionid信息
  删除当前的会话数据并删除会话的Cookie。

request.session.flush()  # 将浏览器和服务端全部删除
这用于确保前面的会话数据不可以再次被用户的浏览器访问
例如,django.contrib.auth.logout() 函数中就会调用它。

设置会话Session和Cookie的超时时间

request.session.set_expiry(value)

  • 如果value是个整数,session会在些秒数后失效。

    • 如果value是个datatime或timedelta,session就会在这个时间后失效。

    • 如果value是0,用户关闭浏览器session就会失效。

    • 如果value是None,session会依赖全局session失效策略

总结:你在后期可以将一些数据保存到session表中,保存的数据 可以在后端任意位置获取到