Django——表单/admin站点详解

一.构建一张表单

视图文件:

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)

猜你喜欢

转载自blog.csdn.net/m0_74421072/article/details/135123048