大家在写表单的时候,会发现表单中的Field和模型中的Field基本上是一模一样的,而且表单中需要验证的时候,也就是我们模型中需要保存的数据,我们可以在表单中可以从from django import froms
下的froms.ModelForm
来进行绑定字段
from django import froms
forms.ModelFrom
__all__
: 代表着为验证全部字段 ,[]
:代表着只需要验证的字段forms.py
# @Time : 2020/7/21 0:18
# @Author : Small-J
from django import forms
from .models import Article
# forms.Form:代表着为导入表单
# forms.ModelForm:代表着导入模型的表单
class AddForms(forms.ModelForm):
"""
Meta : 该类是必须继承的,但是该字段是
model :对应的模型类
fields : 当为‘__all__就是验证全部字段’,当只想验证其中部分的字段的时候,需要使用[]包裹起来
"""
class Meta:
model = Article
# fields = '__all__'
# 当只想验证某几个字段的情况下可以使用[]的形式
# fields = ['title'] # 表示只验证title这个字段
exclude = ['title'] # exclude->排除的意思 表示不验证title这个字段
error_messages = {
'title': {
'required': '该字段是必须要填的',
'min_length': '最小长度为3',
'max_length': '最大长度为20'
},
'content': {
'required': '该字段是必须要填的',
'max_length': '最大长度为100'
},
'author': {
'required': '该字段是必须要填的',
'max_length': '最大长度为15'
}
}
views.py
from django.shortcuts import render
from django.views import View
# 导入表单验证
from .forms import AddForms
from django.http import HttpResponse
class AddArticle(View):
def get(self, request):
return render(request, 'add.html')
def post(self, request):
form = AddForms(request.POST)
# is_valid:代表验证通过的情况下
if form.is_valid():
return HttpResponse('success')
else:
print(form.errors.get_json_data())
return HttpResponse('fail')
add.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<form action="" method="post">
{# csrf_token:代表着解除csrf的一个保护 #}
{% csrf_token %}
<table>
<tr>
<td>标题:td>
<td><input type="text" name="title">td>
tr>
<tr>
<td>内容:td>
<td><input type="textarea" name="content">td>
tr>
<tr>
<td>作者:td>
<td><input type="text" name="author">td>
tr>
<td><input type="submit" value="提交">td>
table>
form>
body>
html>
models.py
from django.db import models
# 自定义验证器
from django.core import validators
class Article(models.Model):
# 当我们想设置最小长度的时候,但是在字段中没有的话,可以借助自定义验证器
# MinLengthValidator
title = models.CharField(max_length=20, validators=[validators.MinLengthValidator(limit_value=3)])
content = models.TextField(max_length=100, validators=[validators.MinLengthValidator(limit_value=3)])
author = models.CharField(max_length=15)
create_time = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'article'
app/urls.py
# @Time : 2020/7/21 0:11
# @Author : Small-J
from . import views
from django.urls import path
urlpatterns = [
path('', views.AddArticle.as_view())
]
ModelForm还有save方法,可以验证完成后直接调用save方法,就可以将这个数据库保存到数据库中
from django.shortcuts import render
from django.views import View
# 导入表单验证
from .forms import AddForms
from django.http import HttpResponse
class AddArticle(View):
def get(self, request):
return render(request, 'add.html')
def post(self, request):
form = AddForms(request.POST)
# is_valid:代表验证通过的情况下
if form.is_valid():
# 接收请求并保存到数据库
form.save() # 保存完之后在数据库中显示正常
return HttpResponse('success')
else:
print(form.errors.get_json_data())
return HttpResponse('fail')
这个方法必须要在clean没有问题后才能使用,如果在clean之前使用,会抛出异常。另外,我们在调用save方法的时候,如果传入一个commit=False
,那么只会生成这个模型的对象,而不会把这个对象真正的插入到数据库中。比如表单上验证的字段没有包含模型中所有的字段,这时候就可以先创建对象,再根据填充其他字段,把所有字段的只都补充完成后,再保存到数据库中。
views.py
class RegisterArticle(View):
def get(self, request):
return render(request, 'register.html')
def post(self, request):
form = RegisterForm(request.POST)
if form.is_valid():
user = form.save()
user.password = form.cleaned_data.get('pwd1')
user.save()
return HttpResponse('注册成功')
else:
print(form.errors.get_json_data())
return HttpResponse('fail')
forms.py
class RegisterForm(forms.ModelForm):
pwd1 = forms.CharField(min_length=3, max_length=10)
pwd2 = forms.CharField(min_length=3, max_length=10)
email = forms.EmailField()
# clean映射多字段
def clean(self):
changed_data = super().clean()
# print(changed_data) # 该返回的是一个字典形式
# changed_data:该返回是有变化的列表
pwd1 = changed_data.get('pwd1')
pwd2 = changed_data.get('pwd2')
if pwd1 != pwd2:
raise forms.ValidationError('请输入两次相同的密码')
class Meta:
# 使用的模型
model = Register
# 不验证密码
exclude = ['password']
error_messages = {
'telephone': {
'required': '请填写该字段',
},
'email': {
'required': '请填写该字段',
'invalid': '请输入正确的邮箱地址'
}
}
models.py
class Register(models.Model):
# 当不能设置最小长度的时候,可以使用自定义验证器来弄最小长度值
# 对应的字段里面都会对应的自定义验证器使用
username = models.CharField(max_length=10, validators=[validators.MinLengthValidator(limit_value=3)])
password = models.CharField(max_length=10, validators=[validators.MinLengthValidator(limit_value=3)])
telephone = models.CharField(max_length=11, validators=[validators.RegexValidator(r'1[3456789]\d{9}', message='请输入正确的手机号码')])
email = models.CharField(max_length=20, validators=[validators.EmailValidator(message='请输入正确的邮箱地址')])
class Meta:
db_table = 'register'
urls.py
from . import views
from django.urls import path
urlpatterns = [
path('register/', views.RegisterArticle.as_view())
]
register.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<form action="" method="post">
{% csrf_token %}
<table>
<td>
<tr>用户:tr>
<tr><input type="text" name="username">tr>
<br>
<tr>密码:tr>
<tr><input type="password" name="pwd1">tr>
<br>
<tr>再次输入密码:tr>
<tr><input type="password" name="pwd2">tr>
<br>
<tr>电话tr>
<tr><input type="text" name="telephone">tr>
<br>
<tr>邮箱tr>
<tr><input type="text" name="email">tr>
<br>
<tr><input type="submit" value="提交">tr>
td>
table>
form>
body>
html>
完成文件上传必须完成两部分,一部分是前端页面,另外一部分是后端页面
enctype="multipart/form-data"
,不然就不能上传文件。type="file"
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="images"><br>
<input type="submit" value="提交">
form>
body>
html>
后端的主要工作是接收文件。然后存储文件。接收文件的方式跟接收POST的方式是一样的,只不过是通过FILES来实现的
images = request.FILES.get('images')
该对应的是一个类,当我们想读取里面的内容出来的时候需要使用到read()
来读取class UploadFiles(View):
def get(self, request):
return render(request, 'upload.html')
def post(self, request):
# print(request.POST)
# 当选择文件上传的时候,应该选择的是FILES该文件
print(request.FILES) # ]}>
images = request.FILES.get('images')
print(images) # thumb-1920-771788.png 打印的是图片的名字
print(type(images)) # 但是这张图片是一个类
with open('demo.png', 'wb')as f:
f.write(images.read())
return HttpResponse('success')
在定义模型的时候,我们可以给存储文件字段指定为FileField
,这个Field
可以传递一个upload_to
c参数,用来指定上传上来的文件保存到哪里。当upload_to="file"
的时候,对应的参数会保存到file
这个文件夹下。注意:(当上传的文件的名字一样的话,对应的Django会帮助我们处理好图片,并不会覆盖)
models.py
class Article(models.Model):
# 当我们想设置最小长度的时候,但是在字段中没有的话,可以借助自定义验证器
# MinLengthValidator
title = models.CharField(max_length=20, validators=[validators.MinLengthValidator(limit_value=3)])
content = models.TextField(max_length=100, validators=[validators.MinLengthValidator(limit_value=3)])
author = models.CharField(max_length=15)
create_time = models.DateTimeField(auto_now_add=True)
# FileField 为文件上传功能
# upload_to:对应的files创建的文件夹目录
images = models.FileField(upload_to='files', null=True)
class Meta:
db_table = 'article'
views.py
class UploadFiles(View):
def get(self, request):
return render(request, 'upload.html')
def post(self, request):
# print(request.POST)
# 当选择文件上传的时候,应该选择的是FILES该文件
# print(request.FILES) # ]}>
# images = request.FILES.get('images')
# print(images) # thumb-1920-771788.png 打印的是图片的名字
# print(type(images)) # 但是这张图片是一个类
# with open('demo.png', 'wb')as f:
# f.write(images.read())
# ----------------------------------------------------------------
title = request.POST.get('title')
content = request.POST.get('content')
author = request.POST.get('author')
create_time = request.POST.get('create_time')
# 当接收文件的时候使用的是FILES这个文件方式来进行接收
images = request.FILES.get('images')
article = Article(title=title, content=content, author=author, images=images)
article.save()
return HttpResponse('success')
以上我们是使用了upload_to
来指定上传的文件的目录。我们也可以指定MEDIA_ROOT
,就不需要在FielField
中指定upload_to
,他会自动的将文件上传到MEDIA_ROOT
的目录下
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
在urls.py
中添加MEDIA_ROOT
目录下的访问路径
from django.urls import path
from front import views
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
path('', views.index),
] + static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
如果我们同时知道MEDIA_ROOT
和upload_to
,那么会将文件上传到MEDIA_ROOT
下的upload_to
文件夹中
upload_to
: %Y/%M/%D
class Article(models.Model):
# 当我们想设置最小长度的时候,但是在字段中没有的话,可以借助自定义验证器
# MinLengthValidator
title = models.CharField(max_length=20, validators=[validators.MinLengthValidator(limit_value=3)])
content = models.TextField(max_length=100, validators=[validators.MinLengthValidator(limit_value=3)])
author = models.CharField(max_length=15)
create_time = models.DateTimeField(auto_now_add=True)
# FileField 为文件上传功能
# upload_to:对应的files创建的文件夹目录
images = models.FileField(upload_to='%Y/%M/%D', null=True)
class Meta:
db_table = 'article'
如果想要限制上传的文件的拓展名,那么我们就需要用到表单来进行限制。我们可以使用普通的Form表单,也可以使用ModelForm
,直接从模型中读取字段。注意:(当进行文件上传的时候,通过表单验证的时候,需要在对应的参数上面加上request.FILES
),使用ImageField
必须要安装pip install Pillow
models.py
class Article(models.Model):
# 当我们想设置最小长度的时候,但是在字段中没有的话,可以借助自定义验证器
# MinLengthValidator
title = models.CharField(max_length=20, validators=[validators.MinLengthValidator(limit_value=3)])
content = models.TextField(max_length=100, validators=[validators.MinLengthValidator(limit_value=3)])
author = models.CharField(max_length=15)
create_time = models.DateTimeField(auto_now_add=True)
# FileField 为文件上传功能
# upload_to:对应的files创建的文件夹目录
# 自定义验证器对文件上传做相对应的数据验证
# FileExtensionValidator:对应的限制文件上传
# ImageField :默认只允许让你传相对应的图片文件 pip install Pillow
images = models.ImageField(upload_to='%Y/%m/%d', null=True, validators=[validators.FileExtensionValidator(['jpg', 'png'])])
class Meta:
db_table = 'article'
views.py
class UploadFiles(View):
def get(self, request):
return render(request, 'upload.html')
def post(self, request):
# print(request.POST)
# 当选择文件上传的时候,应该选择的是FILES该文件
# print(request.FILES) # ]}>
# images = request.FILES.get('images')
# print(images) # demo.png 打印的是图片的名字
# print(type(images)) # 但是这张图片是一个类
# with open('demo.png', 'wb')as f:
# f.write(images.read())
# ----------------------------------------------------------------
# 当对应需要验证表单和FIELD的时候,需要进行在对应的上面加上参数
form = UploadForm(request.POST, request.FILES)
if form.is_valid():
title = request.POST.get('title')
content = request.POST.get('content')
author = request.POST.get('author')
create_time = request.POST.get('create_time')
# 当接收文件的时候使用的是FILES这个文件方式来进行接收
images = request.FILES.get('images')
article = Article(title=title, content=content, author=author, images=images)
article.save()
return HttpResponse('success')
else:
print(form.errors.get_json_data())
return HttpResponse('fail')
forms.py
class UploadForm(forms.ModelForm):
class Meta:
# 表单验证的一个模型
model = Article
fields = '__all__'
error_messages = {
'images': {
'invalid_extension': '只能上传png和jpg文件格式'
}
}
upload.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<table>
<td>
<tr>标题:tr>
<tr><input type="text" name="title">tr>
<br>
<tr>内容:tr>
<tr><input type="text" name="content">tr>
<br>
<tr>作者:tr>
<tr><input type="text" name="author">tr>
<br>
<tr>文件上传:tr>
<tr><input type="file" name="images">tr>
<br>
<tr><input type="submit" value="提交">tr>
td>
table>
form>
body>
html>