03-Day02-ModelForm生成注册字段

一、Django ModelForm

  • 本章使用 ModelForm 主要实现一下两种功能:
    • 自动生成表单 HTML
    • 实现表单验证功能

1.1、创建用于实现注册的Model

(Bug_manager) daizhe@daizhedeMacBook-Pro Bug_manager % cat users_app/models.py 
from django.db import models
# Create your models here.

class UserInfo(models.Model):
    """
    CharField : 字符串类型字段
    verbose_name : 字段注释
    max_length : 字段长度
    Django ORM 中也提供了一个 EmailField 但是本质上 还是 CharField,区别在于 template展示效果
    """
    username = models.CharField(verbose_name='用户名', max_length=32)
    email = models.EmailField(verbose_name='邮箱', max_length=32)
    models_phone = models.CharField(verbose_name='手机号', max_length=32)
    password = models.CharField(verbose_name='密码', max_length=32)
  • 生成数据库迁移脚本
(Bug_manager) daizhe@daizhedeMacBook-Pro Bug_manager % python3 manage.py makemigrations
Migrations for 'users_app':
  users_app/migrations/0001_initial.py
    - Create model UserInfo
  • 迁移表结构
(Bug_manager) daizhe@daizhedeMacBook-Pro Bug_manager % python3 manage.py migrate       
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, users_app
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK
  Applying users_app.0001_initial... OK

1.2、通过ModelForm实现注册展示示例

  • urls用于注册示例的路由
