zoukankan      html  css  js  c++  java
  • Django基础——ORM字段和字段参数

    ORM概念:

    对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象(

    1. 不同的程序员写的SQL水平参差不齐
    2. 执行效率也参差不齐

    )的技术。

    ORM 能够把 python语句 自动的翻译 为SQL语句

    ORM优点: 

      1. 简单,不用自己写SQL语句
      2. 开发效率高

      缺点:

      执行效率有差距 

    ORM的对应关系:

      类 ---> 数据表
      对象 ---> 数据行
      属性 ---> 字段

    ORM能做的事儿:
      1. 操作数据表 --> 创建表/删除表/修改表
          操作models.py里面的类

      2. 操作数据行 --> 数据的增删改查

      不能创建数据库,自己动手创建数据库

    使用Django的ORM详细步骤:
    1. 自己动手创建数据库
      create database 数据库名;
    2. 在Django项目中设置连接数据库的相关配置(告诉Django连接哪一个数据库)
      # 数据库相关的配置
      DATABASES = {
      'default': {
      'ENGINE': 'django.db.backends.mysql', # 连接的数据库类型
      'HOST': '127.0.0.1', # 连接数据库的地址
      'PORT': 3306, # 端口
      'NAME': "day61", # 数据库名称
      'USER': 'root', # 用户
      'PASSWORD': '123456' # 密码
      }
      }

    3. 告诉Django用pymysql代替默认的MySQLDB 连接MySQL数据库
      在项目/__init__.py文件中,写下面两句:
      import pymysql
      # 告诉Django用pymysql来代替默认的MySQLdb
      pymysql.install_as_MySQLdb()

    4. 在app/models.py里面定义类
    # 出版社
    class Publisher(models.Model):
    id = models.AutoField(primary_key=True) # 自增的ID主键
    # 创建一个varchar(64)的唯一的不为空的字段
    name = models.CharField(max_length=64, null=False, unique=True)

    5. 执行两个命令
    1. python3 manage.py makemigrations --> 把models.py里面的更改记录到小本本上
    2. python3 manage.py migrate --> 把更改翻译成SQL语句,去数据库执行

    Django ORM常用字段:
      1. AutoField --> 自增
      2. CharField --> varchar(xx)
      3. ForeignKey --> 外键

        ForeignKey 字段的参数;

        a.to  --> 设置要关联的表;

        b.to_field -->设置要关联的表的字段

        c.related_name -->  反向操作时,使用的字段名,用于代替原反向查询时的'表名_set'。
      4. ManyToManyField --> 多对多关联

      5. DateField  -->日期字段,日期格式  YYYY-MM-DD 
      6. DateTimeField --> 日期时间字段,格式 YYYY-MM-DD HH:MM

      7. IntegerField -->整数类型

     字段的合集:

    AutoField(Field)
            - int自增列,必须填入参数 primary_key=True
    
        BigAutoField(AutoField)
            - bigint自增列,必须填入参数 primary_key=True
    
            注:当model中如果没有自增列,则自动会创建一个列名为id的列
            from django.db import models
    
            class UserInfo(models.Model):
                # 自动创建一个列名为id的且为自增的整数列
                username = models.CharField(max_length=32)
    
            class Group(models.Model):
                # 自定义自增列
                nid = models.AutoField(primary_key=True)
                name = models.CharField(max_length=32)
    
        SmallIntegerField(IntegerField):
            - 小整数 -32768 ~ 32767
    
        PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
            - 正小整数 0 ~ 32767
        IntegerField(Field)
            - 整数列(有符号的) -2147483648 ~ 2147483647
    
        PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
            - 正整数 0 ~ 2147483647
    
        BigIntegerField(IntegerField):
            - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
    
        BooleanField(Field)
            - 布尔值类型
    
        NullBooleanField(Field):
            - 可以为空的布尔值
    
        CharField(Field)
            - 字符类型
            - 必须提供max_length参数, max_length表示字符长度
    
        TextField(Field)
            - 文本类型
    
        EmailField(CharField):
            - 字符串类型,Django Admin以及ModelForm中提供验证机制
    
        IPAddressField(Field)
            - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
    
        GenericIPAddressField(Field)
            - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
            - 参数:
                protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
                unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol="both"
    
        URLField(CharField)
            - 字符串类型,Django Admin以及ModelForm中提供验证 URL
    
        SlugField(CharField)
            - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
    
        CommaSeparatedIntegerField(CharField)
            - 字符串类型,格式必须为逗号分割的数字
    
        UUIDField(Field)
            - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
    
        FilePathField(Field)
            - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
            - 参数:
                    path,                      文件夹路径
                    match=None,                正则匹配
                    recursive=False,           递归下面的文件夹
                    allow_files=True,          允许文件
                    allow_folders=False,       允许文件夹
    
        FileField(Field)
            - 字符串,路径保存在数据库,文件上传到指定目录
            - 参数:
                upload_to = ""      上传文件的保存路径
                storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
    
        ImageField(FileField)
            - 字符串,路径保存在数据库,文件上传到指定目录
            - 参数:
                upload_to = ""      上传文件的保存路径
                storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
                width_field=None,   上传图片的高度保存的数据库字段名(字符串)
                height_field=None   上传图片的宽度保存的数据库字段名(字符串)
    
        DateTimeField(DateField)
            - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
    
        DateField(DateTimeCheckMixin, Field)
            - 日期格式      YYYY-MM-DD
    
        TimeField(DateTimeCheckMixin, Field)
            - 时间格式      HH:MM[:ss[.uuuuuu]]
    
        DurationField(Field)
            - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
    
        FloatField(Field)
            - 浮点型
    
        DecimalField(Field)
            - 10进制小数
            - 参数:
                max_digits,小数总长度
                decimal_places,小数位长度
    
        BinaryField(Field)
            - 二进制类型
    
    字段合集
    

     

    在ORM 表单中没有char字段;需要自定义

    #自定义char字段
    class FixedCharField(models.Field):
    	"""
    	自定义的char类型的字段类
    	"""
    
    	def __init__(self, max_length, *args, **kwargs):
    		self.max_length = max_length
    		super(FixedCharField, self).__init__(max_length=max_length, *args, **kwargs)
    
    	def db_type(self, connection):
    		"""
    		限定生成数据库表的字段类型为char,长度为max_length指定的值
    		"""
    		return 'char(%s)' % self.max_length
    
    class Class(models.Model):
        id = models.AutoField(primary_key=True)
        title = models.CharField(max_length=25)
        # 使用上面自定义的char类型的字段
        cname = FixedCharField(max_length=25)
    

      

    3. 常用的字段参数
    1. null

    用于表示某个字段可以为空。
    2. default

    该字段为默认值
    3. unique

    如果设置为unique=True 则该字段在此表中必须是唯一的 。
    4. db_index
    如果db_index=True 则代表着为此字段设置数据库索引。

    5. DateField和DateTimeField才有的参数:
    auto_now_add=True --> 创建数据的时候自动把当前时间赋值
    auto_add=True --> 每次更新数据的时候更新当前时间
    上述两个不能同时设置!!!

      

    表和表之间的关系
    1. 一对多(出版社和书);1对多  ,外键通常设置在多的那一边;
    publisher = models.ForeignKey(to="Publisher")
    数据库中实际 生成的是一个 publisher_id 字段

    2. 多对多(作者和书);多对多,通常设置在正向查询多的那一边;比如我用author 查询 book 比较多,则把外键放在author.
    books = models.ManyToManyField(to="Book")

    在数据库中:
    是通过第三张表建立的关系(默认第三张表名 为字段_另一个多对多的字段)

    # 书
    class Book(models.Model):
    	id = models.AutoField(primary_key=True)
    	bookname = models.CharField(null=False,max_length=15,unique=True)
    	price = models.DecimalField(max_digits=5,decimal_places=2,default=99.99)
    	kucun = models.IntegerField(default=10000)
    	sell_num = models.IntegerField(default=0)
    	# 书和出版社关联的外键(单表对单表的)
    	# on_delete=models.CASCADE ; 级联删除,即删除主表数据会自动删除从表数据;使关联的数据对应;
    	# related_name 来代替 表名_set;
    	publisher = models.ForeignKey(to="Publisher",default=1,on_delete=models.CASCADE,
         related_name='books')
         #反向操作时,使用的字段名,用于代替原反向查询时的'表名_set'。 #在数据库里面生成的字段为 publisher_id 是出版社的id #Book.object.publisher 为该书对应的出版社的对象; def __str__(self): return "Publisher_object:{}".format(self.bookname) #出版社 class Publisher(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(null=False,max_length=15,unique=True) def __str__(self): return "Publisher_object:{}".format(self.name) # class Meta: # ordering ='id' # 书和出版社是,1对1的(ForeignKey(to=)),是需要添加外键的 # 而书和作者是多对多的,一本书可以有多个作者,还有一个作者也可能有多本书,即多对多的时候用(ManyToManyField(to=)) #然后ROM会自动的帮你生成另外的一张表来表示多对多的关系,这个列子生产的另外一个表为author_book; # 作者 class Author(models.Model): id = models.AutoField(primary_key=True) author_name = models.CharField(null=False, max_length=15) #多对多的 book = models.ManyToManyField(to="Book") def __str__(self): return "Publisher_object:{}".format(self.author_name)

     详细参考(点我) 

    3. 一对一  ;比如作者和作者详情,一个作者只能对于自己的作者详情;

    1. 什么时候用一对一?
      当 一张表的某一些字段查询的比较频繁,另外一些字段查询的不是特别频繁
      把不怎么常用的字段 单独拿出来做成一张表 然后用过一对一关联起来
    2. 优势
      既保证数据都完整的保存下来,又能保证大部分的检索更
    3. ORM中的用法
      OneToOneField(to="")

    举例:作者和作者详情是一对一的;跟一对多,用法相同,只不过detail里面的不能重复;在数据库中也是多一个detail_id 字段

    总结+练习ORM(多表的查询)

    	# #####################基于对象查询(子查询)##############################
    	#                按字段(publish)
    	# 一对多   book  ----------------->  publish
    	#               <----------------
    	#                 book_set.all()
    
    	# 正向查询按字段:
    
    	# 查询python这本书籍的出版社的邮箱
    
    	# python=models.Book.objects.filter(title="python").first()
    	# print(python.publish.email)
    
    	# 反向查询按     表名小写_set.all()
    
    	# 苹果出版社出版的书籍名称
    
    	# publish_obj=models.Publish.objects.filter(name="苹果出版社").first()
    	# for obj in publish_obj.book_set.all():
    	#     print(obj.title)
    
    	#                按字段(authors.all())
    	# 多对多   book  ----------------------->  author
    	#               <----------------
    	#                  book_set.all()
    
    	# 查询python作者的年龄
    	# python = models.Book.objects.filter(title="python").first()
    	# for author in python.authors.all():
    	#     print(author.name ,author.age)
    
    	# 查询alex出版过的书籍名称
    
    	# alex=models.Author.objects.filter(name="alex").first()
    	# for book in alex.book_set.all():
    	#     print(book.title)
    
    	#                  按字段 authorDetail
    	# 一对一  author  ----------------------->  authordetail
    	#                <----------------
    	#                  按表名  author
    
    	# 查询alex的手机号
    	# alex=models.Author.objects.filter(name='alex').first()
    	# print(alex.authorDetail.telephone)
    
    	# 查询家在山东的作者名字
    
    	# ad_list=models.AuthorDetail.objects.filter(addr="shandong")
    	#
    	# for ad in ad_list:
    	#     print(ad.author.name)
    
    	'''
    	对应sql:
    
    	   select publish_id from Book where title="python"
    	   select email from Publish where nid =   1
    
    
    	'''
    
    	# #####################基于queryset和__查询(join查询)############################
    
    	# 正向查询:按字段  反向查询:表名小写
    
    	# 查询python这本书籍的出版社的邮箱
    	# ret=models.Book.objects.filter(title="python").values("publish__email")
    	# print(ret.query)
    
    	'''
    	select publish.email from Book 
    	left join Publish on book.publish_id=publish.nid 
    	where book.title="python"
    	'''
    
    	# 苹果出版社出版的书籍名称
    	# 方式1:
    	# ret1 = models.Publish.objects.filter(name="苹果出版社").values("book__title")
    	# print("111111111====>", ret1.query)
    	# # 方式2:
    	# ret2 = models.Book.objects.filter(publish__name="苹果出版社").values("title")
    	# print("2222222222====>", ret2.query)
    	#
    	# # 查询alex的手机号
    	# # 方式1:
    	# ret = models.Author.objects.filter(name="alex").values("authorDetail__telephone")
    	#
    	# # 方式2:
    	# models.AuthorDetail.objects.filter(author__name="alex").values("telephone")
    
    
    
    	# 查询手机号以151开头的作者出版过的书籍名称以及书籍对应的出版社名称 ; 跨5张表; 都联合起来;
    	ret = models.Book.objects.filter(authors__authorDetail__telephone__startswith="151").values('title', "publish__name")
    	print(ret)
    

      

    # 作者
    class Author(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        phone = models.IntegerField()
        books = models.ManyToManyField(to="Book", related_name="authors")
        detail = models.OneToOneField(to="AuthorDetail")
    
        def __str__(self):
            return self.name
    
    
    # 作者详情
    class AuthorDetail(models.Model):
        # 爱好
        hobby = models.CharField(max_length=32)
        # 地址
        addr = models.CharField(max_length=128)  

  • 相关阅读:
    0827IO作业
    0927集合作业
    初学集合,以及泛型
    异常课——抛出
    Python环境变量配置
    安装Python
    MySQL多表操作
    MySQL增删改查
    Group by分组详解
    MySQL常用函数
  • 原文地址:https://www.cnblogs.com/zenghui-python/p/10800176.html
Copyright © 2011-2022 走看看