Python全栈:Django表单及应用

1 Django表单介绍

常见的表单元素:

  • 表单标签——<form>
  • 单行文本框/多行文本框
  • 选择(单选、多选、下拉选择)
  • 隐藏表单域
  • 表单按钮
  • 文件上传框

Django中的表单:

  • 框架自带
    • Flask是使用FlaskWTF库

表单使用的步骤:

  • 第一步:创建表单类

    • from django import forms
      
      class LoginForm(forms.Form):
          """ 登录表单 """
          username = forms.CharField(label='用户名', max_length = 100)
      
  • 第二步:添加到视图

    • views.py

    • def user_login(request):
          """ 用户登录 """
          form = LoginForm()
          return render(request, 'user_login.html', {
              'form':form
          })
      
    • urls.py

    • # 用户登录表单
      path('user/login/', views.user_login, name='user_login'),
      
  • 第三步:渲染到模板

    • as_p()

    • as_ul()

    • as_table()

    • <body>
          <h3>用户登录</h3>
          <form action=".">
              {{ form.as_p }}
              <input type="submit" value="登录">
          </form>
      
      </body>
      
  • 第四步:在视图中处理表单数据

    • <form action="." method="post">

    • def form(request):
          # 表单对象
          if request.method == 'POST':
              form = LoginForm(request.POST)
              if form.is_valid():
      			data = form.cleaned_data
                  print('data:',data)
          else:
              form = LoginForm()
          return render(request, 'form.html', {
              'form':form
          })
      

表单字段

  • 表单字段继承自 django.forms.Field
  • 每个字段都具有核心参数
  • 每个字段都可以有自定义的验证逻辑
  • 每个字段都有钩子函数,方便扩充功能

字段的常用参数:

  • label——label标签(如:输入框前的文字描述)
  • required——是否为必填,默认为必填
  • help_text——帮助文字
  • initial——初始化数据
  • error_messages——覆盖字段引发异常后的错误显示
  • widget——定制界面显示方式(如:文本框、选择框)
  • disabled——禁用表单,界面上不可操作

2 Django内置的表单字段

  • 文本/字符串
    • CharField——字符串输入
    • EmailField——邮件地址输入
    • URLField——URL地址输入
    • UUIDField——uuid字符串输入
  • 数值(整数/小数)
    • IntegerField——整数输入
    • FloatField——浮点数输入
    • DecimalField——小数输入(更精确)
  • 选择(单选/多选)
    • ChoiceField——单选
    • MultipleChoiceField——多选
    • TypedChoiceField——高级选择(支持结果转换类型)
  • 日期/时间
    • DateField——日期选择
    • DateTimeField——日期时间选择
    • DurationField——时间片段timedelta
    • TimeField——时间选择
  • 文件/文件上传
    • ImageField——图片
    • FileField——文件
    • FilePathField——文件路径
  • 布尔
    • BooleanField——True/False
    • NullBooleanField——None/True/False
  • 正则表达式
    • RegexField——正则输入

3 Django创建用户注册表单

设计注册表单:

  • 用户名
  • 密码
  • 用户昵称
  • 生日

在视图中获取表单值:

  • GET请求
    • request.GET.get('name', None)
  • POST请求
    • request.POST.get('name', None)
  • 文件对象
    • request.FILES.get('name', None)

表单类的可选参数:

  • initial——初始化参数

    • def user_reg(request):
          """ 用户注册 """
          if request.method == 'POST':
              data = request.POST
              print('post data:',data)
      
          initial_data = {
              'username':'默认昵称',
              'birth_data':'2000-1-1'
          }
      
          form = UserRegForm(initial=initial_data)
          return render(request, 'user_reg.html',{
              'form':form
          })
      
  • data——表单数据

  • files——文件对象

Form对象的方法:

  • as_p()/as_ul()/as_table()——渲染表单
  • is_valid()——表单是否已经通过验证
  • clean()——调用表单的验证/自定义的验证
  • is_bound——是否已经绑定了属性
  • cleaned_data——访问表单验证后的数据
  • errors——表单验证后的错误信息
  • initial——初始化数据
  • fields——表单中的字段
def user_reg(request):
    """ 用户注册 """
    if request.method == 'POST':
        data = request.POST
        print('post data:',data)
        form = UserRegForm(data=request.POST, files=request.FILES)
        # 是否已经通过验证
        if form.is_valid():
            form_data = form.cleaned_data
            print('验证通过后的数据:',form_data)
        else:
            # 表单没有通过验证
            print(form.errors)
    else:
        initial_data = {
            'username':'默认昵称',
            'birth_date':'2000-1-1'
        }
        form = UserRegForm(initial=initial_data)

    return render(request, 'user_reg.html',{
        'form':form
    })

4 自定义界面显示

  • 密码输入
  • URL输入、Email输入、日期输入等
  • 多行文本输入

示例代码:

class CommentForm(forms.Form):
    """ 评论表单 """
    content = forms.CharField(
    	label = '内容',
        widget = forms.Textarea
    )

