Python学习---ModelForm拾遗180325

image

ModelForm适用于前台验证和后台直接操作数据库的前后台未做分离,可以一次执行验证和保存数据的场景。

注意:  1.  ModelForm里面没有删除方法,需要手动删除内容

2. ModelForm里面也可以像Form里面一样自定义clean_email()和clean()方法进行数据正确性的验证【post_clean()方法需要自定义try...except

ModelForm创建信息

settings.py

INSTALLED_APPS = [
   ...
 'app01',   # 注册app
]
STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),)  # 现添加的配置,这里是元组,注意逗号
TEMPLATES = [
   ...
   'DIRS': [os.path.join(BASE_DIR, 'templates')],
]

urls.py

from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include
from app01 import views
urlpatterns = [
   url('modelFormDemo/', views.modelFormDemo),
]

views.py

from django.shortcuts import render, redirect, HttpResponse
from app01 import models
# ModelForm实例
from django import forms as modelForm
from app01 import models
class UserModelForm(modelForm.ModelForm):
    # 自动帮我们拿到了关联数据,且我们不需要操作什么,就可以直接实时刷新数据
    class Meta:
        # 说明指向,指定去执行U里面的内容
        model = models.U
        # 指定类中的字段,告诉ModelForm帮我们处理多少字段
        fields = '__all__'   # 这里是帮我们处理所有字段

def modelFormDemo(request):
    if request.method == "GET":
        obj = UserModelForm()
        return render(request, 'modelFormDemo.html', {"obj":obj})
    else :
        obj = UserModelForm(request.POST)
        if obj.is_valid():
            data = obj.clean()
            print('正确数据:', data)
            #  这个是以前我们Model操作来进行增加数据:models.U.objects.create(**data)
            obj.save()  # 这个是ModelForm直接帮我们添加数据,同样也适用于多对多的情况
        err = obj.errors
        print('错误数据:', err)
        return render(request, 'modelFormDemo.html', {"obj":obj})

templates/modelFormDemo.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    {#as_p是从BaseForm里面的方法#}
    <form action="/modelFormDemo/" method="POST">
        {{ obj.as_p }}
        <input type="submit" value="提交">
    </form>
</body>
</html>

models.py

from django.db import models
class U(models.Model):
    id = models.AutoField(primary_key=True)  # AutoField必须是主键,才能自定义该列
    name = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    userType = models.ForeignKey("UT", on_delete=True)  # 1对多[无法用自定义,有约束关系]

class UT(models.Model):
    caption = models.CharField(max_length=32)
    def __str__(self):
        return self.caption

页面显示;

image

初始化数据库

python manage.py makemigrations
python manage.py migrate

ModelForm之实时更新下拉框数据

settings.py

INSTALLED_APPS = [
   ...
 'app01',   # 注册app
]
STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),)  # 现添加的配置,这里是元组,注意逗号
TEMPLATES = [
   ...
   'DIRS': [os.path.join(BASE_DIR, 'templates')],
]

urls.py

from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include
from app01 import views
urlpatterns = [
    url('edit_UserModelForm-(\d+)/', fm.edit_UserModelForm),
]

views.py

from django.shortcuts import render, redirect, HttpResponse
from app01 import models
# ModelForm实例
from django import forms as modelForm
class UserModelForm(modelForm.ModelForm):
    # 自动帮我们拿到了关联数据,且我们不需要操作什么,就可以直接实时刷新数据
    class Meta:
        # 说明指向,指定去执行U里面的内容
        model = models.U
        # 指定类中的字段,告诉ModelForm帮我们处理多少字段
        fields = '__all__'   # 这里是帮我们处理所有字段

# 修改ModelForm内容
def edit_UserModelForm(request, nid):
    if request.method == "GET":
        obj_model = models.U.objects.get(id=nid)  # 后台数据库的数据
        obj = UserModelForm(instance=obj_model)  # 把数据库的数据给了ModelForm
        return render(request, 'modelFormDemo.html', {"obj": obj})  # 进行页面显示
    else:
        obj_model = models.U.objects.get(id=nid)  # 后台数据库的数据
        # 如果有instance则修改,没有则添加新数据
        obj = UserModelForm(request.POST, instance=obj_model)  # 获取前台提交的数据进行更新操作
        if obj.is_valid():
            data = obj.clean()
            print('正确数据:', data)
            #  这个是以前我们Model操作来进行增加数据:models.U.objects.create(**data)
            obj.save()  # 这个是ModelForm直接帮我们添加数据,同样也适用于修改数据的情况
        return render(request, 'edit_modelFormDemo.html', {"obj": obj, 'nid':nid})  # 进行页面显示

