一.构建一张表单
视图文件:
from django.shortcuts import render
# Create your views here.
def getdata(request):
data = ''
# number = 0
if 'data' in request.POST:
# 获取客户端提交data
data = request.POST['data']
number = data * 2
return render(request,'index.html',{"current_data":data,"number":number})
子路由:
from django.urls import path
from app import views
urlpatterns = [
path('getdata/',views.getdata),
]
模板文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 注意此时的getdata两边需要斜杆,同时它是指连接路由名叫getdata的路由 -->
<from action="/getdata/" method="POST">
{% csrf_token %}
<label for="data">请输入数据:</label>
<input id="data" type="text" name="data" value="{
{current_data}}">
<input type="submit" value="提交">
<p>计算得到的结果是:{
{number}}</p>
</from>
</body>
</html>
二.详解 django 表单的类
- 自定义的表单类dataForm继承了django.forms.Form类,它包含一个data字段。
- 字段data的类型为forms.CharField。 表单data字段会被渲染为一个<label>元素和一个<input>元素
- 表单字段的label参数指定在表单渲染生成的<label>元素中显示的字符串。
1.字段详解
常用表单字段类
- 绑定的表单拥有已提交的数据,因此可以用来判断数据是否合法,表单的
is_bound
属性用来判断是否具有绑定的数据 - label_suffix :label_suffix属性用于设置表单字段被渲染为HTML <label>元素时的文本内容的后缀,默认后缀为英文冒号“:”
- help_text参数用于设置字段的帮助信息,帮助信息被渲染为<span>元素
- error_messages用于设置自定义错误信息,它将覆盖默认的错误信息。
- error_messages的参数值为字典对象,其中的每个键值对对应一条校验错误信息
- disabled参数被设置为True时,不允许表单字段渲染成的HTML元素与用户交互
>>> class test(forms.Form):
... addr=forms.CharField(label='联系地址',label_suffix='*')
...
>>> print(test())
class test(forms.Form):
... addr=forms.CharField(label='联系地址',disabled=True)
...
>>> print(test())
#initial参数用于设置字段的初始值
>>> class test(forms.Form):
... name=forms.CharField(initial='someone')
...
>>> print(test(auto_id=False))
#也可在创建表单对象时提供初始值:
>>> d=test({'name':'Lining'},auto_id=False)
>>> print(d)
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField(widget=forms.Textarea)
sender = forms.EmailField()
cc_myself = forms.BooleanField(required=False)
class dataForm2(forms.Form):
data = forms.CharField(label='请输入数据:')
a = forms.BooleanField(label='a')
sex = forms.ChoiceField(label='sex')
date = forms.DateField(label='date')
def useDataForm2(request):
return render(request,'form2.html',{'form':dataForm2()})
form2视图:
2.控件
每个表单字段都有一个控件类,控件类对应html表单控件,例如:<input type="text">
每个表单字段都有一个默认控件,比如charfield默认控件是 TextInput
,如果要指定控件如下:
from django import forms
class RunApiForm(forms.Form):
query_params = forms.CharField(label='查询参数', required=False, widget=forms.Textarea(attrs={'rows': 6,'cols': 80,}))
from django import forms
class dataForm(forms.Form):
data = forms.CharField(label="请输入数据")
三.使用 django 表单模板
1 表单渲染选项
{ { form.as_table }}
将它们呈现为包含在标签中的表格单元格{ { form.as_p }}
将它们包裹在<p>
标签中{ { form.as_ul }}
将它们包裹在<li>
标签中
视图文件:
from django import forms
class dataForm(forms.Form):
data = forms.CharField(label="请输入数据")
def useDataForm1(request):
if request.method == 'POST':
form = dataForm(request.POST)
msg = '已完成数据提交'
else:
# 创建空表单
form = dataForm()
msg = '初始化表单'
return render(request,'data1.html',{'form':form,'msg':msg})
data1.html文件:
<form action="/your-name/" method="post">
{% csrf_token %}
{
{ form }}
<input type="submit" value="Submit">
</form>
<form action="/your-name/" method="post">
{% csrf_token %}
{
{ form.as_table }}
<input type="submit" value="Submit">
</form>
<form action="/your-name/" method="post">
{% csrf_token %}
{
{ form.as_p }}
<input type="submit" value="Submit">
</form>
<form action="/your-name/" method="post">
{% csrf_token %}
{
{ form.as_table }}
<input type="submit" value="Submit">
</form>
2 手动渲染字段(ing)
{
{fom.字段名.lable}}:字段的label文本,例如,“姓名”。
{
{fom.字段名.lable_tag}} :封装在HTML-label元素中的label文本,包含表单的label_suffix。
{
{form.字段名.value}}:字段值。
{
{form.字段名.help_text}} :字段的帮助文本。
{
{form.字段名.errors}} :字段未通过验证时的错误信息。
{
{fom.字段名.field}}; :表单字段的BoundField实例对象,用于访问字段属性。例如,{
{form.name.field.max_length}}。
视图文件:
from django import forms
class test(forms.Form):
name = forms.CharField(max_length=50,label='姓名')
age = forms.IntegerField(max_value=50,min_value=15,label='年龄',help_text='年龄大于15且小于50')
def useTest(request):
if request.method == 'POST':
form = test(request.POST)
else:
form = test()
return render(request,'tem.html',{"form":form})
tem.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="/diy/",method='POST'>
{% csrf_token %}
<div>
{
{form.name.label}}:{
{form.name}}
</div>
<div>
{
{form.age.label}}:{
{form.age}}{
{form.age.help_text}}
</div>
<input type="submit" value="提交">
</form>
</body>
</html>
3 遍历表单字段
视图文件:
# 遍历字段
class test1(forms.Form):
name = forms.CharField(max_length=50,label='姓名')
age = forms.IntegerField(max_value=50,min_value=15,label='年龄',help_text='年龄大于15且小于50')
def useTe(request):
if request.method == 'POST':
form = test1(request.POST)
else:
form = test1()
return render(request,'bianli.html',{"form":form})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h3>遍历表单字段</h3>
<form action="/diyfor/" method="POST">
{% csrf_token %}
{% for field in form %}
<p>
{
{ field.errors }}
//这个是标签中的固定值:例如:姓名,年龄
<b>{
{ field.label_tag }}</b>
{
{ field }}
{% if field.help_text %}
<I>{
{ field.help_text|safe }}</I>
{% endif %}
</p>
{% endfor %}
<input type="submit" value="提交">
</form>
</body>
</html>
四.表单集
视图文件:
from django.forms import formset_factory
def useform(request):
classTestForm = formset_factory(test,extra=2)
if request.method == 'POST':
formset = classTestForm(request.POST)
else:
formset = classTestForm()
return render(request,'temform.html',{'formset':formset})
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="/formset/" method="POST">
{% csrf_token %}
<table>
{
{ formset }}
</table>
<input type="submit" value="提交">
</form>
</body>
</html>
五.模型表单
注意:需要连接数据库
model.py
from django.db import models
# Create your models here.
class person(models.Model):
name = models.CharField(max_length=8)
age = models.SmallIntegerField()
视图文件:
from .models import person
from django.forms import ModelForm
class personForm(ModelForm):
class Meta:
model = person
fields = '__all__'
def usePersonForm(request):
# 在提交表单时采用post
if request.method == 'POST':
# 初始化表单
mform = personForm(request.POST)
# 在表单通过验证时执行数据处理
if mform.is_valid():
# 用表单数据查询
ps = person.objects.filter(name=request.POST['name'])
if ps.count() == 0:
mform.save()
msg = '数据已保存'
else:
msg = '数据库已存在相同姓名的数据,请勿重复提交'
else:
msg = '表单数据有错'
else:
# 创建空白表单
mform = personForm()
msg = '请输入数据添加新纪录'
return render(request,'moxing.html',{'mform':mform,'msg':msg})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="/mform/" method="POST">
{% csrf_token %}
<table>
{
{mform}}
</table>
<input type="submit" value="提交">
</form>
<hr/>
{
{msg}}
</body>
</html>
视图文件:
class personFormDIY(ModelForm):
age = forms.CharField(validators=[validata_age],label='年龄',\
widget = forms.NumberInput(),\
help_text='年龄为[20,50]以内的整数')
class Meta:
model = person
fields = ['name','age']
labels = {'name':'姓名',}
help_texts = {'name':'姓名为中文英文字符串',}
widgets = {'name':forms.Textarea(attrs={'cols':30,'rows':2}),}
def usePersonFormDIY(request):
# 在提交表单时采用post
if request.method == 'POST':
# 初始化表单
mform = personForm(request.POST)
# 在表单通过验证时执行数据处理
if mform.is_valid():
# 用表单数据查询
ps = person.objects.filter(name=request.POST['name'])
if ps.count() == 0:
mform.save()
msg = '数据已保存'
else:
msg = '数据库已存在相同姓名的数据,请勿重复提交'
else:
msg = '表单数据有错'
else:
# 创建空白表单
mform = personForm()
msg = '请输入数据添加新纪录'
return render(request,'moxing.html',{'mform':mform,'msg':msg})
六.admin站点
1.创建超级管理员
注意:需要迁移数据库才能打开页面
python manage.py createsuperuser
可以使用文件形式更改数据库:
from django.contrib.auth.models import User
user = User.objects.create(username='admin')
user.set_password('123456')
user.is_superuser=True
user.save()
2.更改admin站点语言
更改为:
还可以更改下面的方法,来更改语言(两种方法都可以)
添加这一行:
3.模型管理
注意:该操作需要执行数据库的迁移
admin.py:
from django.contrib import admin
# Register your models here.
from .models import bookinfo
#网站的url标题
admin.site.site_title='在线图书馆后台管理系统'
#网站标题
admin.site.site_header='在线管理网站'
#注册模型
admin.site.register(bookinfo)
models.py:
from django.db import models
# Create your models here.
class bookinfo(models.Model):
name = models.CharField(max_length=20,verbose_name='书籍名')
author = models.CharField(max_length=20,verbose_name='书籍作者')
price = models.IntegerField(verbose_name='书籍定价')
class Meta:
verbose_name = '书籍信息'
verbose_name_plural = '书籍信息'
更改应用名称:
__init__.py:
default_app_config = 'app.apps.AppConfig'
apps.py:
from django.apps import AppConfig
class AppConfig(AppConfig):
name = 'app'
verbose_name = '图书信息系统'
4.列表页选项
admin.py:
from django.contrib import admin
# Register your models here.
from .models import bookinfo
admin.site.site_title='在线图书馆后台管理系统'
admin.site.site_header='在线管理网站'
# admin.site.register(bookinfo)
@admin.register(bookinfo)
class Bookadmin(admin.ModelAdmin):
# 需要展示的信息
list_display = ('id','name','author','price')
# 点击之后可以以链接的形式展示
list_display_links = ('id','name')
# 右边显示的过滤器
list_filter = ('name',)
# 显示搜索的信息,搜索框
search_fields = ('author','name')
# 排序
ordering = ('price',)
# 类似于分页,需要显示的条数
list_per_page = 1
# 表示其他的可以更改,但是名字不可以更改
readonly_fields = ('name',)
# 表示可以更改价格
list_editable = ('price',)
5.自定义下载编辑
admin.py
from django.contrib import admin
# Register your models here.
from .models import bookinfo
admin.site.site_title='在线图书馆后台管理系统'
admin.site.site_header='在线管理网站'
# admin.site.register(bookinfo)
from django.http import HttpResponse
from django.utils.encoding import escape_uri_path
from openpyxl import Workbook
@admin.register(bookinfo)
class Bookadmin(admin.ModelAdmin):
def download_excel(self,request,queryset):
file_name = '书籍信息.xlsx'
# 用于定义文件名,格式为:app名.模型名
meta = self.model._meta
# 模型所有字段名
field_names = [field.name for field in meta.fields]
# 定义响应数据格式
response = HttpResponse(content_type='application/msexcel')
response['Content-Disposition'] = "attachment;filename*=utf-8'{}".format(escape_uri_path(file_name))
# 新建workbook
wb = Workbook()
# 使用当前活动的sheet表
ws= wb.active
ws.append(['ID','书籍名称','作者','书籍定价'])
for obj in queryset:
for field in field_names:
data = [getattr(obj,field) for field in field_names]
ws.append(data)
wb.save(response)
return response
download_excel.short_description = '下载书籍信息'
# 需要展示的信息
list_display = ('id','name','author','price')
# 点击之后可以以链接的形式展示
list_display_links = ('id','name')
# 右边显示的过滤器
list_filter = ('name',)
# 显示搜索的信息,搜索框
search_fields = ('author','name')
# 排序
ordering = ('price',)
# 类似于分页,需要显示的条数
list_per_page = 1
# 表示其他的可以更改,但是名字不可以更改
readonly_fields = ('name',)
# 表示可以更改价格
list_editable = ('price',)
actions = (download_excel,)
actions_on_top = False
actions_on_bottom = True
6.编辑页选项
admin.py
# 控制编辑页面需要显示的字段
fields = (('name','author'),('price',))
# 对编辑字段进行分组
fieldsets = (('书籍基本信息',{'fields':['name','author']}),
('书籍价格信息',{'fields':['price']}))
# 表示只读字段
readonly_fields = ('name',)
7.优化页面
pip install django-simpleui
pip list
STATIC_DIRS = [os.path.join(BASE_DIR,'static')]
STATIC_ROOT = os.path.join(BASE_DIR,'/static/')
python manage.py collectstatic
//将admin文件复制到项目文件static目录下
python manage.py runserver
8.用户认证
创建普通用户:
from django.contrib.auth.models import User
user = User.objects.create(username='testuser')
user.set_password('123456')
user.save()
创建超级用户:
user = User.objects.create_superuser('admin3', '[email protected]', '123456')
修改对象:
user = User.objects.get(username='testuser')
user.email
user.email = '[email protected]'
user.save()
user.email
#'[email protected]'
删除对象:
user = User.objects.get(username='test')
user.delete()
#(4, {'admin.LogEntry': 0, 'auth.User_groups': 1, 'auth.User_user_permissions': 2, 'auth.User': 1})
验证用户:
from django.contrib.auth import authenticate
user = authenticate(username='testuser',password='123456')
print(user)
#testuser
user = authenticate(username='testuser',password='456')
print(user)
#None
设置权限:
from django.contrib.auth.models import Permission
from django.contrib.auth import get_user_model
User = get_user_model()
admin_permissions = Permission.objects.filter(codename__endswith='permission')
user = User.objects.get(username='testuser')
user.user_permissions.set(admin_permissions)
for p in user.user_permission.all():
print(p.codename.p.name)
from app.models import bookinfo
from django.contrib.contenttypes.models import ContentType
content_type_id = ContentType.objects.get_for_model(bookinfo)
p = Permission.objects.create(codename='can_analyse_person',name='能分析person数据',con
tent_type=content_type_id)
user.user_permissions.add(p)
查看可视化页面:
from django.contrib.auth.models import Permission
from django.contrib.auth.models import User
p = Permission.objects.get(codename='view_permission')
user = User.objects.get(username='testuser')
p.user_set.add(user)
p.user_set.all()
#<QuerySet [<User: testuser>]>
from django.contrib.auth.models import Group
g = Group.objects.get(id = 1)
g.user_set.add(user)