Django中的ORM模型

Django ORM配置

项目配置

DATABASES = {
   'default': {
       'ENGINE': 'django.db.backends.mysql',    #数据库引擎
       'NAME': 'django_data',  #数据库名
       'USER': 'mj',   #账户名
       'PASSWORD': 'x', #密码
       'HOST': 'x', #主机
       'PORT': '3306', #端口
  }
}
  • 配置选项

    • default-默认的数据库,可配置多个

    • ENGINE-模板引擎

  • sqlite3的配置选项

    • 只需要指定数据库引擎和数据库文件名称即可

    • DATABASES = {
         'default': {
             'ENGINE': 'django.db.backends.sqlite3',    #数据库引擎
             'NAME': 'mydatabase.db',  #数据库名
        }
      }

安装依赖

pip install mysqlclient

 

 

常见的ORM字段类型

Django ORM类型映射

Django中的模型代码

文本

  • CharField、TextField-字符串、文本

  • FileField、lmageField--文件、图片

  • FilePathField--文件路径

  • EmailField--邮件地址

  • URLField--URL地址

整数

  • IntegerField--整数

  • SmalllntegerField--整数

  • BiglntegerField-整数

  • BooleanField-布尔值(1,0)

  • PositivelntegerField-正整数

小数

  • FloatField、DecimalField一-小数

时间

  • DateField一日期

  • TimeField-时间

特殊关系

  • OneToOneField--一对一关联

  • ForeignKey--外键关联

  • ManyToManyField--多对多关联

  • GenericForeignKey--复合关联

 

类型的选项

  • 每个类型都有可选参数,部分类型有必传参数

  • 参数传递是无序的(需要写参数的名称)

  • 一般情况下,第一个参数不指定名称

常用

  • CharField

    • max_length--最大长度

    • 相关类型

      • EmailField

      • URLField

  • DateTimeField

    • auto_now--更新时间记录更改时的时间

    • auto_now_add--记录创建的时间(注册时使用)

 

 

模型的创建

from django.db import models


class User(models.Model):
   """用户模型"""
   name = models.CharField('姓名', max_length=64)
   sex = models.CharField('性别', max_length=1, choices=(
      ('1', '男'),
      ('0', '女')
  ),default='1')
   #年龄正整数
   age = models.PositiveIntegerField('年龄',default=0)
   #用户名不能重复unique
   username = models.CharField('用户名',max_length=64,unique=True)
   password = models.CharField('密码',max_length=256)
   remark = models.CharField('备注',max_length=64,null=True,blank=True)

   created_at = models.DateTimeField('注册时间',auto_now_add=True)
   updated_at = models.DateTimeField('最后修改时间',auto_now=True)
   

 

模型同步migrate

实现模型同步

  • 检查settings.py

  • 注册app

  • 检查数据库

  • 检查模型:python manage,py check

  • 使用migrate执行同步:

    • python manage.py makemigrations

    • python manage.py migrate

 

模型的元数据

元数据的描述

使用Meta类来表示

  • 对模型的补充说明

  • 示例

class Meta:
   verbose_name = '用户基础信息'
   verbose_name_plural = '用户基础信息'
   db_table = 'oauth_user'   #指定模型表名称
  1. db_table--模型映射的数据库表的名称

  2. ordering--指定数据表的默认排序规则

  3. verbose_name--供编程查看的字段名称(便于阅读)

 

abstract--抽象类

  • 抽象类不会生成数据库表

  • class CommonModel(models.Model):
       """自定义模型的基类 这个类不会生成具体的数据表"""
       created_at = models.DateTimeField('注册时间', auto_now_add=True)
       updated_at = models.DateTimeField('最后修改时间', auto_now=True)

       class Meta:
           abstract = True
  • 抽象类可被继承

    class Profile(CommonModel):
       nickname = models.CharField('昵称', max_length=64)
  • 生成的Profile表中有

    fields=[
                  (
                       "id",
                       models.BigAutoField(
                           auto_created=True,
                           primary_key=True,
                           serialize=False,
                           verbose_name="ID",
                      ),
                  ),
                  (
                       "created_at",
                       models.DateTimeField(auto_now_add=True, verbose_name="注册时间"),
                  ),
                  (
                       "updated_at",
                       models.DateTimeField(auto_now=True, verbose_name="最后修改时间"),
                  ),
                  ("nickname", models.CharField(max_length=64, verbose_name="昵称")),
              ],

