为了账号安全,请及时绑定邮箱和手机立即绑定

Django模型字段的10个冷门技巧,让你的代码更高效!

1. 使用 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("价格必须大于零哦。")

在你的保存逻辑或表单中使用 clean() 来确保无效数据不会混入你的数据库。

2. 条件性默认值

有时候,你可能需要一些默认值根据特定条件来动态调整。

从 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=请求状态.待处理)

使用类似 Status.PENDING 而不是直接使用字符串。

5. 用于多对多的定制,就像这样

需要在多对多关系中加入额外数据吗?可以使用 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,但在后台不能更新。

7.: 自定义文件上传位置

使用 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 的属性方法,用于返回员工的全名,即名字和姓氏的组合。

像访问字段一样访问它:employee.full_name

9. 自动设置字段的 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 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消