Django 10 表单

表单的使用流程

1. 定义

  1. terminal 输入 django-admin startapp the_14回车
  1. tutorial子文件夹 settings.py INSTALLED_APPS 中括号添加 "the_14",
复制代码
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "the_3",
    "the_5",
    "the_6",
    "the_7",
    "the_8",
    "the_9",
    "the_10",
    "the_12",
    "the_13",
    "the_14",
]
  1. tutorial子文件夹 urls.py
python 复制代码
from django.contrib import admin
from django.urls import path,include
import the_3.urls

urlpatterns = [
    path('admin/', admin.site.urls),
    path('the_3/', include('the_3.urls')),
    path('the_4/', include('the_4.urls')),
    path('the_5/', include('the_5.urls')),
    path('the_7/', include('the_7.urls')),
    path('the_10/', include('the_10.urls')),
    path('the_12/', include('the_12.urls')),
    path('the_13/', include('the_13.urls')),
    path('the_14/', include('the_14.urls')),
]
  1. the_14 子文件夹添加 urls.py
python 复制代码
from django.urls import path
from .views import hello

urlpatterns = [
    path('hello/', hello),
]
  1. the_14\views.py
python 复制代码
from django.http import HttpResponse
from django.shortcuts import render


# Create your views here.

def hello(request):
    return HttpResponse('hello world')
  1. 运行tutorial, 点击 http://127.0.0.1:8000/, 浏览器地址栏 127.0.0.1:8000/the_14/hello/ 刷新
  1. 定义表单, 在 the_14文件夹创建 forms.py文件
python 复制代码
from django import forms

class NameForm(forms.Form):
    your_name = forms.CharField(label='你的名字', max_length=10)
  1. the_14\views.py
python 复制代码
from django.http import HttpResponse
from django.shortcuts import render


# Create your views here.

def hello(request):
    return render(request, 'the_14/hello.html')
  1. templates创建the_14子文件夹,再在 the_14子文件夹创建 hello.html
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>我是表单页面</h1>
</body>
</html>
  1. 运行tutorial, 点击 http://127.0.0.1:8000/, 浏览器地址栏 127.0.0.1:8000/the_14/hello/ 刷新
  1. 我想把form的内容渲染到前端去,首先the_14\views.py 写入
python 复制代码
from django.http import HttpResponse
from django.shortcuts import render
from .forms import NameForm


# Create your views here.

def hello(request):
    form = NameForm()
    return render(request, 'the_14/hello.html', {'myform':form})

其次,在 template\the_14\hello.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>我是表单页面</h1>
    {{ myform }}
</body>
</html>

刷新网页

注意: 这里是没办法提交的,如果想提交, 需要嵌套一个form表单

复制代码
<body>
    <h1>我是表单页面</h1>
    <form action="">
    {{ myform }}
    </form>
</body>

表单的绑定与非绑定

绑定就是说表单里面有值了,非绑定就是表单里面还没有值

表单提交了就是有值, 没有提交或者提交错误就是拿不到值, 拿不到值就是非绑定的状态。

怎么证明表单里面没有值

the_14\views.py

python 复制代码
from django.http import HttpResponse
from django.shortcuts import render
from .forms import NameForm


# Create your views here.

def hello(request):
    form = NameForm()
    import pdb
    pdb.set_trace()
    return render(request, 'the_14/hello.html', {'myform':form})

重新运行,刷新网页, terminal 输入 p form 回车

-> return render(request, 'the_14/hello.html', {'myform':form})

(Pdb) p form

<NameForm bound=False, valid=Unknown, fields=(your_name)>

bound=False 就是非绑定的状态

terminal 再输入 p dir(form) 回车

(Pdb) p dir(form)

['class', 'delattr', 'dict', 'dir', 'doc', 'eq', 'format', 'ge', 'getattribute', 'getitem', 'getstate', 'gt', 'hash', 'html', 'init', 'init_subclass', 'iter', 'le', 'lt', 'module', 'ne', 'new', 'reduce', 'reduce_ex', 'repr', 'setattr', 'sizeof', 'str', 'subclasshook', 'weakref', '_bound_fields_cache', '_clean_fields', '_clean_form', '_errors', '_html_output', '_post_clean', 'add_error', 'add_initial_prefix', 'add_prefix', 'as_p', 'as_table', 'as_ul', 'auto_id', 'base_fields', 'changed_data', 'clean', 'data', 'declared_fields', 'default_renderer', 'empty_permitted', 'error_class', 'errors', 'field_order', 'fields', 'files', 'full_clean', 'get_initial_for_field', 'has_changed', 'has_error', 'hidden_fields', 'initial', 'is_bound', 'is_multipart', 'is_valid', 'label_suffix', 'media', 'non_field_errors', 'order_fields', 'prefix', 'renderer', 'use_required_attribute', 'visible_fields']

