Day23内容回顾--缺失,遗憾成狗。

一:Model(2个功能)

  -数据库操作;

  -验证,只有一个clean方法可以作为钩子。

二:Form(专门来做验证的)--------根据form里面写的类,类里面有字段,这个字段是内置的正则表达式。

  例如:-class LoginForm(Form): email=fields.EmailField()

  -is_valid(触发验证功能) ->每一个字段进行正则(用的是字段内置的正则)+clean_字段 -> clean(__all__) -> _post_clean。

      form的钩子,先进行每一个字段正则表达式验证,然后每一个字段的方法,然后进行clean,clean完了以后是post clean

      email的错误信息放在email [大列表里面了], 整体的错误信息放在了 __all__  里面了。

  -cleaned_data

  -error

建议分开使用上面的两个模块:Model+Form,这样可以降低耦合。但是代码有重复。

Day24:  环境搭建,参考http://www.cnblogs.com/momo8238/p/7508677.html

一,基于form来做。

创建2张表备用,2张表之间用ForeignKey进行关联:

models.py

from django.db import models

# Create your models here.
class UserType(models.Model):
caption=models.CharField(max_length=32) class UserInfo(models.Model):
username = models.CharField(max_length=32)
email=models.EmailField()
user_type=models.ForeignKey(to='UserType',to_field='id')

创建

python manage.py makemigrations
python manage.py migrate

2. 如果我想在index.html页面上对UserInfo表进行操作,那么应该把UserInfo 表中的所有信息从后台传送过来。把所有的字段重新创建一遍。

用Form方法的话,需要自己写field字段。 用ModelForm的话,字段是自己从类里面提取过来的。

views.py

# Create your views here. 用Form方式实现
from django.shortcuts import render
from django import forms
from django.forms import fields
from app01 import models class UserInfoForm(forms.Form):
username = fields.CharField(max_length=32)
email=fields.EmailField()
user_type=fields.ChoiceField(
choices=models.UserType.objects.values_list('id','caption')
#forms下面是用field字段来进行验证的。forms下面没有foreignKey字段,只有choicefield,然后通过choices把另外一张表里面的内容都关联过来。在页面上把用户类型作为一个列表展示出来
) def index(request):
obj=UserInfoForm()
return render(request,'index.html',{'obj':obj})

index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% csrf_token %}
{{obj.as_p}}
</body>
</html>

运行效果:

3. 让user_type每一次都做更新操作,需要重构函数

说明见下图:

具体说明可以参考day23

   def __init__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['user_type'].choices=models.UserType.objects.values_list('id','caption')

4. 完善index.html函数,用form表单提交

{% csrf_token %} 密文显示
{{csrf_token }} 在前端页面生成字符串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/index/" method="POST">
{% csrf_token %}
{{obj.as_p}}
<input type="submit" value="提交"/>
</form>
</body>
</html>

页面效果:

5. 一点提交,数据就传到了后台。

obj.is_valid() #是否通过验证
obj.cleaned_data() #所有的正确信息
obj.errors() #所有的错误信息
models.UserInfo.objects.create(**obj.cleaned_data) #如果数据正确,则创建。是字典格式。
models.UserInfo.objects.filter(id=1).update(**obj.cleaned_data) #找到主键后自动更新 程序粘贴: views.py
# Create your views here. 用Form方式实现
from django.shortcuts import render
from django import forms
from django.forms import fields
from app01 import models class UserInfoForm(forms.Form):
username = fields.CharField(max_length=32)
email=fields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id') fields中没有foreignkey
user_type=fields.ChoiceField(
choices=models.UserType.objects.values_list('id','caption')
#在页面上把用户类型作为一个列表展示出来
) def __init__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['user_type'].choices=models.UserType.objects.values_list('id','caption') def index(request):
if request.method=='GET':
obj=UserInfoForm()
return render(request,'index.html',{'obj':obj})
elif request.method=='POST':
obj=UserInfoForm(request.POST)
obj.is_valid()
obj.cleaned_data()
obj.errors()
#models.UserInfo.objects.create(**obj.cleaned_data)
#models.UserInfo.objects.filter(id=1).update(**obj.cleaned_data)
return render(request, 'index.html', {'obj': obj})

index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/index/" method="POST">
{% csrf_token %}
{{obj.as_p}}
<input type="submit" value="提交"/>
</form>
</body>
</html>

models.py

from django.db import models