proxy--代理模型(对父模型功能的扩充)

  • 比如User是一个基类,现在有一个角色是管理员,管理员可以代理User的所有属性并进行扩充,这样不会让User过于冗杂

  • class Manager(User):
       class Meta:
           proxy = True

     

外键关联类型

关联关系

  • 一对一

  • 一对多

  • 多对多

 

一对一关系

  • OneToOneField(to,on_delete,parent_link=False,**options)

  • 举例:用户信息进行分表

    • 用户基本信息<--用户详细信息

 

一对多关系

  • Foreignkey(to,on_delete,**options)

  • 举例:用户提问

    • 一个用户可以提问多个问题

    • 此时在问题这个表上加上一个Foreignkey指向用户表,这样就可以使用一对多

class Profile(CommonModel):
   """用户相信信息"""
   """拿到一个用户的基础信息,通过张三来取到详细信息
      在此建立一个反向引用
  """
   # zhangsan = User()
   # zhangsan.profile
   user = models.OneToOneField('User', on_delete=models.CASCADE,
                               related_name='profile',
                               db_column='user')
   """OnetoOne在数据库表中都会默认加上一个id user_id
      db.colum把名字改为user
  """
   nickname = models.CharField('昵称', max_length=64)


class Question(CommonModel):
   """问题"""
   name = models.CharField('问题名称', max_length=64)


class Answer(CommonModel):
   question = models.ForeignKey(Question, on_delete=models.CASCADE,
                                related_name='answers',
                                verbose_name='关联的问题')

   content = models.TextField('答案的问题')


class Classify(models.Model):
   """分类
  1 酒水 假设在数据库中拿到酒水,那么通过children可以拿到下面两个记录
      2 啤酒 假设在数据库中拿到啤酒,那么通过parent可以拿到酒水这个对象
      3 白酒
  """
   name = models.CharField('名称', max_length=64)
   parent = models.ForeignKey('self', related_name='children',
                              on_delete=models.CASCADE)

 

多对多

  • ManyToManyField(to,**options)

  • 举例:收藏问题

    • 用户可以收藏多个问题,一个问题可以被多个用户收藏

class User(models.Model):
   ......
collect_ques = models.ManyToManyField('Question')

 

类型的参数选项

to----关联的模型(必传)

  • 模型类

  • 模型类(字符串)

  • self

 

on_delete---删除选项(必传)

  • CASCADE:关联删除

  • PROTECT:受保护,不允许被删除

  • SET_NULL:设置为None,需要添加选项null=True

  • SET_DEFAULT:设置为默认值,需要添加选项default

  • SET():传参设置值

  • DO_NOTHING:什么也不做

 

related_name

是否需要反向引用,反向引用的名称

比如一个用户登录后,想通过这个用户查到自己所提的所有问题,这时可以通过反向引用

related_query_name

反向引用的名称

from django.db import models


class CommonModel(models.Model):
   """自定义模型的基类 这个类不会生成具体的数据表"""
   created_at = models.DateTimeField('注册时间', auto_now_add=True)
   updated_at = models.DateTimeField('最后修改时间', auto_now=True)

   class Meta:
       abstract = True


