• Django【第13篇】:Django之Form组件


    django 之知识点总结以及Form组件

    一、model常用操作

      1、13个API查询:all,filter,get ,values,values_list,distinct,order_by ,reverse , exclude(排除),count,first,last,esits(判断是否存在)

      需要掌握的all、values、values_list的区别

        all:打印的是一个QuerySet集合,一个列表里面放的对象

        values :是一个字典形式

        values_list:是一个元组形式  

      all的性能是最低的

      2、only和defer

    复制代码
    datalist = models.Userinfo.objects.all().only("name","email")  #拿到的还是一个QuerySet集合,仅仅取name和email
    for item in datalist:
        print(item.id)
        print(item.name)
        print(item.pwd)   #只要表里有这个字段,一样会取到值,额外的会再发一次请求
    
    datalist = models.Userinfo.objects.all().defer("name","email") #阻止,不取name和email
    for item in datalist:
        print(item.id)
        print(item.pwd)
    复制代码

      注意:用only的话就去取only里面的字段,取其他的字段效率太低了,尽可能的少的连接数据库

      3、路由系统

      反向生成URL:

        有两种方式:{% url "a1" %}

              reverse("a1")

    用reverse需要导入     from django.core.urlresolvers import reverse

    复制代码
    /index/     func    name=a1
        {% url "a1"}
         reverse('a1')
                    
    /index/(d+)/     func    name=a2
        {% url "a2" 11 %}
        reverse('a2',args=(11,))
                    
    /index/(?P<nid>d+)/     func    name=a3
        {% url "a2" nid=11 %}
        reverse('a3',kwargs={'nid':11})
    复制代码

     

     4、Django的生命周期

                   Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)

        1、首先走wsgi模块,这个模块也是一个协议,包括wsgiref和uwsgi。

        2、然后路由分配-------views视图

        3、从数据库取数据-----------渲染到html

        注意如果导入js文件,是不会渲染的。

      5、HTTP协议

        详见下一篇博客                                                                                                

    二、Form组件

    一、Form组件介绍

    Form组件可以做的几件事情:

      1、用户请求数据验证

      2、自动生成错误信息    

      3、打包用户提交的正确信息

      4、如果其中有一个错误了,其他的正确这,保留上次输入的内容

      4、自动创建input标签并可以设置样式

    二、Form组件的使用

      1、创建规则

    class Foo(Form): #必须继承
        username = xxx
        password = xxx
        email = xxx
    注意这里的字段必须和input的name字段一致

      2、数据和规则进行匹配

    先导入view.py

    from django.forms import Form
    from django.forms import fields
    from django.forms import widgets
    复制代码
    from django.shortcuts import render,redirect
    from app01 import models
    # Create your views here.
    from django.forms import Form
    from django.forms import fields
    from django.forms import widgets
    # 1、创建规则
    class TeacherForm(Form):  #必须继承Form
        # 创建字段,本质上是正则表达式
        username = fields.CharField(
            required=True,     #必填字段
            error_messages={"required":"用户名不能为空!!"},  #显示中文错误提示
            widget=widgets.TextInput(attrs={"placeholder":"用户名","class":"form-control"})  #自动生成input框
           )
        password = fields.CharField(required=True, error_messages={'required': '密码不能为空'},
                                    widget=widgets.TextInput(attrs={'placeholder': '密码', 'class': 'form-control'}))  # 不能为空
        email = fields.EmailField(
            required=True,
            error_messages={"required":"邮箱不能为空!!","invalid":"无效的邮箱"},
            widget=widgets.EmailInput(attrs={"placeholder": "邮箱", "class": "form-control"})  # 自动生成input框
        ) #不能为空且邮箱格式要一致
    
    # 2、使用规则:将数据和规则进行匹配
    def teacherindex(request):
        teacher_obj = models.UserInfo.objects.all()
        # print(teacher_obj)
        return render(request,"teacherindex.html",{"teacher_obj":teacher_obj})
    def add(request):
        if request.method=="GET":
            form = TeacherForm()  #只是让显示一个input框
            return render(request,"add.html",{"form":form })
        else:
            form = TeacherForm(data=request.POST)
            # print(form)  #<QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>, <UserInfo: UserInfo object>]>
            if form.is_valid():# 开始验证
                # print('执行成功',form.cleaned_data)          # 所有匹配成功,字典
                # {'username': 'asd', 'password': 'sdf', 'email': 'sadf@live.com','ut_id':1}
                form.cleaned_data['ut_id'] = 1  #要分的清是班主任还是讲师
                models.UserInfo.objects.all().create(**form.cleaned_data)
                return redirect("/teacherindex/")
            else:
                # print("=====?",form.errors,type(form.errors))#返回失败的结果
                # print(form.errors["username"][0])   #拿到返回失败的结果,渲染到页面
                return render(request,"add.html",{"form":form})
    复制代码

    html.py

    复制代码
    {% block right %}
        <h1>添加老师信息</h1>
        <hr>
        <form method="post" novalidate>
            {% csrf_token %}
            <p>姓名:{{ form.username }}</p>{{ form.errors.username.0 }}
            <p>密码:{{ form.password }}</p>{{ form.errors.password.0 }}
            <p>邮箱:{{ form.email }}</p>{{ form.errors.email.0 }}
            <p><input type="submit" value="提交"></p>
        </form>
    {% endblock %}
    复制代码

    如果访问视图的是一个GET 请求,它将创建一个空的表单实例并将它放置到要渲染的模板的上下文中。这是我们在第一个访问该URL 时预期发生的情况。

    如果表单的提交使用POST 请求,那么视图将再次创建一个表单实例并使用请求中的数据填充它:form = NameForm(request.POST)。这叫做”绑定数据至表单“(它现在是一个绑定的表单)。

    我们调用表单的is_valid()方法;如果它不为True,我们将带着这个表单返回到模板。这时表单不再为空(未绑定),所以HTML 表单将用之前提交的数据填充,然后可以根据要求编辑并改正它。

    如果is_valid()True,我们将能够在cleaned_data 属性中找到所有合法的表单数据。在发送HTTP 重定向给浏览器告诉它下一步的去向之前,我们可以用这个数据来更新数据库或者做其它处理。

    注意: form = TeacherForm()  #没有参数,只是一个input框

        form = TeacherForm(data=request.POST) # 数据和规则放置一起 (添加的时候用)

        form = TeacherForm(initial={'username':obj.username,'password':obj.password,'email':obj.email})   # 显示input,并且将数据库中的默认值填写到input框中 (编辑的时候用)

    Widgets

    每个表单字段都有一个对应的Widget 类,它对应一个HTML 表单Widget,例如<input type="text">

    在大部分情况下,字段都具有一个合理的默认Widget。例如,默认情况下,CharField 具有一个TextInput Widget,它在HTML 中生成一个<input type="text">

    字段的数据

    不管表单提交的是什么数据,一旦通过调用is_valid() 成功验证(is_valid() 返回True),验证后的表单数据将位于form.cleaned_data 字典中。这些数据已经为你转换好为Python 的类型。

    注:此时,你依然可以从request.POST 中直接访问到未验证的数据,但是访问验证后的数据更好一些。

    在上面的联系表单示例中,is_married将是一个布尔值。类似地,IntegerField 和FloatField 字段分别将值转换为Python 的int 和float

    三、数据库表设计

    设计表时注意的几点:

      1、 nid = models.AutoField(primary_key=True)        #如果不指定django会默认加上id的

        nid = models.BigAutoField(primary_key=True)   #但那些整型满足不了你的时候,就用BigAutoField

      2、对于类的注释一般加在类里面

      3、verbose_name=“标题”   字段的中文提示

      4、ForeignKey(to = "表名",tofield= "字段")    #这两个to可以不用写,但是关联的表名一定要写

      5、releated_name = "uuu"   反向查询。如果一个表中有多个ManyTwoMany()或者ForeignKey()必须加上releated_name 

      6、字段经常变动的适合连表

         字段变化小,不怎么变的适合在一个表中,不进行连表:就用choices

           吧班主任和老师可以放到一个表中、因为他们有相同的属性,如果属性全是一样的,可以放在一个表里(推荐)

         也可以分开放,老师表是老师表,班主任表是班主任表。这样就会进行连表操作,连表有性能消耗。

    举例:文章和文章类型

       分析:一个文章有一个类型,一个类型可以对应多个文章(所以文章和文章类型是一对多的关系,关联字段要放在多的一方)

      一:连表设计:

    复制代码
    class News(models.Model):
        title = models.CharField(max_length=32)
        summary = models.CharField(max_length=255)
        news_type = models.ForeignKey(to="NewsType")
    class NewsType(models.Model):
        type_title = models.CharField(max_length=32)

    News:

      id   title   summary  news_type_id
      1    t....    科技...     2
      2    t....    科技...     1
      3    t....    科技...     2

    NewsType:
     id title

      1      图片
      2      挨踢1024
      3      段子

    # 查看所有新闻
    new_list = models.News.objects.all()
    for row in new_list:
    print(row.title,row.summary,row.news_type.title)

    复制代码

      二 :放在一个表中的操作:choices

    复制代码
    class News2(models.Model):
        title = models.CharField(max_length=32)
        summary = models.CharField(max_length=255)
        news_type_chices = (
            (1, '图片'),
            (4, '挨踢1024'),
            (3, '段子'),
        )
        news_type = models.IntegerField(choices=news_type_chices)

    # 查看所有新闻
    new_list = News.objects.all()
    for row in new_list:
    print(row.title,row.summary, row.get_news_type_display() )

    复制代码

    举例二:用户和用户类型

      一:连表设计

    复制代码
    class UserType(models.Model):
            """
            用户类型表,个数经常变动
            """
            title = models.CharField(max_length=32)
    
    class UserInfo(models.Model):
            """
            用户表:讲师和班主任
            """
            username = models.CharField(max_length=32)
            password = models.CharField(max_length=64)
            email = models.CharField(max_length=32)
            ut = models.ForeignKey(to="UserType")
    复制代码

      二:不连表设计:choices

    复制代码
    class UserInfo(models.Model):
    #     """
    #     用户表
    #     """
        username = models.CharField(max_length=32)
        password = models.CharField(max_length=64)
        email = models.CharField(max_length=32,verbose_name="邮箱")
        user_type_choices = (
            (1, '班主任'),
            (2, '讲师'),
        )
    
        user_type_id = models.IntegerField(choices=user_type_choices)
    复制代码

    四、登录

     可设置一个装饰器

    复制代码
    def auth(func):
        def inner(request,*args,**kwargs):
            is_login = request.session.get("is_login", None)
            if not is_login:
                return redirect("/login/")
            ret = func(*args,**kwargs)
            return ret
        return inner
    复制代码

     需要注意的:  

      1、action不写路径,默认提交到当前 

      2、向后台提交数据用post,获取数据用get

      3、submit一般加上value,有些浏览器可能会不识别

      4、一般配置文件的键都是大写的

  • 相关阅读:
    《生命3.0—在亿年的尺度下审视生命的演进》阅读笔记3
    软件杯赛题周总结(2)
    《生命3.0—在亿年的尺度下审视生命的演进》阅读笔记2
    记一次阅读源码的小经历
    11
    解决在 CSS 中,如何实现动态吸顶的样式/效果 ?
    Angular 初始化项目后,如何把默认的 .css 文件修改为 .scss 文件?
    解决 Angular 项目中,添加 <router-outlet> 标签后,报错: ‘router-outlet’ is not a known element 的问题。
    在 Angular 项目中,如何为项目单独创建路由文件?
    [NOIP2013 提高组] 《火柴排队》
  • 原文地址:https://www.cnblogs.com/mqhpy/p/11204112.html
Copyright © 2020-2023  润新知