# Create your models here.
class UserType(models.Model):
caption=models.CharField(max_length=32) class UserInfo(models.Model):
username = models.CharField(verbose_name='用户名',max_length=32)
email=models.EmailField()
user_type=models.ForeignKey(to='UserType',to_field='id')

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
]

二,基于ModelForm来做。

1. class UserInfoModelForm(forms.ModelForm): 它也能帮我们自动生成HTML标签。

views.py
# 基于ModelForm方式来实现
from django.shortcuts import render
from app01 import models from django import forms
from django.forms import fields class UserInfoModelForm(forms.ModelForm):
class Meta:
model=models.UserInfo #指去哪个类里面去获取字段。
fields='__all__' #代指的是所有的field字段
#fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
#exclude=['username'] #把username列排除在外了。 def index(request):
if request.method=='GET':
obj=UserInfoModelForm()
return render(request,'index.html',{'obj':obj})
elif request.method=='POST':
obj=UserInfoModelForm(request.POST)
return render(request, 'index.html', {'obj': obj})

效果:


2.用Form时,字段是自己定义的。所以如果想显示中文的话,用label标签就可以了。

views.py
# 基于Form方式来实现
from django.shortcuts import render
from django import forms
from django.forms import fields
from app01 import models class UserInfoForm(forms.Form):
username = fields.CharField(max_length=32,label='用户名')
email=fields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id') fields中没有foreignkey
user_type=fields.ChoiceField(
choices=models.UserType.objects.values_list('id','caption')
#在页面上把用户类型作为一个列表展示出来
) def __init__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['user_type'].choices=models.UserType.objects.values_list('id','caption') def index(request):
if request.method=='GET':
obj=UserInfoForm()
return render(request,'index.html',{'obj':obj})
elif request.method=='POST':
obj=UserInfoForm(request.POST)
obj.is_valid()
obj.cleaned_data()
obj.errors()
#models.UserInfo.objects.create(**obj.cleaned_data)
#models.UserInfo.objects.filter(id=1).update(**obj.cleaned_data)
return render(request, 'index.html', {'obj': obj})
效果如下:
  用ModelForm时,前端页面中的字段是从相关联的类里面直接提取过来的,两者之间有耦合。自己不用再写了。



如果想要显示中文字段名的话,需要verbose_name='用户'
效果:
3.
model=models.UserInfo  #指去哪个类里面去获取字段,以后也可以做增删改查。
fields='__all__'       #代指的是所有的field字段 
fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
exclude=['username'] #把username列排除在外了。
效果展示1:

效果展示2:

4. 往UserType里面写一条数据备用:

用form方法的时候,验证功能的函数其实是写在BaseForm里的:UserInfoForm-->继承了Form--->继承了BaseForm(is_valid......)

点击提交的时候,modelform也可以做验证。UserInfoModelForm-->继承了ModelForm--->继承了BaseModelForm--->继承了BaseForm(is_valid......)

UserInfoModelForm下面也应该有obj.is_valid(), obj.cleaned_data, obj.errors 等方法。

ModelForm 做验证的时候与Form方法是一样的。

效果1:

效果2:

三,程序粘贴:

1. 基于form方法的views.py

# 基于Form方式来实现
from django.shortcuts import render
from django import forms
from django.forms import fields
from app01 import models class UserInfoForm(forms.Form):
username = fields.CharField(max_length=32,label='用户名')
email=fields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id') fields中没有foreignkey
user_type=fields.ChoiceField(
choices=models.UserType.objects.values_list('id','caption')
#在页面上把用户类型作为一个列表展示出来
) def __init__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['user_type'].choices=models.UserType.objects.values_list('id','caption') def index(request):
if request.method=='GET':
obj=UserInfoForm()
return render(request,'index.html',{'obj':obj})
elif request.method=='POST':
obj=UserInfoForm(request.POST)
obj.is_valid()
obj.cleaned_data()
obj.errors()
#models.UserInfo.objects.create(**obj.cleaned_data)
#models.UserInfo.objects.filter(id=1).update(**obj.cleaned_data)
return render(request, 'index.html', {'obj': obj})

2. 基于modelform方法的views.py

