Django之ModelForm

一、说明

 应用场景:
            - ModelForm - 中小型应用程序。因为ModelForm是依赖于models的
            - Form      - 大型应用程序  *

二、参数说明 

ModelForm
    a.  class Meta:
            model,                           # 对应Model的
            fields=None,                     # 字段
            exclude=None,                    # 排除字段
            labels=None,                     # 提示信息
            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={...})

注意事项:

注意事项:
            - 1. 类 
                  class Foo(ModelForm):
                    class Meta:
                        # model = models.Role
                        # fields = "__all__"
                        # fields = ['caption',]
                        # exclude = ['catpion']
                        model = models.UserType
                        fields = "__all__"

                        error_messages = {
                            'title':{'required':'名称不能为空','invalid':'格式错误'}
                        }
                        widgets = {
                            'title':wd.TextInput(attrs={'class':'c1'})
                        }
                
            - 2. 添加
                 GET:
                    form = Foo()
                 POST:
                    form = Foo(data=request.POST)
                    form.is_valid()
                    form.cleaned_data
                    form.erros
                    form.save()
            - 3. 修改
                 GET:
                    form = Foo(instance=obj)
                 
                 POST:
                    form = Foo(instance=obj,dat=request.POST)
                    ...
                    form.save()

 

三、实例

示例1、简单增删改查

class MyModelForm(ModelForm):
    class Meta:
        model = models.XXX.objects.get(xxx)
        fields = "__all__"

    _m = type("Meta", (object,), {"model": models.XXX.objects.get(xxx), "fields": "__all__"})
    MyModelForm = type("MyModelForm", (ModelForm,), {"Meta": _m})


# 如果request.method == "GET",即初始化页面,不带初始值
model_form_obj = MyModelForm()



