Django之路--进阶(二)之内嵌类Meta与模型继承

目录

内嵌类Meta

模型继承

实例方法

Django.setuP

QuerySet

高级

内嵌类Meta

通过一个内嵌类Meta来定义元数据

元数据又被称为“中介数据”,用来描述数据的数据

简单的讲Meta就是通过自定义属性描述model对象,为其提供额外功能

Meta可用的模块?

  • abstract:讲当前模型类转换成抽象类,当进行migrate的时候会被忽略

    因为migrate是对实体表进行修改,而抽象是一个虚的概念,所以不存在实体。

    实质性的作用:减少代码量,减少代码重复

class Person(models.Model):
    name=models.CharField(max_length=64)
    email = models.EmailField()
    update_time=models.DateTimeField(auto_now=True)
    create_time=models.DateTimeField(auto_now_add=True)
    null=models.CharField(max_length=200,null=True)
    blank_test=models.CharField(max_length=200, blank=True)
    
    
    class Meta:
        abstract=True
class Reader(Person):
    wether_vip=model.BooleanField(default=False)
class Writer(Person):
    pass
       

 

  • app_label:指定当前那个从属于已经注册的应用

    在项目中新建一个model层,对用途进行区分,然后用此继承。但是一定要注册。

    app_label = 'myapp'

    如果你想用 app_label.object_nameapp_label.model_name 来表示一个模型,你可以分别使用 model._meta.labelmodel._meta.label_lower

  • db_table:Options.db_table

    用于模型的数据库表的名称:db_table = music_album

  • managed

    默认为True,如果为False,当前migrate会忽略该模型

class Meta:

	db_table='reader'

	managed=False
  • orderding

    对象的默认排序,用于获取对象列表时:

    ordering = ['-order_date']

    这是一个字符串和/或查询表达式的元组或列表。每一个字符串都是一个字段名,前面有一个可选的“-”字头,表示降序。没有前缀“-”的字段将按升序排列。使用字符串“?”来随机排序。

    例如,要按 pub_date 字段升序排列,使用以下方法:

    ordering = ['pub_date']

    要按 pub_date 降序排列,请使用:

    ordering = ['-pub_date']

    要按 pub_date 降序,然后按 author 升序,请使用:

    ordering = ['-pub_date', 'author']

    你也可以使用 查询表达式。要按 author 升序排列,并使空值最后排序,请使用:

    from django.db.models import F
    ​
    ordering = [F('author').asc(nulls_last=True)]
  • get_latest_by

    设置获取最后一条记录的排序规则

    模型中的字段名或字段名列表,通常是 DateFieldDateTimeFieldIntegerField。这指定了在你的模型中使用的默认字段 Managerlast()earliest() 方法。

# Latest by ascending order_date.
get_latest_by = "order_date"

# Latest by priority descending, order_date ascending.
get_latest_by = ['-priority', 'order_date']
  •  indexs

设置索引

from django.db import models