is_bound 判断是否绑定的状态

terminal 输入 p form.is_bound回车 , False指的是非绑定状态

(Pdb) p form.is_bound

False

terminal 输入 c回车, 结束调试

(Pdb) c

[07/Jan/2024 19:10:13] "GET /the_14/hello/ HTTP/1.1" 200 344

2.渲染

渲染表单到模板

复制代码
{{ form.as_table }}、{{ form.as_table }}、{{ form.as_p }}、{{ form.as_ul }}
复制代码
{{ form.attr }}

the_14\hello.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>我是表单页面</h1>
    <form action="" method="post">
    账号:{{ myform.your_name }}
        <input type="submit" value="上传">
    </form>
</body>
</html>

表单验证

  • 字段验证
  • 基于cleaned_data的类方法: clean_<fieldname>()
  • 基于cleaned_data的类方法:clean()

表单使用:其实是包含的两个请求的

第一个请求, get请求,这个请求可以拿到网页,展示页面

第二个请求, post请求,这个请求主要是提供数据给后台 , 注意:需要声明请求的url

templates\the_14\hello.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>我是表单页面</h1>
    <form action="{% url 'form_hello' %}" method="post">
    账号:{{ myform.your_name }}
        <input type="submit" value="上传">
    </form>
</body>
</html>

the_14\urls.py

python 复制代码
from django.urls import path
from .views import hello

urlpatterns = [
    path('hello/', hello, name='form_hello'),
]

the_14\views.py

python 复制代码
from django.http import HttpResponse
from django.shortcuts import render
from .forms import NameForm


# Create your views here.

def hello(request):
    form = NameForm()
    # import pdb
    # pdb.set_trace()
    print(form.is_bound)
    return render(request, 'the_14/hello.html', {'myform':form})

刷新网页,输入名字panda, 点击上传,可以看到有两个False, 执行了两次。

False

[07/Jan/2024 20:56:07] "GET /the_14/hello/ HTTP/1.1" 200 352

False

[07/Jan/2024 20:56:13] "POST /the_14/hello/ HTTP/1.1" 200 352

第二次优化

the_14\views.py

python 复制代码
from Scripts.bottle import view
from django.http import HttpResponse
from django.shortcuts import render
from .forms import NameForm


# Create your views here.

# def hello(request):
#     request.method = 'GET'
#     form = NameForm()
#     # import pdb
#     # pdb.set_trace()
#     print(form.is_bound)
#     return render(request, 'the_14/hello.html', {'myform':form})

class Hello(view):
    def get(self, request):
        form = NameForm()
        return render(request, 'the_14/hello.html', {'myform': form})

    def post(self,request):
        form = NameForm(request.POST)
        return render(request, 'the_14/hello.html', {'myform': form,'post':True})

the_14\urls.py

python 复制代码
from django.urls import path
from .views import Hello

urlpatterns = [
    # path('hello/', hello, name='form_hello'),
    path('hello/', Hello.as_view(), name='form_hello'),
]

刷新网页,输入 panda提交, 浏览器页面会出来 这里是post返回的内容。

字段验证

输入的字段受 max_length的长度限制

基于cleaned_data的类方法: clean_<fieldname>()

def post(self,request): form = NameForm(request.POST) # form.data # 属于原始数据 if form.is_valid(): # 是否校验过 print(form.cleaned_data) # 校验之后的数据, 干净的数据 return render(request, 'the_14/hello.html', {'myform': form,'post':True})

the_14\forms.py

python 复制代码
from django import forms

class NameForm(forms.Form):
    your_name = forms.CharField(label='你的名字', max_length=10)

    def clean_your_name(self):  # 专门校验your_name
        your_name = self.cleaned_data['your_name']
        if your_name.startswith('fuck'):
            raise forms.ValidationError('不能带脏字哟!')  # 不通过就主动抛出错误
        return your_name

the_14\views.py

python 复制代码
from Scripts.bottle import view
from django.http import HttpResponse
from django.shortcuts import render
from .forms import NameForm


# Create your views here.

# def hello(request):
#     request.method = 'GET'
#     form = NameForm()
#     # import pdb
#     # pdb.set_trace()
#     print(form.is_bound)
#     return render(request, 'the_14/hello.html', {'myform':form})

class Hello(view):
    def get(self, request):
        form = NameForm()
        return render(request, 'the_14/hello.html', {'myform': form})

    def post(self,request):
        form = NameForm(request.POST)
        # form.data # 属于原始数据
        if form.is_valid(): # 是否校验过
            print(form.cleaned_data) # 校验之后的数据, 干净的数据
        else:
            print(form.errors)
        return render(request, 'the_14/hello.html', {'myform': form,'post':True})