# 基于ModelForm方式来实现
from django.shortcuts import render,HttpResponse
from app01 import models from django import forms
from django.forms import fields def orm(request):
#models.UserType.objects.create(caption='Alex')
return HttpResponse('orm') class UserInfoModelForm(forms.ModelForm):
class Meta:
model=models.UserInfo #指去哪个类里面去获取字段,以后也可以做增删改查。
fields='__all__' #代指的是所有的field字段
#fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
#exclude=['username'] #把username列排除在外了。 class UserInfoForm(forms.Form):
username = fields.CharField(max_length=32)
email=fields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id')
user_type=fields.ChoiceField(
choices=models.UserType.objects.values_list('id','caption')
) def __init__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['user_type'].choices=models.UserType.objects.values_list('id','caption') def index(request):
if request.method=='GET':
obj=UserInfoModelForm()
return render(request,'index.html',{'obj':obj})
elif request.method=='POST':
obj=UserInfoModelForm(request.POST)
print(obj.is_valid())
print(obj.cleaned_data)
print(obj.errors)
return render(request, 'index.html', {'obj': obj})

3.index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/index/" method="POST">
{% csrf_token %}
{{obj.as_p}}
<input type="submit" value="提交"/>
</form>
</body>
</html>

4.models.py

from django.db import models

# Create your models here.
class UserType(models.Model):
caption=models.CharField(max_length=32) class UserInfo(models.Model):
username = models.CharField(verbose_name='用户',max_length=32)
email=models.EmailField()
user_type=models.ForeignKey(to='UserType',to_field='id')

5.urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
url(r'^orm/', views.orm),
]

四,Django之ModelForm组件

4.1 labels=None,                     # 提示信息

如果不想在Models原表中写verbose_name的话,可以在定义类的时候在ModelForm中写提示信息。

原来的效果:

 

现在也可以在modelform中写提示信息:labels是个字典格式,可以写多个。

4.2  help_texts=None,                 # 帮助提示信息

4.3 widgets=None,                    # 自定义插件以及样式。

4.4 错误信息 error_messages=None,             # 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS)

前端:

后台收集的错误信息:

错误信息的显示:

整体的错误信息也可以在这里用同样的方法定义,用的是__all__:{  }。 每一项的错误信息应该放到一个字典中。

4.5  field_classes=None               # 自定义字段类 (也可以自定义字段)

我想把邮箱格式的正则表达式改为url的格式进行验证。

# 基于ModelForm方式来实现
from django.shortcuts import render,HttpResponse
from app01 import models
from django import forms
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
def orm(request):
#models.UserType.objects.create(caption='Alex')
return HttpResponse('orm') class UserInfoModelForm(forms.ModelForm):
class Meta:
model=models.UserInfo #指去哪个类里面去获取字段,以后也可以做增删改查。
fields='__all__' #代指的是所有的field字段
#fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
#exclude=['username'] #把username列排除在外了。
#labels={'username':'请填入用户名'}
#help_texts={'username':'请把你的名字写对'}
#widgets={'username':Fwidgets.Textarea(attrs={'class':'c1'})}
error_messages={
'__all__':{},
'email':{
'required':'邮箱不能为空',
'invalid':'邮箱格式错误',
}
}
field_classes={
'email':Ffields.URLField #这里只能填类,不能加括号,加上括号就变成对象了。
}
class UserInfoForm(forms.Form):
username = Ffields.CharField(max_length=32)
email=Ffields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id')
user_type=Ffields.ChoiceField(
choices=models.UserType.objects.values_list('id','caption')
) def __init__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['user_type'].choices=models.UserType.objects.values_list('id','caption') def index(request):
if request.method=='GET':
obj=UserInfoModelForm()
return render(request,'index.html',{'obj':obj})
elif request.method=='POST':
obj=UserInfoModelForm(request.POST)
print(obj.is_valid())
print(obj.cleaned_data)
print(obj.errors.as_json())
return render(request, 'index.html', {'obj': obj})

效果:

4.6 把时间本地化的时候,需要在setting里面进行一下当前时区的设置。

            localized_fields=('birth_date',) # 本地化,如:根据不同时区显示数据
            如:
                数据库中
                    2016-12-27 04:10:57
                setting中的配置
                    TIME_ZONE = 'Asia/Shanghai'
                    USE_TZ = True
                则显示:
                    2016-12-27 12:10:57

4.7 切记 class Meta里面最容易犯的错误就是加逗号。千万不要加逗号

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={...})

五  第一个省事的地方是不用写字段了。第二个省事的地方是验证通过以后,用save方式就可以直接添加到数据库中了。

程序:

