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

    model是Django中的数据模型每个model都是继承自django.db.models.Model的子类每个...

网友评论

      本文标题:Models#1

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