Models#1

作者: wangfp | 来源:发表于2017-09-18 12:44 被阅读0次
    • model是Django中的数据模型
      • 每个model都是继承自django.db.models.Model的子类
      • 每个model都映射一个数据表
      • model中的每个类属性对应着数据表中的一列
      • django支持ORM
    • 创建model并进行migrate后
      • Django会自动生成表名(可以自定义
      • Django会自动增加主键一列(可以自定义)
      • Django会根据不同数据库创建不同的SQL语句
    • Field中的常见选项
      • null:允许该列数据为空(默认为False)
      • blank:主要用于是否允许表单为空(默认为False)
      • choices:为一个Field提供可选项(并且默认生成的表单为一个选项)
        from django.db import models
        
        class Person(models.Model):
            # choices的对象是一个可迭代对象,其元素为‘含有两个元素的元组’
            SHIRT_SIZES = (
                ('S', 'Small'),
                ('M', 'Medium'),
                ('L', 'Large'),
            )
            name = models.CharField(max_length=60)
            shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
          
        # choice API
        >>> p = Person(name="Fred Flintstone", shirt_size="L")
        >>> p.save()
        >>> p.shirt_size
        'L'
        >>> p.get_shirt_size_display()   # get_FOO_display()方法可以显示具体内容
        'Large'
        
      • default:既可以是一个数值对象,也可以是一个可调用对象
      • help_text:在生成的表单中展示‘帮助’信息
      • primary_key:将某一列设置为主键(该列变为只读);默认为False,即Django会自动创建一个整型主键
      • unique:该列中的每个数据必须独一无二(默认为False)
    • 自动生成主键
      默认情况下,如果不显式指定主键,Django会在model中自动添加以下属性
      id = models.AutoField(primary_key=True)
      
    • 显式指定列名
      对于非关系型列(即非ForeignKeyField,ManyToManyField,OneToOneField),第一个位置参数为空时,将默认属性名为列名;否则使用位置参数作为列名
      对于关系型列,需要指定位置参数以表明关联的数据表
      # 列名为"person's first name"
      first_name = models.CharField("person's first name", max_length=30)
      
      # 列名为"first_name"
      first_name = models.CharField(max_length=30)
      
      # 关联表为"Poll"
      poll = models.ForeignKey(
          Poll,
          on_delete=models.CASCADE,
          verbose_name="the related poll",
      )
      
    • 关联
      • Many-to-one 关联
        使用django.db.models.ForeignKey,第一个位置参数需要指定关联表名
      • Many-to-many 关联
        使用django.db.models.ManyToManyField(相关的两个表中,只需要在一个表中指定即可)
        可以显式的创建many-to-many的关联数据表
        from django.db import models
        
        class Person(models.Model):
            name = models.CharField(max_length=128)
        
            def __str__(self):              # __unicode__ on Python 2
                return self.name
        
        class Group(models.Model):
            name = models.CharField(max_length=128)
            # 通过through指定关联表
            members = models.ManyToManyField(Person, through='Membership')
        
            def __str__(self):              # __unicode__ on Python 2
                return self.name
        
        class Membership(models.Model):
            person = models.ForeignKey(Person, on_delete=models.CASCADE)
            group = models.ForeignKey(Group, on_delete=models.CASCADE)
            date_joined = models.DateField()
            invite_reason = models.CharField(max_length=64)
        
      • One-to-one 关联
        使用django.db.models.OneToOneField,可以用于扩展某一model
    • Meta 选项
      Model的Meta中保存着所有非列的属性(比如ordering(默认排序)、db_table(数据表名称)等等)
      from django.db import models
      
      class Ox(models.Model):
          horn_length = models.IntegerField()
          
          # class Meta 是可选项
          class Meta:
              ordering = ["horn_length"]
              verbose_name_plural = "oxen"
      
    • Model 的方法
      我们可以在Model中自定义方法,也可以使用或者重载Model中已有的方法
      有两个方法在大多数情况下需要我们自己定义
      • __ str__()
      • get_absolute_url()
        该方法告诉Django如何得到一个对象的URL(一般使用django的reverse()函数)
        def get_absolute_url(self):
            from django.urls import reverse
            return reverse('people.views.details', args=[str(self.id)])
        
      重载Model中已定义的方法
      from django.db import models
      
      class Blog(models.Model):
          name = models.CharField(max_length=100)
          tagline = models.TextField()
      
          def save(self, *args, **kwargs):
              do_something()
              # 关键在于对Model.save()方法的继承上,另外通过使用(*args, **kwargs)参数可以自动获取相关参数
              super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
              do_something_else()
      

    • Model的继承
      django中存在三种继承
      • Abstract base classes
      • Multitable inheritance
      • Proxy models
    • Abstract base classes
      在class Meta中设置abstract = True,就可以将该model变为抽象类——该类中定义的列属性可以被子类所继承而无需重新定义,且class Meta中的属性亦会被继承(除了abstract = True)
      Abstract base classes并不会产生数据表,也不能直接用于创建实例
      from django.db import models
      
      class CommonInfo(models.Model):
          name = models.CharField(max_length=100)
          age = models.PositiveIntegerField()
          
          # 将CommonInfo声明为一个abc类
          class Meta:
              abstract = True
              ordering = ['name']
      
      class Student(CommonInfo):
          # Student 类自动继承name和age列
          home_group = models.CharField(max_length=5)
      
          class Meta: 
              # Student 类会继承CommonInfo中的Meta的信息
              # 不过在此之前会自动设置abstract=False(当然也可以自己显式地设置abstract=True从而成为abc类)
              db_table = 'student_info'
      
      为了指定子类关联表列的relate_name,可以在abc类的关联表列中进行设置
      # common/models.py
      from django.db import models
      
      class Base(models.Model):
          m2m = models.ManyToManyField(
              OtherModel,
              # 若不设置related_name,则默认为"子类名 + '_set'"
              # %(app_label)s 指代当前应用名称
              # %(class)s 指代当前类的类名
              related_name="%(app_label)s_%(class)s_related",
              related_query_name="%(app_label)s_%(class)ss",
          )
      
          class Meta:
              abstract = True
      
      # OtherModel 使用 ChildA 类时的属性名将是'common_childa_related'
      class ChildA(Base):
          pass
      
      class ChildB(Base):
          pass
      
    • Multi-table inheritance
      父类和子类都可以生成数据表,且子类会继承父类的类属性(列属性),但父类和子类是两个不同的表
      此外,不同于abc类,子类不会继承父类class Meta中的属性
    • Proxy models
      Proxy model用于当你只想为一个表增加一些方法或者Meta属性,而不想改变原model的代码时
      from django.db import models
      
      class Person(models.Model):
          first_name = models.CharField(max_length=30)
          last_name = models.CharField(max_length=30)
      
      class MyPerson(Person):
          class Meta:
              # 指定该类为Person的代理数据模型
              proxy = True
              # 在该proxy model中可以增加一个额外的Meta属性
              odering = ['last_name']
      
          # 在该proxy model中可以增加一些额外的方法
          def do_something(self):
              # ...
              pass
      
      # 需要注意的一点是Person和MyPerson类都可以调用Person数据表中的数据
      # 不同之处在于通过Person类创建/查找到的实例中没有ordering属性,也不能调用do_something方法
      

    相关文章

      网友评论

          本文标题:Models#1

          本文链接:https://www.haomeiwen.com/subject/eygvsxtx.html