效果:

六,再新建一张表,做多对多的示例。

6.1 models.py

from django.db import models

class UserType(models.Model):
caption=models.CharField(max_length=32) class UserGroup(models.Model):
name=models.CharField(max_length=32) class UserInfo(models.Model):
#username = models.CharField(verbose_name='用户',max_length=32)
username = models.CharField(max_length=32)
email=models.EmailField()
user_type=models.ForeignKey(to='UserType',to_field='id')
u2g=models.ManyToManyField(UserGroup)

在usergroup表中新建几条数据

def orm(request):
models.UserGroup.objects.create(name='CEO')
models.UserGroup.objects.create(name='CFO')
models.UserGroup.objects.create(name='COO')
return HttpResponse('orm')

如下:

页面效果:发现多对多也显示出来了。

6.2 页面上新建然后保存数据

点击提交,就保存到数据库表中了。

多对多表中数据也增加了。

这个save的功能太强大了。

6.3 views.py

# 基于ModelForm方式来实现
from django.shortcuts import render,HttpResponse
from app01 import models
from django import forms
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
def orm(request):
#models.UserGroup.objects.create(name='CEO')
#models.UserGroup.objects.create(name='CFO')
#models.UserGroup.objects.create(name='COO')
return HttpResponse('orm') class UserInfoModelForm(forms.ModelForm):
class Meta:
model=models.UserInfo #指去哪个类里面去获取字段,以后也可以做增删改查。
fields='__all__' #代指的是所有的field字段
#fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
#exclude=['username'] #把username列排除在外了。
#labels={'username':'请填入用户名'}
#help_texts={'username':'请把你的名字写对'}
#widgets={'username':Fwidgets.Textarea(attrs={'class':'c1'})}
error_messages={
'__all__':{},
'email':{
'required':'邮箱不能为空',
'invalid':'邮箱格式错误',
}
}
#field_classes={'email':Ffields.URLField}
class UserInfoForm(forms.Form):
username = Ffields.CharField(max_length=32)
email=Ffields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id')
user_type=Ffields.ChoiceField(
choices=models.UserType.objects.values_list('id','caption')
) def __init__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['user_type'].choices=models.UserType.objects.values_list('id','caption') def index(request):
if request.method=='GET':
obj=UserInfoModelForm()
return render(request,'index.html',{'obj':obj})
elif request.method=='POST':
obj=UserInfoModelForm(request.POST)
if obj.is_valid():
obj.save()
#print(obj.is_valid())
#print(obj.cleaned_data)
#print(obj.errors.as_json())
return render(request, 'index.html', {'obj': obj})

七,obj.save()的拆分

查看源码可知,save包含两部分:

       instance.save(当前这个model对象,意思就是可以把当前表save一下)

       obj.save_m2m( )  save ManyToMany,其实就是把两步save拆开了。

7.1 测试 instance.save

测试效果:

7.2 小结:ModelForm可以帮我们生成HTML标签,也可以帮忙做验证,验证完了以后还可以直接保存在数据库中。

八,基于modelform实现添加数据的功能

models.UserInfo.objects.all().select_related('user_type','u2g') #跨表

8.1 添加user_list函数

# 基于ModelForm方式来实现
from django.shortcuts import render,HttpResponse
from app01 import models
from django import forms
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
def orm(request):
#models.UserGroup.objects.create(name='CEO')
#models.UserGroup.objects.create(name='CFO')
#models.UserGroup.objects.create(name='COO')
return HttpResponse('orm') class UserInfoModelForm(forms.ModelForm):
class Meta:
model=models.UserInfo #指去哪个类里面去获取字段,以后也可以做增删改查。
fields='__all__' #代指的是所有的field字段
#fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
#exclude=['username'] #把username列排除在外了。
#labels={'username':'请填入用户名'}
#help_texts={'username':'请把你的名字写对'}
#widgets={'username':Fwidgets.Textarea(attrs={'class':'c1'})}
error_messages={
'__all__':{},
'email':{
'required':'邮箱不能为空',
'invalid':'邮箱格式错误',
}
}
#field_classes={'email':Ffields.URLField}
class UserInfoForm(forms.Form):
username = Ffields.CharField(max_length=32)
email=Ffields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id')
user_type=Ffields.ChoiceField(
choices=models.UserType.objects.values_list('id','caption')
) def __init__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['user_type'].choices=models.UserType.objects.values_list('id','caption') def index(request):
if request.method=='GET':
obj=UserInfoModelForm()
return render(request,'index.html',{'obj':obj})
elif request.method=='POST':
obj=UserInfoModelForm(request.POST)
if obj.is_valid():
#obj.save()#这个save实现的时候,其实内部包含了2个步骤。可以拆开。
instance=obj.save(False) #什么也没干
instance.save() #只会保存当前这个类,而不会保存manytomany
obj.save_m2m() #保存manytomany
#print(obj.is_valid())
#print(obj.cleaned_data)
#print(obj.errors.as_json())
return render(request, 'index.html', {'obj': obj}) def user_list(request):
li=models.UserInfo.objects.all().select_related('user_type') #先把userinfo中的数据取出来
return render(request,'user_list.html',{'li':li})

