zoukankan      html  css  js  c++  java
  • django之Model(数据表)的增删改查

    一、新闻模型

    class BaseModel(models.Model):
        # 创建时间
        create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
        # 更新时间
        update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
        # 数据是否删除
        # 逻辑删除
        is_delete = models.BooleanField(default=False, verbose_name="逻辑删除")
    
        class Meta:
            # 这个类只是被继承的
            abstract = True
    
    # 新闻
    class News(BaseModel):
        title = models.CharField(max_length=150, verbose_name="文章标题")
        digest = models.CharField(max_length=200, verbose_name="文章摘要")
        content = models.TextField(verbose_name="文章内容")
        clicks = models.IntegerField(default=0, verbose_name="点击量")
        image_url = models.URLField(default="", verbose_name="图片链接")
        tag = models.ForeignKey("Tag", on_delete=models.SET_NULL, null=True)
        # 如果是其他模块的数据库,关联需要使用app_name.model_name
        author = models.ForeignKey("users.User", on_delete=models.SET_NULL, null=True)
    
        class Meta:
            # 默认排序
            ordering = ["-update_time", "-id"]
            # 指明数据库名
            db_table = "tb_news"
            verbose_name = "新闻"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return f"News({self.id}, {self.title})"

    二、操作

      两种创建的对象:QuerySet(惰性机制)、Manager

      1、添加

    # 方式一
    news = News(title="Python机器学习", 
                digest="...", 
                content="...", 
                )
    news.save()
    
    # 方拾二
    news = News()
    news.title = "Python机器学习"
    news.digest = "..."
    news.content = "..."
    news.save()
    
    # 方式三
    News.objects.create(title="Python机器学习", 
                        digest="...", 
                        content="...",
                        )
    
    
    # 方式四
    # 返回一个元组(查到的数据,是否创建)
    res = News.objects.get_or_create(id=2000)
    print(res)

      2、修改

    # 修改一条
    news = News.objects.get(id=3)
    news.title = "机器学习"
    news.content = "..."
    news.save()
    
    # 修改多条
    News.objects.filter(tag__name="机器学习").update(title="机器学习")

      3、删除

    # 删除一条
    News.objects.get(id=9).delete()
    
    # 删除多条
    News.objects.all().delete()

      4、查找

    # 查询一条,返回模型对象,立即查询
    News.objects.first() # 查询默认第一条数据
    News.objects.last()  # 查询默认最后一条数据
    # 查询不到和查询到多条都会报错,所以一般配合查询主键使用,pk指代主键
    News.objects.get(pk=3)
    
    # 查询多条
    News.objects.all()  # 查询所有
    News.objects.filter(title="Python高级", tag="Python全栈")  # 相当于执行while...and...
    News.objects.exclude(title="Python高级", tag="Python全栈")  # 相当于执行while not (... and ...),与filter相反
    # 切片,惰性机制:如果不计算,就不会执行数据库查询 res = News.objects.all()
    print(res.query)  # 输出数据库查询语句
    res[1:20].all()  # 切片相当于limit
    
    # 多条件OR查询:Q查询
    from django.db.models import Q
    News.objects.filter(Q(name="Python")|Q(title="机器学习"))
    # F查询:我们构造的过滤器只是将字段值与某个字符串常量做比较。如果我们要对两个字段的值做比较,那么就应该使用F查询
    # Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作
    # 查询点击量与id相同的新闻
    from django.db.models import F
    News.objects.filter(id=F("clicks"))
    
    # 不仅可以查询,也可以更新值,总而言之,F("field_name")就是获取对应记录的字段值
    News.objects.update(id=F("id")+1)
    # 指定字段查询,返回QuerySet字典列表
    # <QuerySet [{"":"", "", ""}, {"":"", "":""}]>
    News.objects.values("title", "content")
    # 指定字段查询,返回QuerySet对象列表,一定包含主键,比较高效
    # 即使只有三个字段,也可以访问其他字段,只不过是再查询数据库
    # <QuerySet [News(id, title, content), News(id, title, content)]>
    News.objects.only("title", "content")
    # 指定排除字段查询,用法与only同,效果相反
    News.objects.defer("title", "content")
    # 排序
    # 从小到大排序
    News.objects.all().order_by("id")
    # 从大到小排序
    News.objects.all().order_by("-id")
    
    # 查询条件,应用在get、filter、exclude上面
    # 精准查询
    News.objects.get(id__exact=7)
    # 忽略大小写的精准查询
    News.objects.get(id__iexact=7)
    
    # 模糊查询,针对CharField,包含
    News.objects.filter(title__contains="Python")
    # 模糊查询,针对CharField,忽略大小写
    News.objects.filter(title__icontains="Python")
    # 模糊查询,针对CharField,以什么开头
    News.objects.filter(title__startswith="Python")
    # 模糊查询,针对CharField,以什么结尾
    News.objects.filter(title__endswith="Python")
    
    # 比较查询,针对IntegerField,大于
    News.objects.filter(id__gt=2)
    # 比较查询,针对IntegerField,小于
    News.objects.filter(id__lt=2)
    # 范围查询,针对IntegerField,在什么范围之内
    News.objects.filter(id__range=(10, 200))
    
    # 指定迭代条件, 针对IntegerField、CharField
    News.objects.filter(id__in=[1, 2, 4])
    News.objects.filter(title__in=["Python", "Java"])
    
    # 字段值是否为空
    News.objects.filter(title__isnull=True)
    
    # 聚合查询,利用聚合函数
    from django.db.models import Count, Sum, Avg, Max, Min
    # 如果没有指定键名,则默认为field_name__func_name
    # id__avg
    News.objects.aggregate(Avg("id", "tag_id"))
    # 指定键名
    News.objects.aggregate(id_avg=Avg("id"))
    
    # 分组查询(一般分组与聚合函数会连用)
    # 单独的聚合函数是对数据集的某个字段进行聚合
    # 分组加聚合是先分组,再对每个分组的相应字段进行聚合
    # 对每个分类进行分组,在统计每个分类的新闻数量
    Tag.objects.annotate(news_count=Count("news")).values("name", "news_count")
    
    
    # 正向和反向查询
    # 如果两个表具有关联关系,那么无论在哪一个表,我们都能查询到关联的表的信息
    # 查询id为50的新闻的分类
    # 这是多对一的关系
    News.objects.get(id=5).tag.name
    Tag.objects.get(news__id=5).name
    
    # 多对多的关系
    # 学生和课程表
    from django.db.models import Model, ManyToManyField, CharField
    
    
    class Student(Model):
        department = ManyToManyField("Department")
    
    
    class Department(Model):
        name = CharField(max_length=20)
    
    
    # 查询id为5的学生的课程
    Student.objects.get(id=5).department.all()
    
    Department.objects.filter(student__id=5)
    
    # 查询上数学课的所有学生
    # 最终是为了查询学生信息,但是我们连个表都可以查到,多对多中彼此都添加了一个对方的管理器,
    # 只不过一个是显示声明,一个是隐式声明
    
    Student.objects.filter(department__name="math")
    # student_set是默认添加的
    # modelname_set有add、remove、clear、all的功能,不需要save
    Department.objects.get(name="math").student_set.filter()

    三、优化

      优化主要是针对查询的,一般是同样的查询结果,最少的查询次数,这个参考django数据库查询优化文档:https://docs.djangoproject.com/en/3.0/topics/db/optimization/

  • 相关阅读:
    管理员技术(三): 配置静态网络地址、 使用yum软件源 、 升级Linux内核、查找并处理文件、查找并提取文件内容
    管理员技术(二): 访问练习用虚拟机、 命令行基础技巧 、 挂载并访问光盘设备、ls列表及文档创建、复制删除移动
    管理员技术(一):装机预备技能、安装一台RHEL7虚拟机、使用RHEL7图形桌面、Linux命令行基本操作
    基础(三):yum(RedHat系列)和apt-get(Debian系列 )用法及区别
    基础(二):Linux系统/etc/init.d目录和/etc/rc.local脚本
    基础(一):SCSI硬盘与IDE硬盘有什么区别
    高级运维(六):源码安装Redis缓存服务、常用Redis数据库操作指令、配置Redis主从服务器
    错题
    count 【mysql】
    自连接和子查询
  • 原文地址:https://www.cnblogs.com/loveprogramme/p/12730977.html
Copyright © 2011-2022 走看看