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. Leetcode-645 Set Mismatch

    The set S originally contains numbers from 1 to n. But unfortunately, due to the data error, one of ...

  2. 用python实现一个回文数

    判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数. 示例 1: 输入: 121 输出: true 示例 2: 输入: -121 输出: false 解释: 从左向 ...

  3. 会议室预订系统(meeting room booking system)

    一.mrbs mrbs:(meeting room booking system) 二.效果   三.models from django.db import models # Create your ...

  4. Java 数据库操作

    目录 Java数据库组织架构 下载驱动包 连接数据库 连接数据库的三个步骤 连接数据库的高开销 Statement接口介绍 PreparedStatement类 使用PreparedStatement ...

  5. selenium模拟登陆淘宝

    from selenium import webdriver import time from selenium.webdriver.common.by import By from selenium ...

  6. #Leetcode# 989. Add to Array-Form of Integer

    https://leetcode.com/problems/add-to-array-form-of-integer/ For a non-negative integer X, the array- ...

  7. java 浅拷贝和深拷贝 对象克隆clone

    分一下几点讨论: 为什么要克隆? 如何实现克隆 浅克隆和深克隆 解决多层克隆问题 总结 一:为什么要克隆? 大家先思考一个问题,为什么需要克隆对象?直接new一个对象不行吗? 答案是:克隆的对象可能包 ...

  8. spark单击 搭建

    http://files.cnblogs.com/files/yxnyd/spark.zip

  9. golang操作mysql使用总结

    前言 Golang 提供了database/sql包用于对SQL数据库的访问, 作为操作数据库的入口对象sql.DB, 主要为我们提供了两个重要的功能: sql.DB 通过数据库驱动为我们提供管理底层 ...

  10. PhpStorm 配置链接远程虚拟机

    安装好了 PhpStorm 之后,打开项目文件夹,接着点击工具栏 Tools: 2.接着点击 tools>Deployment: 3.点击Configuration 开始配置    4.填好箭头 ...