class Customer(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

    class Meta:
        indexes = [
            models.Index(fields=['last_name', 'first_name']),
            models.Index(fields=['first_name'], name='first_name_idx'),
        ]
  •  unique_together

        多字段唯一性约束

        unique_together = ['driver', 'restaurant']

模型继承

  • 普通继承

class Person(models.Model):
    name=models.CharField(max_length=64)
    email = models.EmailField()
    update_time=models.DateTimeField(auto_now=True)
    create_time=models.DateTimeField(auto_now_add=True)
    null=models.CharField(max_length=200,null=True)
    blank_test=models.CharField(max_length=200, blank=True)
    
    
    class Meta:
        abstract=True
class Reader(Person):
    wether_vip=model.BooleanField(default=False)
class Writer(Person):
    pass
  • 多重继承
from django.db import models

# Create your models here.
class Student(models.Model):
    student_id=models.AutoField(primary_key=True,db_column='id')
    name=models.CharField(max_length=64)
class Book(models.Model):
    book_id=models.AutoField(primary_key=True,db_column='id')
    book_name = models.CharField(max_length=64)
class BorownRecord(Student,Book):
    _id=models.AutoField(primary_key=True, db_column='id')
    borown_time=models.DateTimeField(auto_now_add=True)

在上边代码值得注意的是:

db_column='id' --->都要指定一个每个表中的id,防止起冲突

_id=models.AutoField(primary_key=True, db_column='id') 规定自己表内的id,防止因为继承的student表和book表中的id冲突矛盾

 

实例方法

  • 获取最新记录

    get_latest_by=['id']
    ​
    item=model.objects.latest()

  • 自定义输出

    def __str__(self):
    ​
        return f "id:{self.id,},{self.question_text}"

  • refresh_db:刷新当前记录

  • 字段唯一性验证

    unique_together=["name","email"]

Django.setuP

import os
import random
import django


def create_reader():
    for i in range(10):
        reader = Reader(
            name=f'name_{i}',
            email=f'email_{i}@163.com',
            null_test=None,
            blank_test='',
            whether_vip=random.choice([True, False])
        )

		# 通过clean_fields方法对当前对象进行自检
        # 如果当前字段可以为None, 则需要将该字段置入exclude参数中
        reader.clean_fields(exclude=['null_test'])
        
        # 调用save会往数据插入一条数据或者更新一条数据
        reader.save()


if __name__ == "__main__":
    # 设置环境变量
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
    django.setup()
    from myblog.models import Reader
    create_reader()

QuerySet

  • Create

    • save

  • Retrieve

    Django的orm时一条执行链, 而不是单个语句

        Reader.objects.all().filter(id__gt=300).order_by("name", "id")

    orm尽量使用一些简单的接口

    如果查询需求比较复杂, 尽量使用SQL

    • all

      获取表中所有记录

      如果表非常大, 一定要小心使用.

    • get

      通过指定条件, 获取一条数据, 如果有多条, 则会报错

      reader = Reader.objects.get(name="name_0")
    • filter

      匹配满足条件的记录, 类似于SQL中的WHERE语句

      reader_array = Reader.objects.filter(name="name_0")
      • 比较

        Reader.objects.filter(id__gte=300)
        • >= ----- gte

        • > --------gt

        • <=-------lte

        • < --------lt

      • 模糊匹配

        类似于WHERE 字段 LIKE '%xx%'

        • __startswith

        • __endswith

        • __icontains

    • exlude

      filter逻辑取反

    • 限制返回的记录数

      相当于SQL中的limit

      reader_array[:5]
    • latest

      # 需要在models, Meta中指定get_latest_by
      Reader.objects.latest()

    • order_by

      Reader.objects.all().order_by("name", "id")

  • Update

  • Delete

    如果想对整张表进行清除, 还是truncate table命令更快

    • delete

      reader.delete()

高级

  • RAW

    遇到复杂的场景, 需要使用SQL语句

    通过Reader._meta.db_table来获取记录所在表

    queryset = Reader.objects.raw(f"select * from {Reader._meta.db_table} limit 1")
    list(queryset)

  • 指定数据库

    • 在settings配置该数据库,

      DATABASES = {
          'default': {
              'ENGINE': 'django.db.backends.mysql',
              'NAME': 'polls',
              'USER': 'root',
              'PASSWORD': 'qwe369',
              'HOST': '127.0.0.1',
              'PORT': '3306'
          },
          'person': {
              'ENGINE': 'django.db.backends.mysql',
              'NAME': 'person',
              'USER': 'root',
              'PASSWORD': 'qwe369',
              'HOST': '127.0.0.1',
              'PORT': '3306'
          }
      }

    • 使用参数using

      reader.save(using='person')
      Reader.objects.using('person').all()
  • 事务

    • 基于HTTP请求的事务

      • settings中要设置ATOMIC_REQUESTSTrue

      from django.db import transaction
      ​
      @transaction.atomic
      def my_view(request):
          表达式...
    • 基于视图具体逻辑的事务

      from django.db import transaction
      ​
      def viewfunc(request):
          表达式
          with transaction.atomic():
              表达式A
              表达式B
              ...

更多QuerySet API操作:https://docs.djangoproject.com/zh-hans/4.1/ref/models/querysets/

猜你喜欢

转载自blog.csdn.net/weixin_52312427/article/details/127089250