这个世界像是蒙着一层白雾,看不清这个世界也看不见自己,只是感觉到脚下还踩着坚实的土地,由此证明自己还活着,除了自己一无所有。

使用表单

以前提交表单内容数据都是在HTML中写一个表单,然后发送到后端,后端进行处理。

但是在Django中变得简单明了,首先在应用的目录下新建一个forms.py

# NHDZ/app/forms.py

# coding:utf-8
from django import forms
import datetime
class Login(forms.Form):
    username = forms.CharField(label='用户名', widget=forms.TextInput, initial='admin', label_suffix=':x:',required=True)
    # 这里设置表单传送过来的数据,并且自动在前端生成表单
    # label 表单的前缀显示  '用户名:'
    # widget   类型为text
    # initial 输入框内的默认值 为 admin
    # label_suffix 后缀,默认是 用户名: 现在变成了  用户名:x:
    # required 给字段添加必填属性,不能空着。

    password = forms.CharField(label='密码', widget=forms.PasswordInput, initial=datetime.date.today(),help_text='在这里输入你的密码')
    # initial 默认值 可以动态获取日期
    # help_text 帮助文档

然后就能在视图中编写登陆部分的功能

# NHDZ/app/login.py

# coding:utf-8
from .froms import Login
from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    # 登陆页面
    login_form = Login()
    # 实例化表单,然后把表单的内容获取后,渲染到html页面
    return render(request, 'login.html', {'login_form': login_form})


def login(request):
    # 登陆验证
    if request.method == 'POST':
        do_login = Login(request.POST)
        # 实例化传递过来的数据
        if do_login.is_valid():
            # 判断数据是否合法
            username = do_login.cleaned_data['username']
            # 这里的 cleaned_data方法可以清洗数据,然后获取数据
            passowrd = do_login.cleaned_data['password']
            return HttpResponse(username + '<br>' + passowrd)

然后在templates文件夹新建一个login.html文件,内容如下

<form action="{%url 'login_success'%}" , method='POST'>
    {% csrf_token %}
    {{login_form}}
<button type="submit">登陆</button>
</form>

最后修改一些路由文件urls.py

# NHDZ/app/urls.py

from django.urls import path
from .views import Index,Add_Images,Add_Texts
from .show import show
from .login import index,login
urlpatterns = [
    path('',Index,name='index'),
    path('add_texts/',Add_Texts,name='add_texts'),
    path('add_images/',Add_Images,name='add_images'),
    path('show/<str:user>',show,name='show'),
    path('login/',index,name='login'),
    path('login_success/',login,name='login_success')
]

这个时候添加功能差不多完成了,访问一下看看是不是生成了表单

点击登陆后,返回结果

自动渲染格式

在演示的login.html中,我只是传入了 就自动生成了表单,但是样式还是非常简陋的,这里使用Django提供自带的样式表渲染就可以变得美美哒

  1. 将表单渲染成一个表格元素,每个输入框作为一个标签
  2. 将表单的每个输入框包裹在一个

    标签内 tags

  3. 将表单渲染成一个列表元素,每个输入框作为一个
  4. 标签

