项目中碰到的ORM问题

文章详细解释了Django中外键的on_delete参数的不同策略,如CASCADE、PROTECT等,并介绍了GenericForeignKey如何实现灵活的多模型关联。此外,还讨论了ORM字段如何设置唯一性约束以及文件上传的处理。同时,提到了cached_property装饰器的作用,它可以缓存方法的结果以提高性能。
摘要由CSDN通过智能技术生成

外键关联关系on_delete参数问题

  • CASCADE      删除级联,当父表的记录删除时,子表中与其相关联的记录也会删除。即:当一个老师被删除时,关联该老师的学生也会被删除
  • PROTECT      子表记录所关联的父表记录被删除时,会报ProtectedError异常。即:当一个学生所关联的老师被删除时,会报ProtectedError异常
  • SET_NULL      子表记录所关联的父表记录被删除时,将子表记录中的关联字段设为NULL,注意:需要允许数据表的该字段为NULL,需要写null=True
  • SET_DEFAULT      子表记录所关联的父表记录被删除时,将子表记录中的关联字段设为一个给定的默认值,需要写default=关联id值
  • DO_NOTHING      子表记录所关联的父表记录被删除时,什么也不做
  • SET()      设置为一个传递给SET()的值或者一个回调函数的返回值,该参数用得相对较少

外键字段GenericRelation

from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
通的Foreignkey,只能“指向”单一的模型,而ContentType则可以允许和任意的模型进行连接,非常灵活。设立这种外键,需要3个字段

1:设定一个普通外键,连接于ContentType,一般名字叫“content_type”。
这个字段实际上是代码你在Likes这个点赞里面,是给哪个对应的模型在点赞,是文章/评论/视频,或是其他。

2:设立一个PostiveIntegerField的字段,一般名字叫做“object_id”。
以记录所对应的模型的实例的id号,比如我们给一篇文章点赞,这篇文章是Post类里的id为10的文章,那么这个object_id就是这个10。
其实看到这里,应该清楚了,当你有了模型的名字,也告诉了你这个模型的实例的id号,你就可以找出这个实例了。

3:第三个也是最后一个,就是设定这个GenericForeignkey外键了,这个外键需要传入两个参数,就是上面的1和2,如果你为上面2个字段取的名字就是content_type和object_id的话,你可以不需要输入,因为这个字段默认会读取这2个名字。如果你自定义过了,那就需要你手动添加。

ORM字段唯一值限制

某些字段,不是主键,但是我们想要他在数据库中生成唯一值,不能够重复,那么我们就需要给该字段添加唯一约束:

vul_num = models.CharField(max_length=255, unique=True, blank=True,null=True)

这个字段是自己手动拼接的编号,为了保证编号的唯一限定,需要我们在字段添加unique=True,这样该字段是不能重复的

注意:如果添加唯一限制,CharField最大数不能超过255,否则会报错,空的也会校验唯一,所以如果有一个空,再生成一个空也会唯一冲突报错

关于文件上传

ppp = models.FileField('file', upload_to=指定上传路径, max_length=256, null=True, blank=True)

针对文件的上传,upload_to对应的是指定上传路径,也可以是一个函数,函数返回值是对应的上传路径,可以在其中针对上传文件进行校验

在类中定义类,从外部类找到内部类的属性

如果是类嵌套的情况下,外部类想要访问内部类对象想要访问内部类的属性,我们可以通过外部类点内部类产生的对象,最后在点击内部类的属性就可以获得该内部类的属性了

class Index:
    
    class Inner:
        name = 'zh'


print(Index.Inner().name)  # zh   方法1


class Index:
    def __init__(self):
        self.inner = self.Inner()
    class Inner:
        name = 'zh'


print(Index.Inner.name)  # 方法2

还可以选择第三种继承django的ORM中Choice字段这样可以直接用来点击类名拿到属性

from django.db.models.enums import Choices


class Index:
    class Inner(Choices):
        name = 'zh'


print(Index.Inner.name)  # zh

实际业务场景,我们可以在模型类中写这样一个字段,里面有多个选择,可以按照内部类的选择来进行字段的筛选,如下代码,这样可以提升代码的可扩展性,另类的Choice选择写法

class Base(models.Model):


    # 申请状态
    class Status(Choice):
        # 暂存(尚未提交)
        TEMPORARY = 0
        # 未通过 (已提交,尚未审核)
        NOT_THROUGH = 1
        # 审核中
        UNDER_REVIEW = 2
        # 驳回
        TURN_DOWN = 3
        # 已通过 (审核完成)
        PASSED = 4

    status = models.PositiveIntegerField(default=Status.TEMPORARY)

相对于我们传统写choice字段来说,我们筛选的方式会发生改变,我们可以使用filter(status=Base.Status.NOT_THROUGH),而传统的需要我们书写filter(status=1),这样对于代码的可拓展性会比较差

@cached_property装饰器

@chached_propery是一个装饰器,跟@property比较类似,他也可以将类的方法伪装成属性,该属性只会计算一次,然后缓存为普通属性,会将方法的结果缓存起来,只要实例持续存在,缓存结果就可以一直使用

于@property进行对比

# 使用 @property
# A sample class
class Sample():
    def __init__(self):
      self.result = 50

    @property
    # 方法:将结果值增加50
    def increase(self):
        self.result = self.result + 50
        return self.result

# obj 是 Sample 类的一个实例
obj = Sample()
print(obj.increase) # 100
print(obj.increase) # 150
print(obj.increase) # 200


# 用 @cached_property
from functools import cached_property

# A sample class
class Sample():
    def __init__(self):
      self.result = 50

    @cached_property
    # 方法:将结果值增加50
    def increase(self):
        self.result = self.result + 50
        return self.result

# obj 是 Sample 类的一个实例
obj = Sample()
print(obj.increase) # 100
print(obj.increase) # 100
print(obj.increase) # 100

使用@property每次调用都会一次计算结果的值,但是使用@cached_property会直接将第一次计算的结果缓存起来,以后每次在调用该方法的时候,拿到的都是第一次缓存的结果,他可以减少执行的时间,让程序执行的更快

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值