forms component and cookies and sessions

One, many-to-many three creation methods

1. Fully automatic (recommended *).ManyToManyField(to='Author')

​ Advantage: No need for you to manually create a third table

​ Disadvantage: Since the third table is not created by you manually, it means that the fields of the third table are fixed and cannot be extended

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. Pure manual (just understand)

Do not rely on ManyToMany, create a third table by yourself, which has ForeignKey to do the association of the two tables by yourself

​ Advantage: The third sheet can be arbitrarily extended fields

​ Disadvantage: orm query is inconvenient

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. Semi-automatic (recommended to use ******)

Advantages: Combines the advantages of fully automatic and purely manual

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)
                # books = models.ManyToManyField(to='Book', through='Book2Author', 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)

Second, the forms component

The three main functions of the forms component:
1. Rendering the front end to get the label input by the user
2. Verifying the data
3. Displaying the error message
Note: The form component can only render the label that gets the user input and the submit button needs to be written by the user

Manually implement a registration function

Requirement: Warn when user enters illegal content
def login(request):
    error={'username':'','password':''}
    if request.method=='POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if '金梅瓶' in username:
            error['username']='含有金梅瓶等非法信息'
        if len(password) <3:
            error['password']='密码太短'
    return render(request,'login.html',locals())

<form action="" method="POST">
    <p>用户名:<input type="text" name="username"><span style="color: red">{
     
     { error.username }}</span></p>
    <p>密码:<input type="password" name="password"><span style="color: red">{
     
     { error.password }}</span></p>
    <input type="submit">
Just completed 3 no operations: 1. Front-end page construction 2. Transfer data to back-end for verification 3. Display error information
The forms component can directly help you complete the above three steps
form component

Different fields in Django have no binding meaning. The only meaning is for the validation component .

1689626-20190925171956902-1985806054.png

Test environment in Django : "python Console" in the bottom column of pycharm

1689626-20190925172022830-853208378.png

1. Basic usage

All fields in the forms component are required by default (required=True by default)

# 使用forms组件,首先需要导入forms模块
from django import forms
class LoginForm(forms.Form):# 写一个基础了forms.Form的类
    username = forms.CharField(max_length=8,min_length=3)  # 用户名最长八位最短三位
    password = forms.CharField(max_length=8,min_length=5)  # 密码最长八位最短五位
    email = forms.EmailField()  # email必须是邮箱格式

2. Basic use

Keywords:

is_valid()
errors
cleaned_data  
from app01 import views
# 1.将需要校验的数据 以字典的方式传递给自定义的类 实例化产生对象
form_obj = views.LoginForm({'username':'jason','password':'123','email':'123'})
# 2.如何查看数据是否全部合法
form_obj.is_valid()  # 只有所有的数据都符合要求 才会是True
False
# 3.如何查看错误原因
form_obj.errors
{
    'password': ['Ensure this value has at least 5 characters (it has 3).'], 
    'email': ['Enter a valid email address.']
}
# 4.如何查看通过校验的数据。
form_obj.cleaned_data  
{'username': 'jason'}
# 5.渲染前![](https://img2018.cnblogs.com/blog/1689626/201909/1689626-20190925171951834-595759635.png)
端页面 先生成一个空对象 并将对象传递给前端页面
form_obj = MyForm()
# 注意事项:
1.自定义类中所有的字段默认都是必须要传值的
2.可以额外传入类中没有定义的字段名 forms组件不会去校验 也就意味着多传一点关系没有

Note: All verified data are in the big dictionary cleaned_data

3. Three ways for the form component to render the page

Precautions

​ 1. When the forms component renders the page for you, it will only render the label submit button that gets the user input. You need to add it manually

​ 2. If the label annotation of the input box is not specified, the first letter of the field in the class is capitalized by default, which can be changed by specifying the label parameter in the class

First, the first rendering page

<p>第一种渲染页面的方式(封装程度太高 一般只用于本地测试  通常不适用)</p>
{
     
     { form_obj.as_p }}  
{
     
     { form_obj.as_ul }}
{
     
     { form_obj.as_table }}#写和没写一样

Two: The scalability is high. If there are many input boxes, handwriting is required, which is troublesome to write!

<p>第二种渲染页面的方式(可扩展性较高 书写麻烦)</p>
# form_obj.username.label,第二个点是取input框获取input框的中英文注释!
<p>{
     
     { form_obj.username.label }}{
     
     { form_obj.username }}</p>
<p>{
     
     { form_obj.password.label }}{
     
     { form_obj.password }}</p>
<p>{
     
     { form_obj.email.label }}{
     
     { form_obj.email }}</p>

Third, the third way to render the page

<p>第三种渲染页面的方式(推荐)</p>
{% for foo in form_obj %}
<p>{
     
     { foo.label }}{
     
     { foo }}</p>
<span>{
     
     { foo.errors.0 }}</span># 前端展示错误信息,这里的foo相当于上面的form_obj.username、form_obj.password、form_obj.email.
{% endfor %}

3. Display error messages

{% for foo in form_obj %}
<p>{
     
     { foo.label }}:{
     
     { foo }}
    <span>{
     
     { foo.errors.0 }}</span>
    </p>
    {% endfor %}