class User(models.Model):
   """用户模型"""
   name = models.CharField('姓名', max_length=64)
   sex = models.CharField('性别', max_length=1, choices=(
      ('1', '男'),
      ('0', '女')
  ), default='1')
   # 年龄正整数
   age = models.PositiveIntegerField('年龄', default=0)
   # 用户名不能重复unique
   username = models.CharField('用户名', max_length=64, unique=True)
   password = models.CharField('密码', max_length=256)
   remark = models.CharField('备注', max_length=64, null=True, blank=True)
   email = models.EmailField('用户的邮箱', max_length=64, null=True, blank=True)

   collect_ques = models.ManyToManyField('Question')

   class Meta:
       db_table = 'user'


class Manager(User):
   class Meta:
       proxy = True


class Profile(CommonModel):
   """用户相信信息"""
   """拿到一个用户的基础信息,通过张三来取到详细信息
      在此建立一个反向引用
  """
   # zhangsan = User()
   # zhangsan.profile
   user = models.OneToOneField('User', on_delete=models.CASCADE,
                               related_name='profile',
                               db_column='user')
   """OnetoOne在数据库表中都会默认加上一个id user_id
      db.colum把名字改为user
  """
   nickname = models.CharField('昵称', max_length=64)


class Question(CommonModel):
   """问题"""
   name = models.CharField('问题名称', max_length=64)


class Answer(CommonModel):
   question = models.ForeignKey(Question, on_delete=models.CASCADE,
                                related_name='answers',
                                verbose_name='关联的问题')

   content = models.TextField('答案的问题')


class Classify(models.Model):
   """分类
  1 酒水 假设在数据库中拿到酒水,那么通过children可以拿到下面两个记录
      2 啤酒 假设在数据库中拿到啤酒,那么通过parent可以拿到酒水这个对象
      3 白酒
  """
   name = models.CharField('名称', max_length=64)
   parent = models.ForeignKey('self', related_name='children',
                              on_delete=models.CASCADE)

 

 

 

复合类型

举例

  • 景点评论,订单评论

    • 1景点------n评论

    • 1订单------n评论

普通版

from django.db import models


class Sight(models.Model):
   """景点表"""
   name = models.CharField('景点名称', max_length=64)
   address = models.CharField('景点地址', max_length=64)


class Order(models.Model):
   sn = models.CharField('订单号', max_length=64)
   amount = models.FloatField('订单金额')


class SightComment(models.Model):
   """景点评论"""
   content = models.CharField('评论内容', max_length=512)
   score = models.FloatField('分数', default=512)


class OrderComment(models.Model):
   """订单评论"""
   content = models.CharField('评论内容', max_length=512)
   score = models.FloatField('分数', default=512)

优化

评论记录同时关联到景点和订单等多种会被评论的

具体模型

  • Contentype----类容模型

  • ForeignKey(Contentype)----关联复合模型

  • GenericForeignKey----关联模型

  • GenericRelation----反向关联

from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models


class Sight(models.Model):
   """景点表"""
   name = models.CharField('景点名称', max_length=64)
   address = models.CharField('景点地址', max_length=64)


class Order(models.Model):
   # order = Order()
   # order.comments
   sn = models.CharField('订单号', max_length=64)
   amount = models.FloatField('订单金额')
   comments = GenericRelation('Comment', related_query_name='order_comments')


class Comment(models.Model):
   """所有评论"""
   # comment = Comment()
   # comment.order
   # comment.order

   """首先使用外键关联,关联自django提供的类容模型content_type
      把关联的某一个模型的某一条记录的id存下来
      通过评论的某一条记录找到对应的对象    
  """
   content_type = models.ForeignKey(ContentType,on_delete=models.CASCADE)
   object_id = models.PositiveIntegerField()
   content_object = GenericForeignKey('content_type', 'object_id')  # comment.content_object
   content = models.CharField('评论内容', max_length=512)
   score = models.FloatField('分数', default=512)

原理分析

  • ContentType可以找到对应的模型

  • object_id找到对应的id

  •  

 

 

 

 

 

 

 

posted @ 2023-05-08 21:02  qfzwy  阅读(132)  评论(0)    收藏  举报