Django保证表单的正确显示需要添加CSRF(防止网站跨站请求伪造而默认开启的一种保护方式),在<form></form>之间添加
{% csrf_token %}
在项目settings.py中 * ‘django.middleware.csrf.CsrfViewMiddleware’, * 引入,如果没有此中间件,手动添加。
文件上传
首次打开路径是GET请求,如果点击上传是POST请求,如果文件内容不为空,则上传文件,上传路径为主项目下的 media/uploads/,如果路径不存在则新建。open(os.path.join(path + myFile.name), ‘wb+’) 二进制读写打开对应文件,chunks()将文件分块读写。
def upload_file(request):
if request.method == "GET":
return render(request, 'app1/upload.html')
if request.method == "POST":
myFile = request.FILES.get("myfile", None)
if myFile:
path = 'media/uploads/'
if not os.path.exists(path):
os.makedirs(path)
dest = open(os.path.join(path + myFile.name), 'wb+')
for chunk in myFile.chunks():
dest.write(chunk)
dest.close()
return HttpResponse("上传完成")
else:
return HttpResponse("没有上传文件")
添加路由。 文件已经上传成功。
Form表单
如下新建一个form.py写入如下代码
from django import forms
class UserInfoForm(forms.Form):
'''用户状态'''
STATUS = ((None, '请选择'), (0, '正常'), (1, '无效'),)
username = forms.CharField(label="用户名称", min_length=6, widget=forms.widgets.TextInput(
attrs={'class': 'form-control', 'placeholder': '请输入用户名称'}
))
password = forms.CharField(label="密码", min_length=6, max_length=10, widget=forms.widgets.PasswordInput(
attrs={'class': 'password'}, render_value=True
))
age = forms.IntegerField(label="年龄", initial=1)
mobile = forms.IntegerField(label="手机号码")
status = forms.ChoiceField(label="用户状态", choices=STATUS)
createdate = forms.DateTimeField(label="创建时间", required=False)
表单字段
表单字段 | 说明 |
---|
CharField | 文本输入 | InterField/FloatField/DecimalField | 数值输入 | ChoiceField | 选择输入框 choices指定下拉列表 | FileField | 文件 | BooleanField | 复选框 | DateField/DateTimeField/TimeField/时间输入框,可以设置输入格式 input_format=[“%Y-%m-%d %H:%M”] | | EmailField | 邮件输入框 | URLField | 路劲输入框 | ModelChoiceField | 从数据库获取下拉列表 |
字段参数
字段 | 说明 |
---|
label | label标签 | label_suffix | Label标签统一后缀信息 | initial | 初始值 | help_text | 字段描述信息 | error_messages | 字段描述信息 | validators | 验证规则 | required | 是否必须 | disabled | 字段是否可编辑 | widget | 指定HTML样式 |
widget参数
参数 | 说明 |
---|
PasswordInput | 密码输入框 | HiddenInput | 隐藏元素 | Textarea | 文本域 | CheckboxInput | 复选框 | FileInput | 文件输入框 | RadioSelect | 单选按钮 | DateTimeInput | 时间输入框 | Select | 下拉列表 | SelectMuitiple | 多选框 |
配置视图和路径显示对应表单 app1下的views.py
def userinfo_form(request):
if request.method == "GET":
myForm = UserInfoForm()
return render(request, 'app1/userinfo.html', {'form_obj': myForm})
userinfo.html
<html>
<head></head>
<body>
<form action="" method="POST">
{% csrf_token %} {{ form_obj.as_p }}
<input type="submit" value="提交" />
</form>
</body>
</html>
- as_p 为表单提供<p>标签
- as_table 为表单提供<table>标签
- as_ui 为表单提供<ui>标签
以上用了as_p,故源代码显示p标签。
表单的验证
- is_valid() 验证表单数据是否合法
- cleaned_data 获取表单通过验证的数据
- errors 表单验证的错误信息
在form中添加如下代码
class UserInfoForm__Msg(forms.Form):
'''用户状态'''
STATUS = ((None, '请选择'), (0, '正常'), (1, '无效'),)
username = forms.CharField(label="用户名称", min_length=6, widget=forms.widgets.TextInput(
attrs={'class': 'form-control', 'placeholder': '请输入用户名称'}
), error_messages={
'required': '用户姓名不能为空', 'min_length': '长度不能少于6位', 'invalid': '不能含有特殊字符'
})
password = forms.CharField(label="密码", min_length=6, max_length=10, widget=forms.widgets.PasswordInput(
attrs={'class': 'password'}, render_value=True
), error_messages={
'required': '密码不能为空', 'min_length': '密码不能少于6位', 'max_length': '密码不能多余10位',
})
age = forms.IntegerField(label="年龄", initial=1, validators=[age_validate], error_messages={
'required': '年龄不能为空',
})
mobile = forms.IntegerField(label="手机号码", validators=[mobile_validate], error_messages={
'required': '手机号码不能为空',
})
status = forms.ChoiceField(label="用户状态", choices=STATUS, error_messages={
'required': '用户状态不能为空',
})
createdate = forms.DateTimeField(label="创建时间", required=False)
- required 为空的时候的错误信息
- invalid 格式验证错误的信息
- min_length和max_length 长度不在设定的范围的错误信息
添加视图
def userinfo_form_msg(request):
if request.method == "GET":
myForm = UserInfoForm__Msg()
return render(request, 'app1/userinfoform.html', {'form_obj': myForm})
else:
f = UserInfoForm__Msg(request.POST)
if f.is_valid():
print(f.cleaned_data['username'])
else:
errors = f.errors
print(errors)
return render(request, 'app1/userinfoform.html', {'form_obj': f, 'errors': errors})
return render(request, 'app1/userinfoform.html', {'form_obj': f})
模板文件
<form action="" method="POST" novalidate>
{% csrf_token %}
<p>
{{ form_obj.username.label }}:{{ form_obj.username }} {{ errors.username.0 }}
</p>
<p>{{ form_obj.password}}{{ errors.password.0 }}</p>
<p>{{ form_obj.status.label }}:{{ form_obj.status }} {{ errors.status.0 }}</p>
<p>{{ form_obj.age.label }}:{{ form_obj.age }} {{ errors.age.0 }}</p>
<p>{{ form_obj.mobile.label }}:{{ form_obj.mobile }} {{ errors.mobile.0 }}</p>
错误信息汇总: {{ errors }}
<input type="submit" value="提交" />
</form>
这里还添加了表单的自我格式验证,获取表单的数据
- f.clean() 获取全部数据
- f.clean_date[] 获取对应值的数据
- f.data 获取全部数据
表单模型文件上传例子
模板文件:upload_form.html
<form enctype="multipart/form-data" action="" method="post">
{% csrf_token %} {{ form_obj.as_p }}
<br />
<input type="submit" value="文件上传" />
<img src="media/uploads/{{ user.heading }}"
</form>
模型文件 在models.py中添加模型,这里没有主键默认会生成id的主键
class ImgFile(models.Model):
name = models.CharField(verbose_name='用户名称', max_length=300, default="")
heading = models.FileField(verbose_name='文件名', upload_to='media/uploads/')
def __str__(self):
return self.name
class Meta:
verbose_name = ' 用户头像信息'
db_table = 'user_img'
表单模型 form.py
class ImgFileForm(forms.Form):
name = forms.CharField()
heading = forms.FileField()
视图模型
如果上传了文件,将文件保存在对应的目录下,并返回文件的信息。
def ingfileform(request):
if request.method == "GET":
f = ImgFileForm()
return render(request, 'app1/upload_form.html', {'form_obj': f})
else:
f = ImgFileForm(request.POST, request.FILES)
if f.is_valid():
name = f.cleaned_data['name']
heading = f.cleaned_data['heading']
path = 'media/uploads/'
if not os.path.exists(path):
os.makedirs(path)
dest = open(os.path.join(path + heading.name), 'wb+')
for chunk in heading.chunks():
dest.write(chunk)
dest.close()
userimg = ImgFile()
userimg.name = name
userimg.heading = heading
userimg.save()
print('上传成功')
return render(request, 'app1/upload_form.html', {'form_obj': f, 'user': userimg})
else:
print(f.errors)
路由 re_path 配置了可以直接在浏览器访问对应的文件,
from django.urls import path, include, re_path
from django.views.static import serve
from mywed import settings
path('app1/userimg/', views.ingfileform),
re_path('media/uploads/(?P<path>.*)', serve,
{"document_root": settings.MEDIA_ROOT}),
settings.py 这里路径在项目文件中设置便于统一,在实际的应用中也应该多在公共文件中设置
MEDIA_URL = "media/uploads/"
MEDIA_ROOT = os.path.join(MEDIA_URL, "")
db中也登陆了对应的信息
模型表单
Django提供了ModelForm可以直接和模型关联,省略了Form表单中定义的操作。
AJAX
模板文件,为了能够正常的访问,必须添加csrfmiddlewaretoken或者在视图函数中注释@csrf_exempt,建议使用第一种方式
用户名:<input type="text" id="username"></input>
密码:<input type="password" id="password"></input>
{% csrf_token %}
<button id="submit">提交</button>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<script>
$("#submit").click(function(){
var csrf = $('input[name="csrfmiddlewaretoken"]').val();
$.ajax({
url: '/app1/ajax_login_data',
type: "post",
data: {
'username': $("#username").val(),
'password': $("#password").val(),
'csrfmiddlewaretoken': csrf
},
success: function(data){
console.log(data)
},
error: function(jqXHR, textStatus, err){
console.log(arguments);
}
});
});
</script>
视图文件
from django.views.decorators.csrf import csrf_exempt
def ajax_login(request):
return render(request, 'app1/ajax.html')
def ajax_login_data(request):
if request.method == "GET":
HttpResponse("内部自己的url")
username = request.POST.get('username')
password = request.POST.get('password')
print(username)
if username == 'admin' and password == '123456':
return JsonResponse({
'code': 1,
'msg': "登陆成功"
})
else:
print("222")
return JsonResponse({
'code': 0,
'msg': "登陆失败"
这里使用的是网上的jquery地址,也可在settings.py匹配如下,在网站根目录中创建static目录,放入jquery文件。
<script src=“/statics/jquery.min.js”></script>
STATIC_URL = '/statics/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "statics"),
]
|