其实还是挺简单的,由于我的需求只需要在Django后台页面显示,所以只需要在Models那里处理一下就好了。由于我需要的字段比较多,因此在app目录下新建了一个文件cons.py专门存储字段。
以下是模型文件models.py:
# -*- coding: UTF-8 -*-
from django.db import models
from .cons import SALCATEGORIES
from .cons import YEAR
from .cons import MONTH
from .cons import ORG
# Create your models here.
class Salary(models.Model):
month = models.CharField('月',max_length=50, choices=MONTH)
year = models.CharField('年',max_length=10, choices=YEAR)
org = models.CharField('组织名',max_length=100, choices=ORG)
create_timestamp = models.DateTimeField('创建时间',auto_now_add=True)
change_timestamp = models.DateTimeField('修改时间',auto_now=True)
def __str__(self):
return dict(YEAR)[self.year] dict(MONTH)[self.month] '_' dict(ORG)[self.org]
class Meta:
db_table = 'salary'
cons.py文件引入的内容如下:
# -*- coding: UTF-8 -*-
SALCATEGORIES = (
('shubas','应发 - 基本工资'),
('shupos','应发 - 岗位工资'),
('shupls','应发 - 绩效工资'),
('shuotr','应发 - 其他'),
('wihuem','扣缴 - 失业保险'),
('wihmed','扣缴 - 医疗保险'),
('wihold','扣缴 - 养老保险'),
('wihgjj','扣缴 - 公积金'),
('wihbgj','扣缴 - 补充住房公积金'),
('wihotr','扣缴 - 其他'),
('relsal','实发 - 实发工资'),
('relotr','实发 - 其他'),
)
YEAR = (
('2020','2020年'),
('2021','2021年'),
('2022','2022年'),
('2023','2023年'),
('2024','2024年'),
('2025','2025年'),
('2026','2026年'),
('2027','2027年'),
('2028','2028年'),
)
MONTH = (
('01','01月'),
('02','02月'),
('03','03月'),
('04','04月'),
('05','05月'),
('06','06月'),
('07','07月'),
('08','08月'),
('09','09月'),
('10','10月'),
('11','11月'),
('12','12月'),
)
ORG = (
('abc','中国abc公司'),
('cde','上海cde公司'),
)
这个键值对,存储的是前面的键,显示的是后面的值
上面的这个形式,对于该变量的类型也是一个挺有趣的东西。众所周知( )是个元组的初始化标志,正常来说元组是不能直接转换为字典的,但是上面这样的变量是可以正常转换的,请见如下测试代码和输出:
print(type(ORG))
for i in ORG:
print(i[0] "_" i[1])
print(type(i))
print(type(dict(ORG)))
print(dict(ORG))
for i in dict(ORG):
print(i)
print(type(i))
输出:
<class 'tuple'>
abc_中国abc公司
<class 'tuple'>
cde_上海cde公司
<class 'tuple'>
<class 'dict'>
{'abc': '中国abc公司', 'cde': '上海cde公司'}
abc
<class 'str'>
cde
<class 'str'>
回到实现上来。最终我需要的后台显示情况如下:
数据库表存储情况如下:
这里我们介绍一下Django里模型Field的choices字段:
一个 sequence 本身由正好两个项目的迭代项组成(例如 [(A,B),(A,B)...] ),作为该字段的选择。如果给定了选择,它们会被 模型验证 强制执行,默认的表单部件将是一个带有这些选择的选择框,而不是标准的文本字段。
每个元组中的第一个元素是要在模型上设置的实际值,第二个元素是人可读的名称。例如:
YEAR_IN_SCHOOL_CHOICES = [ ('FR', 'Freshman'), ('SO', 'Sophomore'), ('JR', 'Junior'), ('SR', 'Senior'), ('GR', 'Graduate'), ]
一般来说,最好在模型类内部定义选择,并为每个值定义一个合适的名称的常量:
from django.db import models class Student(models.Model): FRESHMAN = 'FR' SOPHOMORE = 'SO' JUNIOR = 'JR' SENIOR = 'SR' GRADUATE = 'GR' YEAR_IN_SCHOOL_CHOICES = [ (FRESHMAN, 'Freshman'), (SOPHOMORE, 'Sophomore'), (JUNIOR, 'Junior'), (SENIOR, 'Senior'), (GRADUATE, 'Graduate'), ] year_in_school = models.CharField( max_length=2, choices=YEAR_IN_SCHOOL_CHOICES, default=FRESHMAN, ) def is_upperclass(self): return self.year_in_school in {self.JUNIOR, self.SENIOR}
虽然你可以在模型类之外定义一个选择列表,然后引用它,但在模型类内定义选择和每个选择的名称,可以将所有这些信息保留在使用它的类中,并帮助引用这些选择(例如,Student.SOPHOMORE 将在导入 Student 模型的任何地方工作)。
你还可以将你的可用选择收集到可用于组织目的的命名组中:
MEDIA_CHOICES = [ ('Audio', ( ('vinyl', 'Vinyl'), ('cd', 'CD'), ) ), ('Video', ( ('vhs', 'VHS Tape'), ('dvd', 'DVD'), ) ), ('unknown', 'Unknown'), ]
每个元组中的第一个元素是应用于该组的名称。第二个元素是一个二元元组的迭代,每个二元元组包含一个值和一个可读的选项名称。分组后的选项可与未分组的选项结合在一个单一的列表中(如本例中的 'unknown' 选项)。
对于每一个设置了 choice 的模型字段,Django 会添加一个方法来检索字段当前值的可读名称。参见数据库 API 文档中的 get_FOO_display()。
请注意,选择可以是任何序列对象——不一定是列表或元组。这让你可以动态地构造选择。但是如果你发现自己把 chips 魔改成动态的,你可能最好使用一个合适的的带有 ForeignKey 的数据库表。 chips 是用于静态数据的,如果有的话,不应该有太大的变化。
每当 choices 的顺序变动时将会创建新的迁移。
除非 blank=False 与 default 一起设置在字段上,否则包含 "---------" 的标签将与选择框一起呈现。要覆盖这种行为,可以在 choices 中添加一个包含 None 的元组,例如 (None, 'Your String For Display') 。另外,你也可以在有意义的地方使用一个空字符串来代替 None ——比如在 CharField。
,