# 如果request.method == "GET",即初始化页面,带初始值
obj = models.XXX.objects.get(pk=pk)
model_form_obj = MyModelForm(instance=obj)
初始化页面
    <form method="POST" novalidate>
        {% csrf_token %}
{#        {{ form.as_p }}#}
{#        <div>===================</div>#}
        {% for item in form %}
            <div>{{ item.name }}:{{ item }}</div>
        {% endfor %}

        <input type="submit">
    </form>
html
return render(request, "xxx.html", {"form":model_form_obj})
views.py

 

from django.forms import ModelForm

class MyModelForm(ModelForm):
    class Meta:
        model = models.XXX.objects.get(xxx)
        fields = "__all__"

    _m = type("Meta", (object,), {"model": models.XXX.objects.get(xxx), "fields": "__all__"})
    MyModelForm = type("MyModelForm", (ModelForm,), {"Meta": _m})


model_form_obj = MyModelForm(data=request.POST,files=request.FILES)
model_form_obj.save()
class MyModelForm(ModelForm):
    class Meta:
        model = models.XXX.objects.get(xxx)
        fields = "__all__"

    _m = type("Meta", (object,), {"model": models.XXX.objects.get(xxx), "fields": "__all__"})
    MyModelForm = type("MyModelForm", (ModelForm,), {"Meta": _m})


# 如果request.method == "GET",即初始化页面,带初始值
obj = models.XXX.objects.get(pk=pk)
model_form_obj = MyModelForm(instance=obj)


# 如果request.method == "POST",即页面post上来进行修改
model_form_obj = MyModelForm(data=request.POST,files=request.FILES,instance=obj)
model_form_obj.save()

 

示例2

from django.shortcuts import render,redirect
from app01 import models
from django.forms import ModelForm

class TestModelForm(ModelForm):
    class Meta:
        model = models.UserInfo
        fields = "__all__"
        # fields = ("user","email")
        error_messages = {
            "user":{"required":"用户名不能为空"},
            "email":{"required":"email不能为空","invalid":"邮箱格式错误"},
        }

def test(request):
    # return TemplateResponse(request,[] or ['xiaohaohao.tml',"test.html"],{"k1":"v1"})
    if request.method == "GET":
        form = TestModelForm()
        context = {
            "form":form,
        }
        return render(request,"test.html",context)
    else:
        form = TestModelForm(request.POST)
        if form.is_valid():
            print(form.cleaned_data)
            form.save()  # ModelForm具有models功能,可直接save
            # models.UserInfo.objects.create(**form.cleaned_data)
            # return redirect("http://www.baidu.com")
        context = {
            "form":form,
        }
        return render(request,"test.html",context)

def edit(request,nid):
    obj = models.UserInfo.objects.filter(id=nid).first()
    if request.method == "GET":
        form = TestModelForm(instance=obj)
        context = {
            "form":form,
        }
        return render(request,"edit.html",context)

    else:
        form = TestModelForm(instance=obj,data=request.POST,files=request.FILES)
        if form.is_valid():
            form.save()
            return redirect("http://www.baidu.com")
views.py + ModelForm
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>test页面</h1>
    <form method="POST" >
        {% csrf_token %}
{#        {{ form.as_p }}#}
        <p>name:{{ form.user }}{{ form.user.errors.0 }}</p>
        <p>email:{{ form.email }}{{ form.email.errors.0 }}</p>
        <p>ug:{{ form.ug }}{{ form.ug.errors.0 }}</p>
        <p>m2m:{{ form.m2m }}{{ form.m2m.errors.0 }}</p>
        <input type="submit">
    </form>
</body>
</html>
test.html

示例3 注意,1对多、多对多也是这样form.save()

"""first_review URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path,re_path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path("app01/",include("app01.urls")),
    re_path("testmodelform/",include("testmodelform.urls")),
]



############## /testmodelform/urls.py

from django.contrib import admin
from django.urls import path,re_path,include
from testmodelform import views

urlpatterns = [
    re_path("index/",views.index),
    re_path("user_add/",views.UserAdd.as_view()),
    re_path("user_edit/(?P<pk>\d+)/",views.UserEdit.as_view()),
]
urls.py
from django.db import models

# Create your models here.
class UserInfo(models.Model):
    username = models.CharField(max_length=16)
    password = models.CharField(max_length=16)
    email = models.EmailField()

    def __str__(self):
        return "{}-{}".format(self.username,self.email)
models.py
# -*- coding:utf-8 -*-
from django.forms import fields,models,widgets,Form

class UserInfoForm(Form):
    username = fields.CharField(required=True,max_length=16,error_messages={"required":"不能为空"})
    password = fields.CharField(required=True,max_length=16,widget=widgets.PasswordInput,error_messages={"required":"不能为空"})
    email = fields.EmailField(required=True,error_messages={"required":"不能为空"})
form.py(此示例用了普通、form、modelform三种方法,此为form)
from django.shortcuts import render,HttpResponse,redirect
from testmodelform import models
from django.views import View
from testmodelform import form
from django.forms import ModelForm,widgets




class UserInfoModelForm(ModelForm):
    class Meta:   #这个类必须写,而且名字必须是这个
        model = models.UserInfo   #这个model也是固定的,注意不加s,
        # fields = "__all__"   #代表所有的字段,但是你也可以指定单个的字段
        fields = ["username","password","email"]
        exclude = []

        error_messages = {
            "username":{"required":"用户名不能为空"},
            "password":{"required":"密码不能为空"},
            "email": {"required": "email不能为空", "invalid": "邮箱格式错误"},
        }
        widgets = {
            "password":widgets.PasswordInput,
        }



class UserAdd(View):

    ###### 普通 ######
    # def get(self,request):
    #
    #     return render(request,"user_add.html")
    #
    # def post(self,request):
    #     data = request.POST
    #     res = models.UserInfo.objects.create(
    #         username=data.get("username"),
    #         password=data.get('password'),
    #         email=data.get("email")
    #     )
    #     print(res.id)
    #     return HttpResponse("OK")

    ###### form ######
    # def get(self, request):
    #     obj = form.UserInfoForm(initial={"username":"用户名"})
    #     return render(request, "user_add.html",{"form":obj})
    #
    # def post(self, request):
    #     obj = form.UserInfoForm(request.POST,request.FILES)
    #     if obj.is_valid():
    #         data = obj.cleaned_data
    #         res = models.UserInfo.objects.create(
    #             username=data.get("username"),
    #             password=data.get('password'),
    #             email=data.get("email")
    #         )
    #         print(res.id)
    #         return HttpResponse("OK")
    #     else:
    #         print(obj.errors)
    #         return render(request,"user_add.html",{"form":obj})

    ###### modelform ######
    def get(self,request):
        obj = UserInfoModelForm(initial={"username":"用户名"})
        context = {
            "form":obj,
        }
        return render(request,"user_add.html",context)

    def post(self,request):
        obj = UserInfoModelForm(request.POST)
        if obj.is_valid():
            print(obj.cleaned_data)
            obj.save()
            return HttpResponse("ok")
        else:
            return render(request,"user_add.html",{"form":obj})


class UserEdit(View):
    def get(self,request,pk):
        obj = models.UserInfo.objects.get(pk=pk)
        user_obj = UserInfoModelForm(instance=obj)
        context = {
            "pk":pk,
            "form":user_obj
        }
        return render(request,"user_edit.html",context)

    def post(self,request,pk):
        obj = models.UserInfo.objects.get(pk=pk)
        user_obj = UserInfoModelForm(request.POST,instance=obj)
        if user_obj.is_valid():
            user_obj.save()
            return HttpResponse("ok")
        else:
            return render(request, "user_edit.html", {"form": obj})
views.py(含modelform)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>user_edit</h1>
    <form action="/testmodelform/user_add/" method="POST" novalidate>
        {% csrf_token %}
        {# 普通 #}
{#        <div>用户名:<input type="text" name="username"></div>#}
{#        <div>密码:<input type="password" name="password"></div>#}
{#        <div>邮箱:<input type="email" name="email"></div>#}
        {# form #}
{#            <div>{{ form.username }}{{ form.username.errors.0 }}</div>#}
{#            <div>{{ form.password }}{{ form.password.errors.0 }}</div>#}
{#            <div>{{ form.email }}{{ form.email.errors.0 }}</div>#}
        {# modelform #}
            <div>{{ form.username }}{{ form.username.errors.0 }}</div>
            <div>{{ form.password }}{{ form.password.errors.0 }}</div>
            <div>{{ form.email }}{{ form.email.errors.0 }}</div>

        <input type="submit" value="submit">
    </form>
</body>
</html>
user_add.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>useredit</h1>
<form action="/testmodelform/user_edit/{{ pk }}/" method="POST" novalidate>
    {% csrf_token %}
    {{ form.username }}
    {{ form.password }}
    {{ form.email }}
    <input type="submit">

</form>

</body>
</html>
user_edit.html

 

posted @ 2018-04-24 14:53  fat39  阅读(148)  评论(0编辑  收藏  举报