学习Django进阶

本文深入探讨了Django中的各种字段类型,如BooleanField、IntegerField等,并讲解了字段选项与约束,如主键、唯一性和默认值。还介绍了如何创建测试应用、调试与修复migrations,以及内嵌类Meta的使用。涵盖了模型继承、实例方法、高级查询和事务处理等内容。
摘要由CSDN通过智能技术生成

Django进阶

字段类型

有限使用, 尽量使用和数据库一致的数据类型

  • BooleanField

    代表true或者false, 也就是代表1和0;

  • IntegerField

  • BigIntField

  • FloatField

  • DecimalField


  • CharField

    在mysql中对应的就是varchar, 所以必须指定长度
    name = models.CharField(max_length=200)
    
  • TextField

    遇到大的文本和图片, 文件. 推荐做法是存当前的URI或者URL, 然后通过路径从静态资源服务器, 文档数据库或者云服务器中获取该文件


  • DateField

  • DateTimeField

  • AutoField

    如果没有指定主键, 当前模型会自动将一个自增id的IntegerField做为主键.

  • ImageField

  • EmailField

    当前django提供用来做特殊约束和校验的字段.

  • UUIDField

    一般来说, uuid会用作当前数据表的主键

字段选项/约束

  • primary_key

    将当前字段设置为主键

    id = models.AutoField(max_length=191, primary_key=True)
    
  • null

    默认为False, 如果为True, 当前字段可以为NULL.

  • blank

    代表空白字符"", 默认为False, 如果是True, 当前字段允许为空

    password = models.CharField(max_length=200, blank=False)
    
  • unique

    默认为False, 如果为True, 重复记录会报错

  • default

    默认值

  • 时间类型字段

    • auto_now_add

      create_time = models.DateTimeField(auto_now_add=True)
      
    • auto_now

      update_time = models.DateTimeField(auto_now=True)
      

创建测试应用myblog

class Person(models.Model):
    name = models.CharField(max_length=200, primary_key=True)
    email = models.EmailField()
    update_time = models.DateTimeField(auto_now=True)
    create_time = models.DateTimeField(auto_now_add=True)

    null_test = models.CharField(max_length=200, null=True)
    blank_test = models.CharField(max_length=200, blank=True)

调试

  • 修改manage.py进行debug调试

        print(sys.argv)
        # sys.argv = ['manage.py', 'migrate']
        execute_from_command_line(sys.argv)
    
  • 修复migrations

    执行python manage.py migrate命令其实是按顺序执行未同步的migrations.

    • 更改migrations中的文件解决问题
    • 删除migrations文件推倒重来
      • django会在数据表django_migrations中创建同步记录
      • 删除对应的同步记录
      • 如果有创建表的记录, 需要删除表

内嵌类Meta

通过一个内嵌类Meta来定义元数据, 元数据又被称为中介数据, 用于描述数据得数据.

简单地讲, Meta就是通过属性来描述model对象, 为其提供额外得功能.

  • abstract

    将当前模型类转换成抽象类, 当进行migrate的时候会被忽略.

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

  • app_label

    指定当前model从属于哪个已经注册的应用

    使用场景一般为应用只编写视图层来处理业务逻辑. 模型层统一由一个models模块来管理, 所以要区分所属应用

  • db_table

    自定义表名, 如果不指定表名则默认为应用名_模型名

    第一种使用情况为目标表已经存在.

    第二种为开发没有管理表的权限, 需要dba建表再开发.

    第三种为规范数据库的表名命名, 而不是使用django默认的命名规范.

  • managed

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

    • 虽然设置了managed为False, 但是如果没有主键的化, 依然会自动创建主键.

    很多公司都会由专人DBA来管理数据库.

    独立开发流程: 创建模型-> migrate

    公司合作开发流程: dba建表->创建模型

  • ordering

    设置排序字段, 默认排序规则为升序

    • -表示降序

      ordering = ['-order_date']
      ordering = ['-pub_date', 'author']
      
    • ?表示随机的意思

      ordering = ['?']
      
  • get_lastest_by

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

  • indexes

    设置索引

        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=191)
        email = models.EmailField()
        update_time = models.DateTimeField(auto_now=True)
        create_time = models.DateTimeField(auto_now_add=True)
    
        null_test = models.CharField(max_length=200, null=True)
        blank_test = models.CharField(max_length=200, blank=True)
    
        class Meta:
            abstract = True
    
    
    class Reader(Person):
        whether_vip = models.BooleanField(default=False)
    
  • 多重继承

    如果当前模型对象没有指定主键, 那么django会自动帮我们创建名为id的主键字段.

    为了解决多重继承产生的id冲突, 你需要覆盖id字段.

    from django.db import models
    
    # Create your models here.
    class Student(models.Model):
        # db_column为数据库中的字段
        student_id = models.AutoField(primary_key=True, db_column="id")
        name = models.CharField(max_length=200)
    
    
    class Book(models.Model):
        book_id = models.AutoField(primary_key=True, db_column="id")
        book_name = models.CharField(max_length=200)
    
    
    class BorrowRecord(Student, Book):
        _id = models.AutoField(primary_key=True, db_column="id")
        borrow_time = models.DateTimeField(auto_now_add=True)
    

实例方法

  • 获取最新记录

    get_lastest_by = ['id']
    item = model.objects.latest()
    
  • 自定义输出

        def __str__(self):
            return f"id:{self.id}, {self.question_text}"
    
  • 刷新当前记录

    refresh_from_db
    
  • 字段验证

    比如EmailField调用clean_fields会验证当前格式是否正确

  • 字段唯一性验证

    # 在meta中设置唯一性字段
    unique_together = ['name', 'email']
    reader.validate_unique(exclude=['null_test', 'create_time', 'update_time', 'id'])
    

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

    • save

      reader.email = "test@163.com"
      reader.save()
      
  • 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
      		...
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值