clean()
自定义字段验证方法
你知道可以用 clean()
方法为特定的字段添加自定义的验证逻辑吗?
from django.db import models
from django.core.exceptions import ValidationError
class Product(models.Model):
name = models.CharField(max_length=100)
price = models.DecimalField(max_digits=10, decimal_places=2)
def clean(self):
if self.price <= 0:
raise ValidationError("价格必须大于零哦。")
2. 条件性默认值在你的保存逻辑或表单中使用
clean()
来确保无效数据不会混入你的数据库。
有时候,你可能需要一些默认值根据特定条件来动态调整。
从 django.utils.timezone 导入 now
class Event(models.Model):
name = models.CharField(max_length=100)
start_date = models.DateTimeField(default=now)
end_date = models.DateTimeField(default=lambda: now() + timedelta(days=7))
3. 多字段唯一性约束,例如,确保邮箱地址和电话号码组合的唯一性。这非常棒,适用于时间戳或自动生成默认未来日期。
用唯一性约束替换不再推荐使用的 unique_together 约束,以便更好地控制。
from django.db import models
# 定义了一个名为`Membership`的模型类
class Membership(models.Model):
# 定义了一个名为`user`的外键字段,关联到`auth.User`,并设置删除时级联删除
user = models.ForeignKey('auth.User', on_delete=models.CASCADE)
# 定义了一个名为`group`的外键字段,关联到`Group`,并设置删除时级联删除
group = models.ForeignKey('Group', on_delete=models.CASCADE)
class Meta:
# 定义了模型的约束条件
constraints = [
# 定义了一个唯一约束条件,字段为`user`和`group`,命名为`唯一会员关系`
models.UniqueConstraint(fields=['user', 'group'], name='唯一会员关系')
]
这确保了,没有用户被添加到相同的组重复。
4. 在枚举中使用choices
Django的choices
使字段更加整洁有序,特别是在使用枚举时。
from django.db import models
class 请求状态(models.TextChoices):
待处理 = 'P', '待处理'
已批准 = 'A', '已批准'
已拒绝 = 'R', '已拒绝'
class 请求(models.Model):
状态 = models.CharField(max_length=1, choices=请求状态.choices, default=请求状态.待处理)
5. 用于多对多的定制,就像这样使用类似
Status.PENDING
而不是直接使用字符串。
需要在多对多关系中加入额外数据吗?可以使用 through
。
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author, through='Authorship')
class Authorship(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
role = models.CharField(max_length=50) # 例如:合著者,编辑。
这让你可以了解更多关于关系的细节。
6. 字段级别的可编辑性与editable=False
禁止管理员直接编辑,但仍允许通过程序更新。
定义了一个名为Order的类,它继承了models.Model。其中total_price是一个小数字段,最大位数为10,小数点后有2位,且该字段不允许编辑。
你仍然能在代码里更新 total_price
,但在后台不能更新。
使用 upload_to
动态整理上传文件。
def 上传头像(instance, filename):
return f"uploads/{instance.user.id}/{filename}"
class 用户资料(models.Model):
user = models.OneToOneField('auth.User', on_delete=models.CASCADE)
头像 = models.ImageField(upload_to=上传头像)
上传的文件会根据用户的ID整齐存储起来。
8. 在模型中使用Property
字段
Django框架中的模型可以包含计算字段。
员工类定义了一个名为 Employee 的模型类。
该类包含两个属性:first_name 和 last_name,分别表示员工的名字和姓氏,每个属性都是长度最多为50个字符的字符串。
此外,该类还定义了一个名为 full_name 的属性方法,用于返回员工的全名,即名字和姓氏的组合。
9. 自动设置字段的像访问字段一样访问它:
employee.full_name
save()
方法
通过重写 save()
方法来自定义字段的保存行为。
# 定义一个名为Article的模型类
class Article(models.Model):
# 定义一个名为title的CharField,最大长度为100
title = models.CharField(max_length=100)
# 定义一个名为slug的SlugField,唯一且可为空
slug = models.SlugField(unique=True, blank=True)
# 重写保存方法,自定义slug的生成逻辑
def save(self, *args, **kwargs):
# 如果slug为空,则根据title生成slug
if not self.slug:
# 将title转为小写并替换空格为破折号
self.slug = self.title.lower().replace(' ', '-')
# 调用父类的save方法
super().save(*args, **kwargs)
10. 软删除 with如果没有提供网址别名,则根据标题自动生成。
is_archived
与其删除记录,不如存档。
# 抽象基类,定义基础模型
class BaseModel(models.Model):
is_archived = models.BooleanField(default=False)
# 重写删除方法,标记为已归档,而不是真正删除
def delete(self, *args, **kwargs):
self.is_archived = True
self.save()
class Meta:
# 设置为抽象类,不能实例化
abstract = True
您的数据在用户看来已被删除的情况下仍然保持安全。
结论:
Django的模型系统非常强大,这些技巧可以帮助你更好地利用它,写出更简洁、更高效的代码。你已经在用哪些技巧了呢?你最喜欢哪个呢?
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