Django模板语法和ModelForm

ModelForm 或者 Form组件的作用:

  1. 生成HTML标签
  2. 对POST过来的表单数据进行验证
  3. 直接将数据保存到数据库
  4. 获取表单错误信息
Django的管道操作

模板时间格式化显示

{{item.event_start|date:“Y-m-d H:i:s”}}
{{bio|truncatewords:“30”}}
{{my_list|first|upper}}
{{name|lower}}

Mysql时间转Python时间字符串
obj.create_time.strftime("%Y-%m-%d  %H:%M:%S"))
在模板中调用方法是不能加()的, 模板会自动帮我们添加.

models中,建立自定义枚举类的约束到数据库

gender_choices = (
        (1, "男"),
        (2, "女"),
    )
gender = models.SmallIntegerField(verbose_name="性别", choices=gender_choices)

python中获取Model中自定义的Enum名称,调用对应的get_gender_display()方法

obj.get_gender_display()

模板中调用该方法获取Enum名称时,不可以加()

{{ i.get_gender_display }}
ModelForm生成页面

本节中包含ModelForm字段中批量添加BootStrap5.1的实现,可以单独提取出来封装成一个类,配合BootStrap5.1一起使用

views中

class UserModelForm(ModelForm):
	# 自定义校验规则, 不自定义会启用默认校验规则
    name = forms.CharField(min_length=3, label="用户名")
    # password = forms.CharField(label="密码", validators='正则')
    
 	# 删除时间输入框的浏览器自动提示 方式1
    # create_time = forms.DateTimeField(label="入职时间", widget=forms.DateTimeInput(attrs={
    #     'autocomplete': 'off'
    # }))  
    
    # 自动生成html页面标签
    class Meta:
        model = UserInfo
        fields = ["name", "password", 'age', "account", "create_time", "gender", "depart"]
        
    # 循环找到所有的控件, 添加类名
    def __init__(self, *args, **kwargs):
        super(UserModelForm, self).__init__(*args, **kwargs)        
        for name, field in self.fields.items():
            # name 字段名
            # field 字段对应的对象
            # 字段中有属性,保留原来的属性,没有属性,才增加
            if field.widget.attrs:
                field.widget.attrs['class'] = 'form-control'
                field.widget.attrs['placeholder'] = field.label
            else:
                field.widget.attrs = {"class": "form-control", "placeholder": field.label}
            # 如果是时间输入,屏蔽掉浏览器自带的输入提示,方便DateTimePicker的显示
            if name == "create_time":
                field.widget.attrs['autocomplete'] = 'off'

def user_mode_form_add(request):
    """ 添加用户 (ModelForm版本)"""
    form = UserModelForm()
    return render(request, "app01/user_model_form_add.html", locals())
    def user_mode_form_add(request):

    # 用户POST提交数据,数据校验
    form = UserModelForm(data=request.POST)
    if form.is_valid():
        # 校验成功,入库
        # print(form.cleaned_data)
        # 自动入库
        form.save()
        return redirect("/user/list/")
    
    # 验证失败 ,页面显示错误信息
    print(form.errors)
    return render(request, "app01/user_model_form_add.html", locals())

templates中
其中DateTimePicker不是关注点, 文中忽略
模板中直接调用form中的field,对于字段是外键的,如果不做任何处理,返回的是对象类型.

<form method="post" novalidate>
    {% csrf_token %}
    {% for field in form %}
       <div class="mb-3">
       		{# ModelForm类自动生成面页标签和面页控件 #}
           <label for="name" class="form-label">{{ field.label }}label>
           {{ field }}
           <span style="color:red;">{{ field.errors.0 }} span>{# [error1 error2] #}
       div>
    {% endfor %}
    <button type="submit" class="btn btn-primary btn-sm">保存button>
form>
解决ModelForm返回外键引用的对象的问题.

models中

class Department(models.Model):
    # 部门表
    title = models.CharField(verbose_name="部门名称", max_length=32)

    def __str__(self):
        # 解决ModelForm的外键引用返回对象的问题.
        return self.title
MD5加密

对于密码输入框的加密处理
自定义一个模块
用md5加密,再加上django自带的盐

import hashlib
from django.conf import settings

def md5(data_string):
    salt = settings.SECRET_KEY
    obj = hashlib.md5(salt.encode("utf-8"))
    obj.update(data_string.encode("utf-8"))
    return obj.hexdigest()
用钩子方法对密码校验和提交前的校验

在views中

class AdminModelForm(BootStrapModelForm):
    # 数据表中没有,但是我们需要添加一个字段的处理方式
    confirm_password = forms.CharField(
        label="确认密码",
        # render_value=True,密码错误的时候页不会清空输入框
        widget=forms.PasswordInput(render_value=True))

    class Meta:
        model = Admin
        fields = "__all__"
        widgets = {
            "password": forms.PasswordInput
        }

    # 定义钩子方法 在数据提交到数据库前的操作
    def clean_password(self):
        pwd = self.cleaned_data.get("password")
        return md5(pwd)

    # 勾到confirm_password字段上
    def clean_confirm_password(self):
        # print(self.cleaned_data)
        pwd = self.cleaned_data.get("password")
        confirm = self.cleaned_data.get("confirm_password")
        confirm = md5(confirm)
        if pwd != confirm:
            # 抛自定义的异常
            raise ValidationError("密码不一致")
        # 如果不抛异常,就会直接return confirm这个值, 并且通过form.save()入库
        return confirm
利用Form主动添加一个错误

在做密码验证的时候,如果用户名或者密码错误,可以通过向form中主动添加错误的方式来提示用户
在views中

 exists = Admin.objects.filter(**form.cleaned_data).exists()
        if exists:
            return redirect("/admin/list/")
        else:
            # 主动在form中显示一个错误
            form.add_error("password", "用户名或者密码错误")
            return render(request, "app01/login.html", locals())
用Ajax发送post请求时,避免跨域问题的方法

在views中,函数前添加一个装饰器

@csrf_exempt
def task_ajax(request):
    print(request.POST)
    return HttpResponse("不刷页面发送请求")

你可能感兴趣的:(django,django,python)