注意:你要自己手动编写

    标签。

    比如我现在把login.html文件修改成这样

    <form action="{%url 'login_success'%}" , method='POST'>
        {% csrf_token %}
        {{login_form.as_p}}
    <button type="submit">登陆</button>

    现在前端显示的表的样式就变成酱紫

    手动渲染格式

    在希望引用bootstrap时候,需要手动渲染每个地方的样式表,可以通过如下方式进行获取到表的内容,然后进行渲染

    使用直接获取方式

    可以使用 表单.属性 的方式获取到表单的内容输入

    <form action="{%url 'login_success'%}" , method='POST'>
        {% csrf_token %}
    
    <p>用户id:{{ login_form.username }}</p>
    
    # 这里的 login_form.username 就是直接从表单中获取到数据,然后可以自己添加样式
    
    <h2>密码:{{login_form.password}}
    
    <button type="submit">登陆</button>

    使用迭代表方式获取

    传入的数据进行迭代

    <form action="{%url 'login_success'%}" , method='POST'>
        {% csrf_token %}
        {% for field in login_form %}
    
    		# 这里对传入的表单迭代
    
    	  

    {{ field.label_tag }}:{{ field }} # field 是表单输入的内容,field.label_tag 是表单的样式表 # 然后使用 p 标签进行渲染,当然可以把p标签替换css样式

    {{ field.errors }} # 如果表单错误,提示错误内容 {% endfor %} <button type="submit">登陆</button>

    渲染表单错误信息

    在表单里处理错误信息。对于每一个表单字段的错误,它其实会实际生成一个无序列表,参考下面的样子:

    <ul class="errorlist">
        <li>Sender is required.</li>
    </ul>

    这个列表有个默认的CSS样式类errorlist,如果你想进一步定制这个样式,可以循环错误列表里的内容,然后单独设置样式:

    {% if login_form.errors %}
    	    
      {% for error in form.username.errors %}
    1. {{ error|escape }}
    2. {% endfor %}
    {% endif %}

    一切非字段的错误信息,比如表单的错误,隐藏字段的错误都保存在中,上面的例子,我们把它放在了表单的外围上面,它将被按下面的HTML和CSS格式渲染:

    <ul class="errorlist nonfield">
        <li>Generic validation error</li>
    </ul>

    使用 CSS 样式表

    总结了一下,可以通过三种(说到底就是两种)方式设置层叠样式表

    后端处理

    在Django编写forms.py表单模型的时候,能够通过设置Field类的属性设置样式,比如

    class Login(forms.Form):
        username = forms.CharField(label='用户名', widget=forms.TextInput(attrs={'size': '20'}))
        # 代表大小为20px

    然后 在templates的login.html修改成

    <form action="{%url 'login_success'%}" , method='POST'>
        {% csrf_token %}
    
    {{login_form}}
    
    <button type="submit">登陆</button>

    结果如下

    使用前端处理

    如上文的手动渲染格式一样,使用field.xxx获取表单的属性,然后自己在前端html编写css

    需要注意的是,如果你在前端手动获取了表单的内容数据后然后自己写css渲染后,后端代码中设置的样式不起作用

    半自动处理

    前端框架习惯bootstrap,实践后发现能通过前后端设置bootstrap的属性,我为了省事儿没有在static文件夹保存bootstrap的文件,直接引用了

    后端代码如下:

    class Login(forms.Form):
        username = forms.CharField(label='用户名', widget=forms.TextInput(attrs={'class': 'form-control'}))
        # class:form-control 是bootstrap的输入框的一个样式

    前端代码如下:

    <head>
        <meta charset="UTF-8">
        <title>登陆</title>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    
        # 通过这直接远程引用了bootstrap
    
    </head>
    <body>
    <form action="{%url 'login_success'%}" , method='POST'>
        {% csrf_token %}
    <div class="col-md-3">
    
    # 这里是属于bootartap的一个栅栏样式
    
    {{login_form}}
    
    <button type="submit">登陆</button>
    </form>
    </div>

    返回的结果:

    熟悉的界面~

    上传文件

    走FORMS

    首先,写一个form模型,它必须包含一个FileField:

    # forms.py
    from django import forms
    
    class UploadFileForm(forms.Form):
        title = forms.CharField(max_length=50)
        file = forms.FileField()

    处理这个表单的视图将在request.FILES中收到文件数据,可以用request.FILES[‘file’]来获取上传文件的具体数据,其中的键值‘file’是根据file = forms.FileField()的变量名来的。

    注意:request.FILES只有在请求方法为POST,并且提交请求的
    具有enctype=”multipart/form-data”属性时才有效。 否则,request.FILES将为空。

    下面是一个接收上传文件的视图范例:

    # views.py
    
    from django.http import HttpResponseRedirect
    from django.shortcuts import render
    from .forms import UploadFileForm
    
    # 另外写一个处理上传过来的文件的方法,并在这里导入
    from somewhere import handle_uploaded_file
    
    def upload_file(request):
        if request.method == 'POST':
            form = UploadFileForm(request.POST, request.FILES) # 注意获取数据的方式
            if form.is_valid():
                handle_uploaded_file(request.FILES['file'])
                return HttpResponseRedirect('/success/url/')
        else:
            form = UploadFileForm()
        return render(request, 'upload.html', {'form': form})

    请注意,必须将request.FILES传递到form的构造函数中。

    form = UploadFileForm(request.POST, request.FILES)

    下面是一个处理上传文件的方法的参考例子:

    def handle_uploaded_file(f):
        with open('some/file/name.txt', 'wb+') as destination:
            for chunk in f.chunks():
                destination.write(chunk)

    遍历UploadedFile.chunks(),而不是直接使用read()方法,能确保大文件不会占用系统过多的内存。

    走MODELS

    如果是通过模型层的model来指定上传文件的保存方式的话,使用ModelForm更方便。 调用form.save()的时候,文件对象会保存在相应的FileField的upload_to参数指定的地方。

    from django.http import HttpResponseRedirect
    from django.shortcuts import render
    from .forms import ModelFormWithFileField
    
    def upload_file(request):
        if request.method == 'POST':
            form = ModelFormWithFileField(request.POST, request.FILES)
            if form.is_valid():
                # 这么做就可以了,文件会被保存到Model中upload_to参数指定的位置
                form.save()
                return HttpResponseRedirect('/success/url/')
        else:
            form = ModelFormWithFileField()
        return render(request, 'upload.html', {'form': form})

    如果手动构造一个对象,还可以简单地把文件对象直接从request.FILES赋值给模型:

    from django.http import HttpResponseRedirect
    from django.shortcuts import render
    from .forms import UploadFileForm
    from .models import ModelWithFileField
    
    def upload_file(request):
        if request.method == 'POST':
            form = UploadFileForm(request.POST, request.FILES)
            if form.is_valid():
                instance = ModelWithFileField(file_field=request.FILES['file'])
                instance.save()
                return HttpResponseRedirect('/success/url/')
        else:
            form = UploadFileForm()
        return render(request, 'upload.html', {'form': form})

    前端表单常用属性

    属性                         说明
    {{ login_form.label }}        字段对应的label信息
    {{ login_form.label_tag }}    自动生成字段的label标签,注意与{{ login_form.label }}的区别。
    {{ login_form.id_for_label }}    自定义字段标签的id
    {{ login_form.value }}         当前字段的值,比如一个Email字段的值someone@example.com
    {{ login_form.html_name }}     指定字段生成的input标签中name属性的值
    {{ login_form.help_text }}     字段的帮助信息
    {{ login_form.errors }}         包含错误信息的元素
    {{ login_form.is_hidden }}     用于判断当前字段是否为隐藏的字段,如果是,返回True
    {{ login_form.field }}         返回字段的参数列表。例如{{ char_field.field.max_length }}

    表单内置的Field类

    转载地址,侵删URL

    对于每个字段类,介绍其默认的widget,当输入为空时返回的值,以及采取何种验证方式。‘规范化为’表示转换为PYthon的何种对象。可用的错误信息键,表示该字段可自定义错误信息的类型(字典的键)。

    1. BooleanField

    默认的Widget:CheckboxInput
    空值:False
    规范化为:Python的True或者False
    可用的错误信息键:required

    ##2. CharField

    默认的Widget:TextInput
    空值:与empty_value给出的任何值。
    规范化为:一个Unicode 对象。
    验证max_length或min_length,如果设置了这两个参数。 否则,所有的输入都是合法的。
    可用的错误信息键:min_length, max_length, required
    有四个可选参数:
    
    max_length,min_length:设置字符串的最大和最小长度。
    strip:如果True(默认),去除输入的前导和尾随空格。
    empty_value:用来表示“空”的值。 默认为空字符串。

    ##3. ChoiceField
    默认的Widget:Select
    空值:’’(一个空字符串)
    规范化为:一个Unicode 对象。
    验证给定的值是否在选项列表中。
    可用的错误信息键:required, invalid_choice
    参数choices:用来作为该字段选项的一个二元组组成的可迭代对象(例如,列表或元组)或者一个可调用对象。格式与用于和ORM模型字段的choices参数相同。

    ##4. TypedChoiceField
    像ChoiceField一样,只是还有两个额外的参数:coerce和empty_value。

    默认的Widget:Select
    空值:empty_value参数设置的值。
    规范化为:coerce参数类型的值。
    验证给定的值在选项列表中存在并且可以被强制转换。
    可用的错误信息的键:required, invalid_choice

    ##5. DateField
    默认的Widget:DateInput
    空值:None
    规范化为:datetime.date对象。
    验证给出的值是一个datetime.date、datetime.datetime 或指定日期格式的字符串。
    错误信息的键:required, invalid
    接收一个可选的参数:input_formats。一个格式的列表,用于转换字符串为datetime.date对象。

    如果没有提供input_formats,默认的输入格式为:
    
    ['%Y-%m-%d',      # '2006-10-25'
     '%m/%d/%Y',      # '10/25/2006'
     '%m/%d/%y']      # '10/25/06'
    另外,如果你在设置中指定USE_L10N=False,以下的格式也将包含在默认的输入格式中:
    
    ['%b %d %Y',      # 'Oct 25 2006'
     '%b %d, %Y',     # 'Oct 25, 2006'
     '%d %b %Y',      # '25 Oct 2006'
     '%d %b, %Y',     # '25 Oct, 2006'
     '%B %d %Y',      # 'October 25 2006'
     '%B %d, %Y',     # 'October 25, 2006'
     '%d %B %Y',      # '25 October 2006'
     '%d %B, %Y']     # '25 October, 2006'

    ##6. DateTimeField
    默认的Widget:DateTimeInput
    空值:None
    规范化为:Python的datetime.datetime对象。
    验证给出的值是一个datetime.datetime、datetime.date或指定日期格式的字符串。
    错误信息的键:required, invalid
    接收一个可选的参数:input_formats

    如果没有提供input_formats,默认的输入格式为:
    
    ['%Y-%m-%d %H:%M:%S',    # '2006-10-25 14:30:59'
     '%Y-%m-%d %H:%M',       # '2006-10-25 14:30'
     '%Y-%m-%d',             # '2006-10-25'
     '%m/%d/%Y %H:%M:%S',    # '10/25/2006 14:30:59'
     '%m/%d/%Y %H:%M',       # '10/25/2006 14:30'
     '%m/%d/%Y',             # '10/25/2006'
     '%m/%d/%y %H:%M:%S',    # '10/25/06 14:30:59'
     '%m/%d/%y %H:%M',       # '10/25/06 14:30'
     '%m/%d/%y']             # '10/25/06'

    7. DecimalField

    默认的Widget:当Field.localize是False时为NumberInput,否则为TextInput。
    空值:None
    规范化为:Python decimal对象。
    验证给定的值为一个十进制数。 忽略前导和尾随的空白。
    错误信息的键:max_whole_digits, max_digits, max_decimal_places,max_value, invalid, required,min_value
    接收四个可选的参数:
    
    max_value,min_value:允许的值的范围,需要赋值decimal.Decimal对象,不能直接给个整数类型。
    
    max_digits:值允许的最大位数(小数点之前和之后的数字总共的位数,前导的零将被删除)。
    
    decimal_places:允许的最大小数位。

    ##8. DurationField
    默认的Widget:TextInput
    空值:None
    规范化为:Python timedelta。
    验证给出的值是一个字符串,而且可以转换为timedelta对象。
    错误信息的键:required, invalid.
    9. EmailField
    默认的Widget:EmailInput
    空值:’’(一个空字符串)
    规范化为:Unicode 对象。
    使用正则表达式验证给出的值是一个合法的邮件地址。
    错误信息的键:required, invalid
    两个可选的参数用于验证,max_length 和min_length。

    ##10. FileField
    默认的Widget:ClearableFileInput
    空值:None
    规范化为:一个UploadedFile对象,它封装文件内容和文件名到一个对象内。
    验证非空的文件数据已经绑定到表单。
    错误信息的键:missing, invalid, required, empty, max_length
    具有两个可选的参数用于验证:max_length 和 allow_empty_file。

    ##11. FilePathField
    默认的Widget:Select
    空值:None
    规范化为:Unicode 对象。
    验证选择的选项在选项列表中存在。
    错误信息的键:required, invalid_choice
    这个字段允许从一个特定的目录选择文件。 它有五个额外的参数,其中的path是必须的:

    path:要列出的目录的绝对路径。 这个目录必须存在。
    
    recursive:如果为False(默认值),只用直接位于path下的文件或目录作为选项。如果为True,将递归访问这个目录,其内所有的子目录和文件都将作为选项。
    
    match:正则表达模式;只有具有与此表达式匹配的文件名称才被允许作为选项。
    
    allow_files:可选。默认为True。表示是否应该包含指定位置的文件。它和allow_folders必须有一个为True。
    
    allow_folders可选。默认为False。表示是否应该包含指定位置的目录。

    ##12. FloatField
    默认的Widget:当Field.localize是False时为NumberInput,否则为TextInput。
    空值:None
    规范化为:Float 对象。
    验证给定的值是一个浮点数。
    错误信息的键:max_value, invalid, required, min_value
    接收两个可选的参数用于验证,max_value和min_value,控制允许的值的范围。

    ##13. ImageField
    默认的Widget:ClearableFileInput
    空值:None
    规范化为:一个UploadedFile 象,它封装文件内容和文件名为一个单独的对象。
    验证文件数据已绑定到表单,并且该文件是Pillow可以解析的图像格式。
    错误信息的键:missing, invalid, required, empty, invalid_image
    使用ImageField需要安装Pillow(pip install pillow)。如果在上传图片时遇到图像损坏错误,通常意味着使用了Pillow不支持的格式。

    ##14. IntegerField
    默认的Widget:当Field.localize是False时为NumberInput,否则为TextInput。
    空值:None
    规范化为:Python 整数或长整数。
    验证给定值是一个整数。 允许前导和尾随空格,类似Python的int()函数。
    错误信息的键:max_value, invalid, required, min_value
    两个可选参数:max_value和min_value,控制允许的值的范围。

    ##15. GenericIPAddressField
    包含IPv4或IPv6地址的字段。

    默认的Widget:TextInput
    空值:''(一个空字符串)
    规范化为:一个Unicode对象。
    验证给定值是有效的IP地址。
    错误信息的键:required, invalid
    有两个可选参数:protocol和unpack_ipv4

    ##16. MultipleChoiceField
    默认的Widget:SelectMultiple
    空值:[](一个空列表)
    规范化为:一个Unicode 对象列表。
    验证给定值列表中的每个值都存在于选择列表中。
    错误信息的键:invalid_list, invalid_choice, required
    ##17. TypedMultipleChoiceField
    类似MultipleChoiceField,除了需要两个额外的参数,coerce和empty_value。

    默认的Widget:SelectMultiple
    空值:empty_value
    规范化为:coerce参数提供的类型值列表。
    验证给定值存在于选项列表中并且可以强制。
    错误信息的键:required, invalid_choice

    ##18. NullBooleanField
    默认的Widget:NullBooleanSelect
    空值:None
    规范化为:Python None, False 或True 值。
    不验证任何内容(即,它从不引发ValidationError)。
    ##19.RegexField
    默认的Widget:TextInput
    空值:’’(一个空字符串)
    规范化为:一个Unicode 对象。
    验证给定值与某个正则表达式匹配。
    错误信息的键:required, invalid
    需要一个必需的参数:regex,需要匹配的正则表达式。

    还可以接收max_length,min_length和strip参数,类似CharField。

    ##20. SlugField
    默认的Widget:TextInput
    空值:’’(一个空字符串)
    规范化为:一个Unicode 对象。
    验证给定的字符串只包括字母、数字、下划线及连字符。
    错误信息的键:required, invalid
    此字段用于在表单中表示模型的SlugField。

    ##21. TimeField
    默认的Widget:TextInput
    空值:None
    规范化为:一个Python 的datetime.time 对象。
    验证给定值是datetime.time或以特定时间格式格式化的字符串。
    错误信息的键:required, invalid
    接收一个可选的参数:input_formats,用于尝试将字符串转换为有效的datetime.time对象的格式列表。

    如果没有提供input_formats,默认的输入格式为:
    
    '%H:%M:%S',     # '14:30:59'
    '%H:%M',        # '14:30'

    ##22. URLField
    默认的Widget:URLInput
    空值:’’(一个空字符串)
    规范化为:一个Unicode 对象。
    验证给定值是个有效的URL。
    错误信息的键:required, invalid
    可选参数:max_length和min_length

    ##23. UUIDField
    默认的Widget:TextInput
    空值:’’(一个空字符串)
    规范化为:UUID对象。
    错误信息的键:required, invalid
    ##24. ComboField
    默认的Widget:TextInput
    空值:’’(一个空字符串)
    规范化为:Unicode 对象。
    根据指定为ComboField的参数的每个字段验证给定值。
    错误信息的键:required, invalid
    接收一个额外的必选参数:fields,用于验证字段值的字段列表(按提供它们的顺序)。

    >>> from django.forms import ComboField
    >>> f = ComboField(fields=[CharField(max_length=20), EmailField()])
    >>> f.clean('test@example.com')
    'test@example.com'
    >>> f.clean('longemailaddress@example.com')
    Traceback (most recent call last):
    ...
    ValidationError: ['Ensure this value has at most 20 characters (it has 28).']

    ##25. MultiValueField
    默认的Widget:TextInput
    空值:’’(一个空字符串)
    规范化为:子类的compress方法返回的类型。
    根据指定为MultiValueField的参数的每个字段验证给定值。
    错误信息的键:incomplete, invalid, required
    ##26. SplitDateTimeField
    默认的Widget:SplitDateTimeWidget
    空值:None
    规范化为:Python datetime.datetime 对象。
    验证给定的值是datetime.datetime或以特定日期时间格式格式化的字符串。
    错误信息的键:invalid_date, invalid, required, invalid_time

    文章作者: Sxadmin
    文章链接: https://sxadmin.github.io/2019/07/08/Django-%E8%A1%A8%E5%8D%95%E5%A4%84%E7%90%86/
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Sxadmin blog
    打赏
    • 微信
      微信
    • 支付寶
      支付寶