周五公司给买的键盘到货了,毕竟我自己不太会买这么贵的键盘……不过这个键盘的布局由于键数缩小到60,键位改变了不少。为了熟悉一下键盘,整理一下近期的一些经验,以飨读者。
Could not resolve URL for hyperlinked relationship using view name "user-detail"
使用Django REST Framework 提示经过查询,由于我在app里的urls.py
里设定了namespace名称,因此在Django设置序列化的文件serializers.py
中,需要在serializers.HyperlinkedIdentityField
中指定view_name
的名称,例如:
class UserSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="myapp:user-detail")
class Meta:
model = User
fields = ('url', 'username')
至此,该问题解决。
Django Models 处理Select形式字段经验总结
其实还是挺简单的,由于我的需求只需要在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'),
]
> 一般来说,最好在模型类内部定义选择,并为每个值定义一个合适的名称的常量:
> ```python
> 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
。
最后,新设备镇楼压轴。这可是近几年手头设备最贵的一年了。