Web框架开发-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})

  

def index(request):
    if request.method == "POST":
        """
        两个return是一样的,用url反向解析就相当于下面的路径在urls里面
        协商别名name="index",但在模板中还是要用{%url"index"%}
        """
       # return redirect(reverse(index))
        return redirect("index.html")   # 跳转到个人主页
    return render(request, "hh.html")

  4、Django的生命周期

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

  1.   首先走wsgi模块,这个模块也是一个协议,包括wsgiref和uwsgi
  2. 然后路由分配---------views视图
  3. 从数据库取数据--------渲染到HTML

 

二、form组件

一、Form组件介绍

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

  1、用户请求数据验证

  2、自动生成错误信息    

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

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

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

二、Form组件的使用

  1、创建规则

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

  2、数据和规则进行匹配

先导入view.py

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={"requeired": "邮箱不能为空!",
                        "invalid": "无效的邮箱格式"},
        widget=widgets.EmailInput(attrs={"placeholder":"邮箱", "class": "form-control"})
    )


# 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)

        if form.is_valid(): # 开始验证
            form.cleaned_data['ut_id'] = 1  # 要分的清是班主任还是讲师
            models.UserInfo.objects.all().create(**form.cleaned_data)
            return redirect("/teacherindex/")

        else:
            return render(request, "add.html", {"form": form})

  add.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加老师信息</title>
</head>
<body>
<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>

</body>
</html>

  

teacherindex.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-8">
            <table class="table-bordered table-striped">
                <thead>
                    <tr>
                        <th>编号</th>
                        <th>姓名</th>
                        <th>邮箱</th>
                    </tr>
                </thead>
                <tbody>
                    {% for teacher in teacher_obj %}
                    <tr>
                        <td>{{ teacher.id }}</td>
                        <td>{{ teacher.username }}</td>
                        <td>{{ teacher.email }}</td>
                    </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>

</body>
</html>

  

  如果访问视图的是一个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
   t....    科技...     2
   t....    科技...     1
   t....    科技...     2
NewsType:
 id    title
     图片
     挨踢1024
     段子
 
# 查看所有新闻
				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、一般配置文件的键都是大写的

猜你喜欢

转载自www.cnblogs.com/mike-liu/p/9784515.html