user_list.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
{% for row in li %}
<li>{{row.username}}-{{row.user_type.caption}}</li>
{% endfor %}
</ul>
</body>
</html>

页面效果:

8.2  最终想要达到的效果:

程序粘贴:

models.py

from django.db import models

class UserType(models.Model):
caption=models.CharField(max_length=32) class UserGroup(models.Model):
name=models.CharField(max_length=32) class UserInfo(models.Model):
#username = models.CharField(verbose_name='用户',max_length=32)
username = models.CharField(max_length=32)
email=models.EmailField()
user_type=models.ForeignKey(to='UserType',to_field='id')
u2g=models.ManyToManyField(UserGroup)

views.py

# 基于ModelForm方式来实现
from django.shortcuts import render,HttpResponse
from app01 import models
from django import forms
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
def orm(request):
#models.UserGroup.objects.create(name='CEO')
#models.UserGroup.objects.create(name='CFO')
#models.UserGroup.objects.create(name='COO')
return HttpResponse('orm') class UserInfoModelForm(forms.ModelForm):
class Meta:
model=models.UserInfo #指去哪个类里面去获取字段,以后也可以做增删改查。
fields='__all__' #代指的是所有的field字段
#fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
#exclude=['username'] #把username列排除在外了。
#labels={'username':'请填入用户名'}
#help_texts={'username':'请把你的名字写对'}
#widgets={'username':Fwidgets.Textarea(attrs={'class':'c1'})}
error_messages={
'__all__':{},
'email':{
'required':'邮箱不能为空',
'invalid':'邮箱格式错误',
}
}
#field_classes={'email':Ffields.URLField}
class UserInfoForm(forms.Form):
username = Ffields.CharField(max_length=32)
email=Ffields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id')
user_type=Ffields.ChoiceField(
choices=models.UserType.objects.values_list('id','caption')
) def __init__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['user_type'].choices=models.UserType.objects.values_list('id','caption') def index(request):
if request.method=='GET':
obj=UserInfoModelForm()
return render(request,'index.html',{'obj':obj})
elif request.method=='POST':
obj=UserInfoModelForm(request.POST)
if obj.is_valid():
#obj.save()#这个save实现的时候,其实内部包含了2个步骤。可以拆开。
instance=obj.save(False) #什么也没干
instance.save() #只会保存当前这个类,而不会保存manytomany
obj.save_m2m() #保存manytomany
#print(obj.is_valid())
#print(obj.cleaned_data)
#print(obj.errors.as_json())
return render(request, 'index.html', {'obj': obj}) def user_list(request):
li=models.UserInfo.objects.all().select_related('user_type') #先把userinfo中的数据取出来
return render(request,'user_list.html',{'li':li}) def user_edit(request,nid):
#获取当前id对应的用户信息
#显示用户已经存在的数据
if request.method=='GET':
user_obj=models.UserInfo.objects.filter(id=nid).first() #获取对象
mf=UserInfoModelForm(instance=user_obj) #帮咱们生成标签
return render(request, 'user_edit.html',{'mf':mf,'nid':nid})
elif request.method=='POST':
user_obj = models.UserInfo.objects.filter(id=nid).first() #获取对象
mf = UserInfoModelForm(request.POST,instance=user_obj) #instance传进来表示更新,不加的话表示新建了一条数据。
if mf.is_valid():
mf.save()
else:
print(mf.errors.as_json())
return render(request, 'user_edit.html', {'mf': mf, 'nid': nid})

user_edit.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="POST" action="/edit-{{nid}}/">
{% csrf_token %}
{{mf.as_p}}
<input type="submit" value="提交"/>
</form> </body>
</html>