#后端代码:max_length,min_length,required
password = forms.CharField(max_length=8,min_length=5,label='密码',error_messages={
        ':max_length':'密码最大八位',
        'min_length':'密码最小五位',
        'required':'密码不能为空'
    },required=False,validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')])  # 密码最长八位最短五位'

# 注意:邮箱有一个invalid参数
email = forms.EmailField(
        label='邮箱',error_messages={
            'required':'不能为空'
            ,'invalid':'邮箱格式不正确',
        }
    )

Display default value: initial

4. Hook function (HOOK): used to customize the validation rules
Usage: Just write the method in the custom form class

1. Global hook : Check whether the user's password is the same twice

# 全局钩子(针对多个字段做额外的校验)    比如校验用户两次密码是否一致
            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','两次密码不一致')
                return self.cleaned_data

2. Local hook: do additional verification for a field

# 局部钩子(针对某一个字段做额外的校验)
1.通过cleaned_data获取
2.add_error报错
def clean_username(self):
    username = self.cleaned_data.get('username')
    if '666' in username:
        self.add_error('username','光喊666是不行的 你得自己上')
        return username

1689626-20190925171859490-704665976.png

5. Other fields and operation methods of the form component

required is required

label annotation information

error_messages error message

initial default value: the change is the value of the label

widget controls label properties and styles

widget=widgets.PasswordInput()
控制标签属性
widget=widgets.PasswordInput(attrs={'class':'form-control c1 c2','username':'jason'})

6. Learn about knowledge points in other fields (you can know where to look when you know that these objects need to be used)

# 单选的radio框 
gender = forms.ChoiceField(
    choices=((1, "男"), (2, "女"), (3, "保密")),
    label="性别",
    initial=2,
    widget=forms.widgets.RadioSelect()
)
# 单选select
hobby = forms.ChoiceField(
    choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    label="爱好",
    initial=3,
    widget=forms.widgets.Select()
)
# 多选的select框
hobby1 = forms.MultipleChoiceField(
    choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    label="爱好",
    initial=[1, 3],
    widget=forms.widgets.SelectMultiple()
)
# 单选的checkbox
keep = forms.ChoiceField(
    label="是否记住密码",
    initial="checked",
    widget=forms.widgets.CheckboxInput()
)
# 多选的checkbox
hobby2 = forms.MultipleChoiceField(
    choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    label="爱好",
    initial=[1, 3],
    widget=forms.widgets.CheckboxSelectMultiple()
)

7.cookie与session

Since the http protocol is stateless. The cookie is saved on the client browser, the session is saved on the server, and the session depends on the cookie. All the user login status or various verifications basically need to depend on the cookie.

7.1 Django operates cookies and sessions

​ Setting cookies uses HttpResponse objects (3)

# 设置浏览器的cookie
obj = HttpResponse()
    obj.set_cookie('k1','v1',max_age=100)
    return obj
# 获取浏览器的cookie
获取cookie,获取浏览器的cookies
request.COOKIE.get()  # request.COOKIE把它看成是一个大字典

as follows:

#给浏览器设置cookie
def lg(request):
    if request.method=='POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username =='wx' and password =='123':
            res = redirect('/home/')
            res.set_cookie('name','wx111')#给浏览器设置cookie
            return res
    return render(request,'lg.html')


def home(request):
    if request.COOKIES.get('name'):#判断是否给浏览器设置了cookie
        return HttpResponse('登录了哦')
    return redirect('/lg/')

Set the login authentication decorator , whether a cookie is set for batch authentication


def lg(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'jason' and password == '123':
            # 先获取url中get请求携带的参数
            old_url = request.GET.get('next')
            # 判断用户是直接访问的登陆页面 还是从别的页面的调过来
            if old_url:
                obj = redirect(old_url)
            else:
                # 如果用户直接访问的登陆页面 那么登陆完成之后 直接跳到网站的首页
                obj = redirect('/home/')
            obj.set_cookie('name','jason',max_age=30)  # 浏览器上就会保存键值对name:jason
            return obj
    return render(request,'lg.html')

def login_auth(func):
    @wraps(func)
    def inner(request,*args,**kwargs):
        # 从request中获取cookie
        # print(request.path)
        # print(request.get_full_path())
        target_url = request.get_full_path()
        if request.COOKIES.get('name'):
            res = func(request,*args,**kwargs)
            return res
        else:
            return redirect('/lg/?next=%s'%target_url)
    return inner

删除cookie
obj1.delete_cookie("k1")

Set timeout
max_age=None, timeout
expires=None, timeout (IE requires expires, so set it if hasn't been already.)

obj.set_cookie('name','jason',max_age=30)  # 浏览器上就会保存键值对name:jason,并启动失效时间

session

1 set the session

request.session['name'] = 'jason'
            """
            上面这一句话发生了三件事
                1.django 内部自动生成一个随机字符串
                2.将随机字符串和你要保存的数据 写入django_session表中(现在内存中生成一个缓存记录 等到经过中间件的时候才会执行)
                3.将产生的随机字符串发送给浏览器写入cookie
                    sessionid:随机字符串
服务端保存用户信息 不一定非要在django_session表中保存。可以利用其他数据库或者换成作为session的暂存地

2 Get session

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

Django session default timeout is 14 days

A record in the django_session table for a browser

Deletes current session data and deletes session cookies.

request.session.delete()

Delete all browsers and servers

request.session.flush()
This is used to ensure that the previous session data cannot be accessed again by the user's browser.
For example, it is called in the django.contrib.auth.logout() function.

# 设置会话Session和Cookie的超时时间
        request.session.set_expiry(value)
            * 如果value是个整数,session会在些秒数后失效。
            * 如果value是个datatime或timedelta,session就会在这个时间后失效。
            * 如果value是0,用户关闭浏览器session就会失效。
            * 如果value是None,session会依赖全局session失效策略。

Summary: You can save some data to the session table in the later stage, and the saved data can be obtained anywhere in the backend

Reprinted in: https://www.cnblogs.com/ZDQ1/p/11582063.html

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326568837&siteId=291194637