templates/edit_modelFormDemo.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    {#as_p是从BaseForm里面的方法#}
    <form action="/edit_UserModelForm-{{ nid }}/ " method="POST">
        {{ obj.as_p }}
        <input type="submit" value="提交">
    </form>
</body>
</html>

models.py

from django.db import models
class U(models.Model):
    id = models.AutoField(primary_key=True)  # AutoField必须是主键,才能自定义该列
    name = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    userType = models.ForeignKey("UT", on_delete=True)  # 1对多[无法用自定义,有约束关系]

class UT(models.Model):
    caption = models.CharField(max_length=32)
    def __str__(self):
        return self.caption

页面显示;

image

image

初始化数据库

python manage.py makemigrations
python manage.py migrate

ModelForm之save()方法分析

save()方法的集成度非常高,帮我们可以保存当前表的数据也可以保存多对多表的数据,一对多也是在当前表中,内部默认做了这些事

image

手动提交内容:

image

ModelForm之Meta的配置选项

ModelForm
a.class Meta:
    model,           # 对应Model的
    fields = None,   # 字段
    exclude = None,  # 排除字段
    labels = None,   # 提示信息
labels = {‘email’:‘邮箱’,’username’:’用户名’}
    help_texts = None,  # 帮助提示信息
    widgets = None,     # 自定义插件
    error_messages = None,  # 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS)
    field_classes = None  # 自定义字段类 (也可以自定义字段)
    localized_fields = ('birth_date',)  # 本地化,如:根据不同时区显示数据
        如:
        数据库中         2016 - 12 - 27 04: 10:57
        setting中的配置
            TIME_ZONE = 'Asia/Shanghai'
            USE_TZ = True
        则显示:
            2016 - 12 - 27  12: 10:57
b.验证执行过程
    is_valid -> full_clean -> 钩子 -> 整体错误
c.字典字段验证
    def clean_字段名(self):
        # 可以抛出异常
        # from django.core.exceptions import ValidationError
        return "新值"
d.用于验证
    model_form_obj = XXOOModelForm()
    model_form_obj.is_valid()
    model_form_obj.errors.as_json()
    model_form_obj.clean()
    model_form_obj.cleaned_data
e.用于创建
    model_form_obj = XXOOModelForm(request.POST)
    #### 页面显示,并提交 #####
    # 默认保存多对多
    obj = form.save(commit=True)
    # 不做任何操作,内部定义 save_m2m(用于保存多对多)
    obj = form.save(commit=False)
    obj.save()  # 保存单表信息
    obj.save_m2m()  # 保存关联多对多信息

f.用于更新和初始化
    obj = model.tb.objects.get(id=1)
    model_form_obj = XXOOModelForm(request.POST, instance=obj)
    ...

    PS: 单纯初始化
    model_form_obj = XXOOModelForm(initial={...}) 

# ModelForm实例

views.py

from django import forms as modelForm
from app01 import models
# 自动帮我们拿到了关联数据,且我们不需要操作什么,就可以直接实时刷新数据
class UserModelForm(modelForm.ModelForm):
# 相当于在Model中U类的基础上有新添加了一个字段,属自定制内容
# 如果有跟数据库内的字段重名了,则会覆盖数据库字段的验证功能[Email验证功能]
# email = forms.CharField()  -->此时就是一个普通的char类型,遵循Form优先的原则
# 总结一下就是: 如果跟数据库不重名,则页面增加一条输入框; 
# 如果重名,则会覆盖原来【Form优先】
# 适用于那种一个月自动登录功能。可以从用户处多拿一个字段到后台进行验证功能
pwd = forms.CharField()   # 此时数据库内并无此字段,这里添加后页面会增加此字段
    class Meta:
        # 说明指向,指定去执行U里面的内容【只能指定一个Model类】
        model = models.U
        # 指定类中的字段,告诉ModelForm帮我们处理多少字段
        fields = '__all__'   # 这里是帮我们处理所有字段,包括多对多的数据
        # fields = ['name', 'email']  # 处理某几个字段
        # exclude = ['name']   # 排除username的页面显示
        labels = {
            'name': '用户名',
            'email': '邮 箱'
        }
        help_texts = {
            'email':"*",
            'name':'请输入姓名'
        }
        # 自定义插件
        from django.forms import widgets as ws
        from django.forms import forms as ff
        widgets = {
            'email': ws.Textarea()
        }
        error_messages = {
'__all__':{‘required’:‘必填内容’},# 全局错误信息集
            'name': {'required':'必填项', 'invalid':'格式错误'}
        }
        # 自定义字段类,进行二次验证
        field_classes = {
            'name':  ff.EmailField  # 虽然数据库时CharField,这里要求页面用EmailField进行正则验证
        }

models.py

from django.db import models
class U(models.Model):
    id = models.AutoField(primary_key=True)  # AutoField必须是主键,才能自定义该列
    name = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    userType = models.ForeignKey("UT", on_delete=True)  # 1对多[无法用自定义,有约束关系]
class UT(models.Model):
    caption = models.CharField(max_length=32)
    def __str__(self):
        return self.caption

ModelForm操作:http://www.cnblogs.com/wupeiqi/articles/6229414.html

猜你喜欢

转载自www.cnblogs.com/ftl1012/p/9418504.html