user_list.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
{% for row in li %}
<li>{{row.username}}-{{row.user_type.caption}}-<a href="/edit-{{row.id}}/">编辑</a></li>
{% endfor %}
</ul>
</body>
</html>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/index/" method="POST">
{% csrf_token %}
{{obj.as_p}}
<input type="submit" value="提交"/>
</form>
</body>
</html>

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
url(r'^user_list/', views.user_list),
url(r'^edit-(\d+)/', views.user_edit),
url(r'^orm/', views.orm),
]

8.3 补充

ModelForm:通过配置生成标签,用is_valid 进行验证,通过save进行保存。

ModelForm也可以自己定义钩子,与Form的用法一样。

在UserInfoModelForm中也可以定义新的字段。比如 username+password 可以从数据库中获取,但是像一个月内免登陆就不需要提交到数据库。像这个字段我们就可以在UserInfoModelForm中单独定义。

views.py

# 基于ModelForm方式来实现
from django.shortcuts import render,HttpResponse
from app01 import models
from django import forms
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
def orm(request):
#models.UserGroup.objects.create(name='CEO')
#models.UserGroup.objects.create(name='CFO')
#models.UserGroup.objects.create(name='COO')
return HttpResponse('orm') class UserInfoModelForm(forms.ModelForm):
#自定义额外的字段,比如是否要保存一个月内免登陆。
is_remember=Ffields.CharField(
widget=Fwidgets.CheckboxInput()
)
class Meta:
model=models.UserInfo #指去哪个类里面去获取字段,以后也可以做增删改查。
fields='__all__' #代指的是所有的field字段
#fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
#exclude=['username'] #把username列排除在外了。
#labels={'username':'请填入用户名'}
#help_texts={'username':'请把你的名字写对'}
#widgets={'username':Fwidgets.Textarea(attrs={'class':'c1'})}
error_messages={
'__all__':{},
'email':{
'required':'邮箱不能为空',
'invalid':'邮箱格式错误',
}
}
#field_classes={'email':Ffields.URLField}
def clean_username(self):
old=self.cleaned_data['username']
return old class UserInfoForm(forms.Form):
username = Ffields.CharField(max_length=32)
email=Ffields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id')
user_type=Ffields.ChoiceField(
choices=models.UserType.objects.values_list('id','caption')
) def __init__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['user_type'].choices=models.UserType.objects.values_list('id','caption') def index(request):
if request.method=='GET':
obj=UserInfoModelForm()
return render(request,'index.html',{'obj':obj})
elif request.method=='POST':
obj=UserInfoModelForm(request.POST)
if obj.is_valid():
#obj.save()#这个save实现的时候,其实内部包含了2个步骤。可以拆开。
instance=obj.save(False) #什么也没干
instance.save() #只会保存当前这个类,而不会保存manytomany
obj.save_m2m() #保存manytomany
#print(obj.is_valid())
#print(obj.cleaned_data)
#print(obj.errors.as_json())
return render(request, 'index.html', {'obj': obj}) def user_list(request):
li=models.UserInfo.objects.all().select_related('user_type') #先把userinfo中的数据取出来
return render(request,'user_list.html',{'li':li}) def user_edit(request,nid):
#获取当前id对应的用户信息
#显示用户已经存在的数据
if request.method=='GET':
user_obj=models.UserInfo.objects.filter(id=nid).first() #获取对象
mf=UserInfoModelForm(instance=user_obj) #帮咱们生成标签
return render(request, 'user_edit.html',{'mf':mf,'nid':nid})
elif request.method=='POST':
user_obj = models.UserInfo.objects.filter(id=nid).first() #获取对象
mf = UserInfoModelForm(request.POST,instance=user_obj) #instance传进来表示更新,不加的话表示新建了一条数据。
if mf.is_valid():
mf.save()
else:
print(mf.errors.as_json())
return render(request, 'user_edit.html', {'mf': mf, 'nid': nid})

效果:

九,总结

一,ModelForm => 可以做验证,可以做数据库操作。
Model+Form => 验证+数据库操作
-class LoginModelForm(XXXX):
利用model.A中的字段
1.生成html标签: class Meta:...
2.mf=xxxModelForm(instance=ModelObj)
3.额外的标签,
4.各种验证 is_valid()->各种钩子...
跟form的钩子一模一样,先进行每一个字段正则表达式验证,然后每一个字段的方法,然后进行clean,clean完了以后是post clean
5.mf.save()
############或者下面的###############
instance=mf.save(False)
instance.save()
mf.save_m2m()