内置的widgets:

  • 文本输入

    • TextInput
    • NumberInput
    • EmailInput
    • URLInput
    • PasswordInput
    • HiddenInput
    • DateInput
    • DateTimeInput
    • TimeInput
    • Textarea
  • 选择输入

    • Select
    • NullBooleanSelect
    • RadioSelect
    • SelectMultiple
    • CheckboxSelectMultiple
  • 文件上传

    • FileInput
  • 复合Widget

    • MultipleHiddenInput
    • SplitDateTimeWidget、SplitHiddenDateTimeWidget
    • SelectDateWidget

5 单个字段的表单验证

表单验证的步骤:

  • 第一步:定义clean_xx验证方法
  • 第二步:获取对应的字段值并验证
  • 第三步:验证失败触发forms.ValidationError异常
  • 第四步:返回验证后的数据
  • 第五步:在html页面显示错误

forms.py

class LoginForm(forms.Form):
  """ 登录表单 """
  username = forms.CharField(label='用户名',
                             max_length=100,
                             required=False,
                             help_text='使用帮助',
                             initial='admin')

  def clean_username(self):
      """ 验证用户名 hook 钩子函数 """
      username = self.cleaned_data['username']
      pattern = r'^1[0-9]{10}$'
      if not re.search(pattern, username):
          raise forms.ValidationError('请输入手机号码')
      return username

views.py

def user_login(request):
    """ 用户登录 """
    if request.method == 'POST':
        form = LoginForm(data=request.POST)
        if form.is_valid():
            print('表单验证通过')
        else:
            print(form.errors)
    else:
        form = LoginForm()
    return render(request, 'user_login.html', {
        'form': form
    })

6 多个字段的综合验证

  • 第一步:重写 clean()方法
  • 第二步:获取用户名和密码数据并验证
  • 第三步:验证失败触发 forms.ValidationError异常
  • 第四步:返回验证后的表单数据 cleaned_data
  • 第五步:在html页面显示错误 non_filed_errors
class LoginForm(forms.Form):
    """ 登录表单 """
    username = forms.CharField(label='用户名',
                               max_length=100,
                               required=False,
                               help_text='使用帮助',
                               initial='admin')
    password = forms.CharField(label='密码', max_length=200, min_length=6,
                               widget=forms.PasswordInput)

    def clean_username(self):
        """ 验证用户名 hook 钩子函数 """
        username = self.cleaned_data['username']
        pattern = r'^1[0-9]{10}$'
        if not re.search(pattern, username):
            raise forms.ValidationError('手机号%s输入不正确',
                                        code='invalid_phone',
                                        params=(username, ))
        return username

    def clean(self):
        data = super().clean()
        print(data)
        # 如果单个字段有错误,直接返回,不执行后面的验证
        if self.errors:
            return
        username = data['username']
        password = data['password']
        # username = data.get('username', None)
        # password = data.get('password', None)
        if username and password:
            # 查询用户名和密码匹配的用户
            user_list = User.objects.filter(username=username)
            err_list = []
            if user_list.count() == 0:
                err_list.append(forms.ValidationError('用户名不存在'))
                # raise forms.ValidationError('用户名不存在')
            # 验证密码是否正确
            # TODO 使用加密算法进行验证
            if not user_list.filter(password=password).exists():
                # raise forms.ValidationError('密码不正确')
                err_list.append(forms.ValidationError('密码不正确'))
            if err_list:
                raise forms.ValidationError(err_list)
        return data

7 从ORM模型创建表单

ORM模型VS表单模型:

image-20210207141208820

image-20210207141311650

models.py

class User(CommonModel):
    """ 用户基本信息 """
    USER_STATUS = (
        (1, '正常'),
        (0, '删除'),
    )
    username = models.CharField('用户名', max_length=128, unique=True, editable=False)
    password = models.CharField('密码', max_length=256)
    nickname = models.CharField('用户昵称', max_length=256, null=True, blank=True)
    avatar = models.ImageField('用户头像', upload_to='avatar', null=True, blank=True)
    status = models.SmallIntegerField('用户状态', default=1, choices=USER_STATUS)
    is_super = models.BooleanField('是否为超级用户', default=False)
    created_at = models.DateTimeField('注册时间', auto_now_add=True)
    updated_at = models.DateTimeField('更新时间', auto_now=True)

    # users = models.Manager()

    class Meta:
        db_table = 'accounts_user'

    def __str__(self):
        return 'User: {}'.format(self.username)

forms.py

class UserChangeForm(forms.ModelForm):
    """ 从模型创建表单 -- 用户基本信息修改 """
    class Meta:
        model = User
        # fields = ('username', 'password', 'nickname', 'avatar')
        exclude = ('status', )

views.py

def user_change(request):
    """ 用户信息维护-基于ORM创建的表单 """
    if request.method == 'POST':
        form = UserChangeForm(data=request.POST)
        if form.is_valid():
            print('表单通过验证')
    else:
        form = UserChangeForm()
    return render(request, 'user_change.html', {
        'form': form
    })
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超级D洋葱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值