刷新浏览器, 输入 fuck_panda, 上传就会出现以下内容

基于cleaned_data的类方法:clean()

如果有多个字段,应该怎么校验

the_14 \forms.py 添加 your_title = forms.CharField(label='你的头衔', max_length=10)

python 复制代码
from django import forms

class NameForm(forms.Form):
    your_name = forms.CharField(label='你的名字', max_length=10)
    your_title = forms.CharField(label='你的头衔', max_length=10)

    def clean_your_name(self):  # 专门校验your_name
        your_name = self.cleaned_data['your_name']
        if your_name.startswith('fuck'):
            raise forms.ValidationError('不能带脏字哟!')  # 不通过就主动抛出错误
        return your_name

templates\the_14\hello.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>我是表单页面</h1>
    <form action="{% url 'form_hello' %}" method="post">
        账号:{{ myform.your_name }} <br>
        头衔:{{ myform.your_title }} <br>
        <input type="submit" value="上传">
    </form>
    {% if post %}
        <div>这里是post返回的内容</div>
    {% endif %}
</body>
</html>

刷新网页

templates\the_14\hello.html 也可以只写 {{ myform }}

复制代码
    <form action="{% url 'form_hello' %}" method="post">
{#        账号:{{ myform.your_name }} <br>#}
{#        头衔:{{ myform.your_title }} <br>#}
        {{ myform }}
        <input type="submit" value="上传">
    </form>

刷新网页

the_14\forms.py

python 复制代码
from django import forms

class NameForm(forms.Form):
    your_name = forms.CharField(label='你的名字', max_length=10)
    your_title = forms.CharField(label='你的头衔', max_length=10)

    def clean_your_name(self):  # 专门校验your_name
        your_name = self.cleaned_data.get('your_name', '')
        if your_name.startswith('fuck'):
            raise forms.ValidationError('不能带脏字哟!')  # 不通过就主动抛出错误
        return your_name

    """
    如果名字以pd开头,头衔必须使用金牌     
    """

    def clean(self):
        name = self.cleaned_data.get('your_name','')
        title = self.cleaned_data.get('your_title', '')

        if name.startswith('pd_') and title != "金牌":
            raise forms.ValidationError('如果名字以pd开头,头衔必须使用金牌')

刷新网页,输入 fuck_panda , pfshjln 上传

复制代码
如果使用['your_name']自定义的验证之后,还会进行clean()的联合校验,但是自定义没有通过,数据是不会填充到clean里面来的,所以
self.cleaned_data['your_name'] 是取不到值的
属性验证

the_14\forms.py

python 复制代码
from django import forms
from django.core.validators import MinLengthValidator


class NameForm(forms.Form):
    your_name = forms.CharField(label='你的名字', max_length=10,validators=[MinLengthValidator(3,'你的长度应该要大于3个')])

    your_title = forms.CharField(label='你的头衔', max_length=10)

刷新网页,填入 1, unknown, 点击上传, 浏览器返回

自定义验证器 - (from django.core import validators)

the_14\forms.py

python 复制代码
from django import forms
from django.core.validators import MinLengthValidator

def my_validator(value):
    if len(value) < 4:
        raise forms.ValidationError('你写少了,赶紧修改')

class NameForm(forms.Form):
    # your_name = forms.CharField(label='你的名字', max_length=10,validators=[MinLengthValidator(3,'你的长度应该要大于3个')])
    your_name = forms.CharField(label='你的名字', max_length=10, validators=[my_validator])
    your_title = forms.CharField(label='你的头衔', max_length=10)

刷新网页,输入 111, unknown 点击上传

3. 提交

4. 校验

5. 保存

相关推荐
企业软文推广28 分钟前
软文实战技巧:如何利用媒体平台资源提升品牌影响力?
大数据·python
哎呦没33 分钟前
英语知识网站开发:Spring Boot框架技巧
spring boot·后端·性能优化
狐凄1 小时前
Python一些项目bug
windows·python·bug
pumpkin845141 小时前
Ray 和 PyTorch
人工智能·pytorch·python
顽疲1 小时前
springboot vue 开源 会员收银系统 (9) 库存管理 结算时扣库存
vue.js·spring boot·后端
独行soc1 小时前
信息收集ip测活-Python脚本编写
linux·服务器·python
2401_857600951 小时前
英语知识在线教学:Spring Boot网站构建
spring boot·后端·mfc
赛丽曼1 小时前
Python中的深浅拷贝
开发语言·python
A Runner for leave1 小时前
105.找到冠军
java·数据结构·python·算法·leetcode
流着口水看上帝1 小时前
一文掌握如何用python开发小程序
python·小程序