一、新闻模型
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/