Day24-ModelForm操作及验证的更多相关文章

  1. django(7)modelform操作及验证、ajax操作普通表单数据提交、文件上传、富文本框基本使用

    一.modelForm操作及验证 1.获取数据库数据,界面展示数据并且获取前端提交的数据,并动态显示select框中的数据 views.py from django.shortcuts import ...

  2. Django ModelForm操作及验证

    一.内容回顾 Model - 数据库操作 - 验证 class A(MOdel): user = email = pwd = Form - class LoginForm(Form): email = ...

  3. Django(九)上:ModelForm操作

    一.内容回顾 Model - 数据库操作 - 验证 class A(MOdel): user = email = pwd = Form - class LoginForm(Form): email = ...

  4. Python开发【Django】:ModelForm操作

    ModelForm 内容回顾: Model - 数据库操作 - 验证 class A(MOdel): user = email = pwd = Form class LoginForm(Form): ...

  5. Django使用普通表单、Form、以及modelForm操作数据库方式总结

    Django使用普通表单.Form.以及modelForm操作数据库主要应用于增删该查的情景下,流程通用如下,只是实现方式不一样: 进入填写表单页面: 在表单页面填写信息,并提交: 表单数据验证 验证 ...

  6. web框架-(七)Django补充---models进阶操作及modelform操作

    通过之前的课程我们可以对于Django的models进行简单的操作,今天了解下进阶操作和modelform: 1. Models进阶操作 1.1 字段操作 AutoField(Field) - int ...

  7. Django ModelForm表单验证

    ModelForm 在使用Model和Form时,都需要对字段进行定义并指定类型,通过ModelForm则可以省去From中字段的定义 应用场景:定制model admin 的时候可以使用.适用于小业 ...

  8. modelform的操作以及验证

    1,model的两个功能 1,数据库操作 2,验证只有一个clean方法作为钩子来操作,方法比较少 2,form(专门用来做验证的) 根据form里面写的类,类里面的字段,这些字段里有内置的的正则表达 ...

  9. ModelForm操作

    ModelForm a. class Meta: model, # 对应Model的 fields=None, # 字段 exclude=None, # 排除字段 labels=None, # 提示信 ...

随机推荐

  1. 通过 sass-resources-loader 全局注册 Sass/Less 变量

    使用webpack引入sass/less全局变量 sass或者less都提供变量设置,在需求切换主题的项目中使用less或者sass变量,只要修改变量值,编译后所有用到该变量的样式都会被修改为你想要的 ...

  2. RabbitMQ总结

    消息队列 三个业务场景:解耦.异步.削峰 带来问题 系统可用性降低:外部依赖越多,越容易挂掉. 系统复杂性提高:重复消费,消息丢失,消息传递的顺序性 一致性问题: 一.如何保证消息的可靠性传输(如何处 ...

  3. H5 55-行高

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. Oja’s rule

    目录 Oja's rule 背景 Hebbian learning 主要的一些理论 论文里面一些主要的假设 引理1 引理2 引理3 定理1 LEMMA 3(ALL) 引理 4 定理 2 定理 3(关于 ...

  5. PHP实用代码片段(四)

    1. 删除文件夹内容 function Delete($path) { if (is_dir($path) === true) { $files = array_diff(scandir($path) ...

  6. Unique Snowflakes UVA - 11572 (离散化+尺取法)

    Emily the entrepreneur has a cool business idea: packaging and selling snowflakes. She has devised a ...

  7. bootstrap简单使用

    Bootstrap (版本 v3.3.7)     官网教程: https://v3.bootcss.com/css/ row——行 row——列 push——推   pull——拉 col-md-o ...

  8. [转帖]BRD、MRD 和 PRD

    来源: https://www.zhihu.com/question/19655491 BRD 商业需求文档 Business Requirement Document MRD 市场需求文档 Mark ...

  9. JQ查找到带有某个字符,并起类名,然后替换这个某个字符

    <script> setTimeout("asdasd()",1000); //定时器是为了防止其他JS影响到它,可以不加 function asdasd() { $( ...

  10. 在页面中有overflow-y:auto属性的div,当出现滚动条,点击返回顶部按钮,内容回这个div最顶部

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...