(Bug_manager) daizhe@daizhedeMacBook-Pro Bug_manager % cat Bug_manager/urls.py 
"""Bug_manager URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from users_app import views

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^send/sms/', views.send_sms),
    # 注册示例
    url(r'^register/', views.register),
]
  • views视图,基于ModelForm 定于展示的元数据属性
(Bug_manager) daizhe@daizhedeMacBook-Pro Bug_manager % cat users_app/views.py
from django import forms
from users_app import models
class RegisterModelForm(forms.ModelForm):
    #  model 定义元数据
    class Meta:
        # 对应的Model类
        model = models.UserInfo
        # Model类中哪些字段可以展示,__all__ 表示所有
        fields = '__all__'


def register(request):
    form = RegisterModelForm()
    return render(request, 'register.html', {'form': form})
  • template模板,展示Module中字段;
  • 开发规范 :
    • 将template目录创建在每个APP目录中
    • 模板的查找顺序 :
      • 首先,查找 项目根目录下 template目录下查找模板,如 Bug_manager/template
      • 其次,通过Settings配置文件中的 INSTALLED_APPS 应用注册顺序,去每一个 APP 里面的 template 目录进行模板查找
$ mkdir users_app/templates
$ touch users_app/templates/register.html
$ cat users_app/templates/register.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>注册</h1>
    {% for field in form %}
        <p> {{ field.label }} : {{ field }} </p>
    {% endfor %}
</body>
</html>

// field.label 去读 ModelForm 中的每一个字段的 labels,但是我们上面 views 中的 ModelForm 没有可渲染的label,所以就会去 根据UserInfo 即ORM 中的 Models 类帮助我们自动生成些 ModelForm 前端渲染的字段
// template字段渲染的查找顺序 :
	// template --> ModuleForm --> ORM(UserInfo)
// 所以目前场景,template中field.label渲染的就是UserInfo中的verbose_name属性
  • 启动项目访问URL

image

  • 补充 :
    • 字段类型、长度限制,如,我们在Models中定义的邮箱为 EmailField 字段类型,所以前端填入的字段也会对应生成一个 "正则表达式",所以仅有填入的格式于Form表单一致才可以写入数据库;

  • ModulesForm重写 models 字段类型,比如下面示例 :
    • 使用 ModelForm 重写 models 中的手机号字段类型;
    • 使用 ModelForm 重写 models 中的password字段属性;
(Bug_manager) daizhe@daizhedeMacBook-Pro Bug_manager % cat users_app/views.py
from django import forms
from users_app import models
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
class RegisterModelForm(forms.ModelForm):

    # 重写models字段类型
    # models_phone = forms.RegexField(regex=r'^\+?1?\d{9,15}$',     # 正则表达式方式一
    #                                 label='国际标准手机号')
                                                                    # 正则表达式方式二
    models_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'),])
    password = forms.CharField(label='密码',widget=forms.PasswordInput())        # password 展示时会根据 forms.PasswordInput() 插件进行展示


    #  model 定义元数据
    class Meta:
        # 对应的Model类
        model = models.UserInfo
        # Model类中哪些字段可以展示,__all__ 表示所有
        fields = '__all__'


def register(request):
    form = RegisterModelForm()
    return render(request, 'register.html', {'form': form})
  • 再次启动项目查看页面

image

  • 补充 :
    • ORM 中的 models 会根据verbose_name注释信息属性生成字段,但是我们觉得models中的字段属性不能满足我们的需求,也可以在ModelForm中进行重写;

  • ModuleForm也可以生成一个 models 中没有的字段
  • 比如下例子 :
    • 1、生成一个 确认密码 的字段,但是实际上并非存在数据库中,仅仅用于页面展示及密码校验;
    • 2、生成一个 验证码 的字段,但是实际上并非存在数据库中,仅仅用于页面展示及密码校验;
  • ModuleForm本身会有自动检测功能 :
    • 如果我们定义在 ModelForm 中的字段与 models 中的字段名称重复,则视为 ModuleForm字段覆盖 models 字段属性;
    • 如果我们定义在 ModelForm 中的字段与 models 中的字段不重复,则视为新增字段(但是数据库中并非有此新增字段,仅在 ModuleForm 中存在使用);
(Bug_manager) daizhe@daizhedeMacBook-Pro Bug_manager % cat users_app/views.py
...
...
from django import forms
from users_app import models
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
class RegisterModelForm(forms.ModelForm):

    # 重写models字段类型
    # models_phone = forms.RegexField(regex=r'^\+?1?\d{9,15}$',     # 正则表达式方式一
    #                                 label='国际标准手机号')
                                                                    # 正则表达式方式二
    models_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'),])
    password = forms.CharField(label='密码',widget=forms.PasswordInput())        # password 展示时会根据 forms.PasswordInput() 插件进行展示
    # 重复密码
    confirm_password = forms.CharField(label='重复密码', widget=forms.PasswordInput())
    # 验证码
    code = forms.CharField(label='验证码')
    #  model 定义元数据
    class Meta:
        # 对应的Model类
        model = models.UserInfo
        # Model类中哪些字段可以展示,__all__ 表示所有
        fields = '__all__'


def register(request):
    form = RegisterModelForm()
    return render(request, 'register.html', {'form': form})
  • 再次启动项目查看页面

image

1.3、ModelForm美化页面

1.3.1、bootstrap cdn引入

$ cat users_app/templates/register.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.4.0/css/bootstrap.min.css">
    <style>
        .account{
            width: 600px;
            margin: 0 auto;
        }
    </style>

</head>
<body>

    <div class="account">
        <h1>注册</h1>
        {% for field in form %}
            <p> {{ field.label }} : {{ field }} </p>
        {% endfor %}
    </div>

</body>
</html>

image

1.3.2、引入 bootstrap 样式,ModelForm增加前端属性

$ cat users_app/templates/register.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.4.0/css/bootstrap.min.css">
    <style>
        .account{
            width: 400px;
            margin: 0 auto;
        }
    </style>

</head>
<body>

    <div class="account">
        <h1>注册</h1>
        <form>
            {% for field in form %}
          <div class="form-group">
            <label for="{{ field.id_for_label }}">{{ field.label }}</label>
            <input type="email" class="form-control" id="exampleInputEmail1" placeholder="Email">
            {{ field }}
          </div>
            {% endfor %}
          <button type="submit" class="btn btn-default">注册</button>
        </form>
    </div>

</body>
</html>

image

  • 调整项说明 :
    • 如果想要实现我们的 field 字段也可以展示成上图中Email字段样式,只需要在字段中增加 class="form-control"样式属性,所以需要后端ModelForm在生成标签的时候,将此class属性自动携带;
$ cat users_app/templates/register.html
...
...
<body>
    <div class="account">
        <h1>注册</h1>
        <form>
            {% for field in form %}
          <div class="form-group">
            <label for="{{ field.id_for_label }}">{{ field.label }}</label>
{#            <input type="email" class="form-control" id="exampleInputEmail1" placeholder="Email">#}
            {{ field }}
          </div>
            {% endfor %}
          <button type="submit" class="btn btn-default">注册</button>
        </form>
    </div>
</body>
...
...
(Bug_manager) daizhe@daizhedeMacBook-Pro Bug_manager % cat users_app/views.py
...
...
from django import forms
from users_app import models
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
class RegisterModelForm(forms.ModelForm):

    # 重写models字段类型
    # models_phone = forms.RegexField(regex=r'^\+?1?\d{9,15}$',     # 正则表达式方式一
    #                                 label='国际标准手机号')
    # 密码
    #   attrs 表示在生成此标签时附加哪些属性 :class 表示生成输入框样式,palceholer 表示输入框提示信息
                                                                     # 正则表达式方式二
    models_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'),])
    password = forms.CharField(label='密码',widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': "请输入密码"}))        # password 展示时会根据 forms.PasswordInput() 插件进行展示
    # 重复密码
    confirm_password = forms.CharField(label='重复密码', widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': "请重复输入密码"}))
    # 验证码
    code = forms.CharField(label='验证码', widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': "请输入验证码"}))
    #  model 定义元数据
    class Meta:
        # 对应的Model类
        model = models.UserInfo
        # Model类中哪些字段可以展示,__all__ 表示所有
        fields = '__all__'


def register(request):
    form = RegisterModelForm()
    return render(request, 'register.html', {'form': form})

image

  • 上面是通过ModelForm对字段增加额外的属性,实现了前端的展示效果;
  • 但是发现每个字段都需要增加额外的属性,固然很麻烦,所以可以在ModelForm重写__init__初始化方法增加属性;
$ cat users_app/templates/register.html
...
...
<body>
    <div class="account">
        <h1>注册</h1>
        <form>
            {% for field in form %}
          <div class="form-group">
            <label for="{{ field.id_for_label }}">{{ field.label }}</label>
{#            <input type="email" class="form-control" id="exampleInputEmail1" placeholder="Email">#}
            {{ field }}
          </div>
            {% endfor %}
          <button type="submit" class="btn btn-default">注册</button>
        </form>
    </div>
</body>
...
...
(Bug_manager) daizhe@daizhedeMacBook-Pro Bug_manager % cat users_app/views.py
...
...
from django import forms
from users_app import models
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
class RegisterModelForm(forms.ModelForm):
    models_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'),])
    password = forms.CharField(label='密码',widget=forms.PasswordInput())
    confirm_password = forms.CharField(label='重复密码', widget=forms.PasswordInput())
    code = forms.CharField(label='验证码', widget=forms.TextInput())

    #  model 定义元数据
    class Meta:
        # 对应的Model类
        model = models.UserInfo
        # Model类中哪些字段可以展示,__all__ 表示所有
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        """
        重写RegisterModelForm 的 初始化方法
            name  表示字段名称
            field 表示forms.CharField对象
                code = forms.CharField(label='验证码', widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': "请输入验证码"}))
        """
        super(RegisterModelForm, self).__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs['class'] = 'form-control'
            field.widget.attrs['placeholder'] = "请输入{}".format(field.label)

def register(request):
    form = RegisterModelForm()
    return render(request, 'register.html', {'form': form})

image

1.4、页面美化和调整

  • 美化验证码按钮
$ cat users_app/templates/register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
    <style>
        .account {
            width: 400px;
            margin: 0 auto;
        }
    </style>
</head>
<body>
<div class="account">
    <h1 style="text-align: center;">注册</h1>
    <form>
        {% for field in form %}
            {% if field.name == 'code' %}
                <div class="form-group">
                    <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                    <div class="clearfix">
                        <div class="col-md-6" style="padding-left: 0;">{{ field }}</div>
                        <div class="col-md-6"><input type="button" class="btn btn-default" value="点击获取验证码"></div>
                    </div>

                </div>
            {% else %}
                <div class="form-group">
                    <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                    {{ field }}
                </div>
            {% endif %}
        {% endfor %}

        <button type="submit" class="btn btn-primary">注 册</button>
    </form>
</div>
</body>
</html>

image

  • 调整页面展示顺序,默认的展示效果是按照 ModelForm 中展示的,展示顺序为 :models中的字段,然后再展示 ModelForm中新增的字段;
(Bug_manager) daizhe@daizhedeMacBook-Pro Bug_manager % cat users_app/views.py
...
...
from django import forms
from users_app import models
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
class RegisterModelForm(forms.ModelForm):
    models_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'),])
    password = forms.CharField(label='密码',widget=forms.PasswordInput())
    confirm_password = forms.CharField(label='重复密码', widget=forms.PasswordInput())
    code = forms.CharField(label='验证码', widget=forms.TextInput())

    #  model 定义元数据
    class Meta:
        # 对应的Model类
        model = models.UserInfo
        # Model类中哪些字段可以展示,__all__ 表示所有
        # fields = '__all__' 也表示默认的展示顺序,可以手动指定展示顺序
        fields = ['username', 'email', 'password', 'confirm_password', 'models_phone', 'code']

    def __init__(self, *args, **kwargs):
        """
        重写RegisterModelForm 的 初始化方法
            name  表示字段名称
            field 表示forms.CharField对象
                code = forms.CharField(label='验证码', widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': "请输入验证码"}))
        """
        super(RegisterModelForm, self).__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs['class'] = 'form-control'
            field.widget.attrs['placeholder'] = "请输入{}".format(field.label)



def register(request):
    form = RegisterModelForm()
    return render(request, 'register.html', {'form': form})

image

二、知识点补充

2.1、Django Form所有内置字段

Field
    required=True,               是否允许为空
    widget=None,                 HTML插件
    label=None,                  用于生成Label标签或显示内容
    initial=None,                初始值
    help_text='',                帮助信息(在标签旁边显示)
    error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}
    validators=[],               自定义验证规则
    localize=False,              是否支持本地化
    disabled=False,              是否可以编辑
    label_suffix=None            Label内容后缀
 
 
CharField(Field)
    max_length=None,             最大长度
    min_length=None,             最小长度
    strip=True                   是否移除用户输入空白
 
IntegerField(Field)
    max_value=None,              最大值
    min_value=None,              最小值
 
FloatField(IntegerField)
    ...
 
DecimalField(IntegerField)
    max_value=None,              最大值
    min_value=None,              最小值
    max_digits=None,             总长度
    decimal_places=None,         小数位长度
 
BaseTemporalField(Field)
    input_formats=None          时间格式化   
 
DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 
DurationField(Field)            时间间隔:%d %H:%M:%S.%f
    ...
 
RegexField(CharField)
    regex,                      自定制正则表达式
    max_length=None,            最大长度
    min_length=None,            最小长度
    error_message=None,         忽略,错误信息使用 error_messages={'invalid': '...'}
 
EmailField(CharField)      
    ...
 
FileField(Field)
    allow_empty_file=False     是否允许空文件
 
ImageField(FileField)      
    ...
    注:需要PIL模块,pip3 install Pillow
    以上两个字典使用时,需要注意两点:
        - form表单中 enctype="multipart/form-data"
        - view函数中 obj = MyForm(request.POST, request.FILES)
 
URLField(Field)
    ...
 
 
BooleanField(Field)  
    ...
 
NullBooleanField(BooleanField)
    ...
 
ChoiceField(Field)
    ...
    choices=(),                选项,如:choices = ((0,'上海'),(1,'北京'),)
    required=True,             是否必填
    widget=None,               插件,默认select插件
    label=None,                Label内容
    initial=None,              初始值
    help_text='',              帮助提示
 
 
ModelChoiceField(ChoiceField)
    ...                        django.forms.models.ModelChoiceField
    queryset,                  # 查询数据库中的数据
    empty_label="---------",   # 默认空显示内容
    to_field_name=None,        # HTML中value的值对应的字段
    limit_choices_to=None      # ModelForm中对queryset二次筛选
     
ModelMultipleChoiceField(ModelChoiceField)
    ...                        django.forms.models.ModelMultipleChoiceField
 
 
     
TypedChoiceField(ChoiceField)
    coerce = lambda val: val   对选中的值进行一次转换
    empty_value= ''            空值的默认值
 
MultipleChoiceField(ChoiceField)
    ...
 
TypedMultipleChoiceField(MultipleChoiceField)
    coerce = lambda val: val   对选中的每一个值进行一次转换
    empty_value= ''            空值的默认值
 
ComboField(Field)
    fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式
                               fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
 
MultiValueField(Field)
    PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
 
SplitDateTimeField(MultiValueField)
    input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
    input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
 
FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中
    path,                      文件夹路径
    match=None,                正则匹配
    recursive=False,           递归下面的文件夹
    allow_files=True,          允许文件
    allow_folders=False,       允许文件夹
    required=True,
    widget=None,
    label=None,
    initial=None,
    help_text=''
 
GenericIPAddressField
    protocol='both',           both,ipv4,ipv6支持的IP格式
    unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
 
SlugField(CharField)           数字,字母,下划线,减号(连字符)
    ...
 
UUIDField(CharField)           uuid类型

2.2、Django model中的class Meta详解

  • 通过一个内嵌类 "class Meta" 给你的 model 定义元数据, 类似下面这样:
class Foo(models.Model): 
    bar = models.CharField(maxlength=30)

    class Meta: 
        # ...
  • Model 元数据就是 "不是一个字段的任何数据" -- 比如排序选项, admin 选项等等;
  • 下面是所有可能用到的 Meta 选项. 没有一个选项是必需的. 是否添加 class Meta 到你的 model 完全是可选的;

app_label

  • app_label这个选项只在一种情况下使用,就是你的模型类不在默认的应用程序包下的models.py文件中,这时候你需要指定你这个模型类是那个应用程序的。比如你在其他地方写了一个模型类,而这个模型类是属于myapp的,那么你这是需要指定为:
app_label='myapp'

db_table

  • db_table是用于指定自定义数据库表名的。Django有一套默认的按照一定规则生成数据模型对应的数据库表名,如果你想使用自定义的表名,就通过这个属性指定,比如:
table_name='my_owner_table'   
  • 若不提供该参数, Django 会使用 app_label + '_' + module_name 作为表的名字.
  • 若你的表的名字是一个 SQL 保留字, 或包含 Python 变量名不允许的字符--特别是连字符 --没关系. Django 会自动在幕后替你将列名字和表名字用引号引起来.

db_tablespace

  • 有些数据库有数据库表空间,比如Oracle。你可以通过db_tablespace来指定这个模型对应的数据库表放在哪个数据库表空间。

get_latest_by

  • 由于Django的管理方法中有个lastest()方法,就是得到最近一行记录。如果你的数据模型中有 DateField 或 DateTimeField 类型的字段,你可以通过这个选项来指定lastest()是按照哪个字段进行选取的。
  • 一个 DateField 或 DateTimeField 字段的名字. 若提供该选项, 该模块将拥有一个 get_latest() 函数以得到 "最新的" 对象(依据那个字段):
get_latest_by = "order_date"

managed

  • 由于Django会自动根据模型类生成映射的数据库表,如果你不希望Django这么做,可以把managed的值设置为False。
  • 默认值为True,这个选项为True时Django可以对数据库表进行 migrate或migrations、删除等操作。在这个时间Django将管理数据库中表的生命周期
  • 如果为False的时候,不会对数据库表进行创建、删除等操作。可以用于现有表、数据库视图等,其他操作是一样的。

order_with_respect_to

  • 这个选项一般用于多对多的关系中,它指向一个关联对象。就是说关联对象找到这个对象后它是经过排序的。指定这个属性后你会得到一个get_XXX_order()和set_XXX_order()的方法,通过它们你可以设置或者回去排序的对象。
  • 举例来说, 如果一个 PizzaToppping 关联到一个 Pizza 对象, 这样做:
order_with_respect_to = 'pizza'
  • ...就允许 toppings 依照相关的 pizza 来排序.

ordering

  • 这个字段是告诉Django模型对象返回的记录结果集是按照哪个字段排序的。比如下面的代码:
ordering=['order_date'] 
# 按订单升序排列
ordering=['-order_date'] 
# 按订单降序排列,-表示降序
ordering=['?order_date'] 
# 随机排序,?表示随机
ordering = ['-pub_date', 'author']
# 对 pub_date 降序,然后对 author 升序
  • 需要注意的是:不论你使用了多少个字段排序, admin 只使用第一个字段;

permissions

  • permissions主要是为了在Django Admin管理模块下使用的,如果你设置了这个属性可以让指定的方法权限描述更清晰可读。
  • 要创建一个对象所需要的额外的权限. 如果一个对象有 admin 设置, 则每个对象的添加,删除和改变权限会人(依据该选项)自动创建.下面这个例子指定了一个附加权限: can_deliver_pizzas:
permissions = (("can_deliver_pizzas", "Can deliver pizzas"),)
  • 这是一个2-元素 tuple 的tuple或列表, 其中两2-元素 tuple 的格式为:(permission_code, human_readable_permission_name).

unique_together

  • unique_together这个选项用于:当你需要通过两个字段保持唯一性时使用。这会在 Django admin 层和数据库层同时做出限制(也就是相关的 UNIQUE 语句会被包括在 CREATE TABLE 语句中)。比如:一个Person的FirstName和LastName两者的组合必须是唯一的,那么需要这样设置:
unique_together = (("first_name", "last_name"),)

verbose_name

  • verbose_name的意思很简单,就是给你的模型类起一个更可读的名字:
verbose_name = "pizza"
  • 若未提供该选项, Django 则会用一个类名字的 munged 版本来代替: CamelCase becomes camel case.

verbose_name_plural

  • 这个选项是指定,模型的复数形式是什么,比如:
verbose_name_plural = "stories"
  • 若未提供该选项, Django 会使用 verbose_name + "s".
posted @ 2021-06-30 13:21  SRE运维充电站  阅读(187)  评论(0编辑  收藏  举报