zoukankan      html  css  js  c++  java
  • Django model

    1. 通常每个model都映射到一张单独的表,自定义model的特点:
      • 每个model都是一个继承自django.db.models.Model的class
      • 每个model的attribute代表一个表的列值
      • model中只包含与表列对应的field
      • django会自动生成访问数据库的api
    2. 示例代码:
      from django.db import models
      class Person(models.Model):
      #models是module,CharField是class
          first_name = models.CharField(max_length=30)
          last_name = models.CharField(max_length=30)
      • 自动创建数据库表,表名默认为app name_model name,可以重命名
      • 自动添加id字段作为主键,此行为也可以改写,相当于执行了id=models.AutoField(primary_key=true),如果显示指定了其他列为primary key,则不会自动添加id列
      • 每个Model都要有一个primary_key=true的field
      • 要通过manage.py migrate命令创建数据库表
    3. 关于字段(field):
      • 每个字段都是Field class的子类对象,Field class是抽象类
      • django通过field的类型确定表列的类型
      • 确定用于显示field的html元素
      • 有效性判断
      • 字段名不能是python保留字,不能带‘--’
    4. common filed arguments包括不限于:
      • null:默认是false,如果是true,则在数据库表中存储null值
      • blank:默认是false,如果true,则存放空值
      • choices:可以作为field值的tuple
      • default:field的默认值,可以是一个值也可以是一个callable object
      • primary_key:如果是ture,这个field是model的primary key
      • db_column:field对应的数据库列名
      • db_index:为这个field创建索引
      • unique:如果是true,field的值必须是唯一的
      • help_text:帮助信息
    5. model之间的关系,也是表之间的关系
      • 多对一:使用ForeignKey类,可以定义自身对自身的多对一关系
        #多对一:ForeignKey类
        from django.db import models
        
        class Manufacturer(models.Model):
            # ...
            pass
        
        class Car(models.Model):
            manufacturer = models.ForeignKey(Manufacturer)
            # ...
      • 对对多:ManyToManyField class,可以定义自身对自身的多对多的关系
        #多对多:ManyToManyField class,在Topping或者Pizza中定义均可
        from django.db import models
        
        class Topping(models.Model):
            # ...
            pass
        
        class Pizza(models.Model):
            # ...
            toppings = models.ManyToManyField(Topping)
        • 可以使用intermediate model管理多对多关系,指定其他field,示例代码:
          from django.db import models
          
          class Person(models.Model):
              name = models.CharField(max_length=128)
          
              def __str__(self):            
                  return self.name
          
          class Group(models.Model):
              name = models.CharField(max_length=128)
              #through参数指向的就是intermediate class
              members = models.ManyToManyField(Person, through='Membership')
          
              def __str__(self):             
                  return self.name
          
          class Membership(models.Model):
              person = models.ForeignKey(Person)
              group = models.ForeignKey(Group)
              #可以指定其他field 描述两者之间的关系
              date_joined = models.DateField()
              invite_reason = models.CharField(max_length=64)
        • intermediate class的限制条件:
          • 必须包含指向两个关系类的foreignkey
          • 自身指向自身的多对多关系,应该设置两个指向同一model的foreignkey
          • 自身指向自身的多对多关系,ManyToManyField.symmetrical必须为false
      • 一对一:OneToOneField class,可以定义自身指向自身的一对一关系
    6. 自定义field type:需要继承models.Field
    7. Meta options:使用class Meta为model定义metadata,django已经定义了很多Meta option字段,如
      • ordering:排序字段
      • app_label: app name
      • db_table:model对应的数据库表名
      • abstract指定该类为抽象类
      • managed:默认为true,django会为model创建数据库表,为false则不会创建
      • proxy:指定proxy model
    8. from django.db import models
      
      class Ox(models.Model):
          horn_length = models.IntegerField()
      
          class Meta:
              #排序字段
               ordering = ["horn_length"]
              verbose_name_plural = "oxen"
              #指定存放model的database table
              db_table="myOx"
    9. Model常用的属性和方法:
      • Model.objects:数据库查询的接口,用于返回model instance
      • get_absolute_url():生成对象的url,在admin site会使用到
    10. 重写已定义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()
              #调用基类方法
               super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
              do_something_else()
    11. 执行自定义sql语句:语法为Manager.raw(raw_query,params=None,translations=None):
      #两者效果一样
      Person.objects.raw('SELECT * FROM myapp_person')
      Person.objects.all()
    12. 定义抽象类:在Meta class中定义abstract=true,抽象类不能创建数据库表,且抽象类中的字段名与其子类中的字段名不能相同。另外Meta class也可以继承
      from django.db import models
      
      class CommonInfo(models.Model):
          # ...
          class Meta:
              abstract = True
              ordering = ['name']
      
      class Student(CommonInfo):
          # django会自定把abstract设为false,所以Student不是抽象类
          class Meta(CommonInfo.Meta):
              db_table = 'student_info'
    13. multi-table 继承:子model与父model间通过隐式的OneToOneField关联,每个model对应单独的表。显示的OneToOneField会占用ForeignKey或ManyToManyField默认的related_name值,如果在子类中还要使用ForeignKey或者ManyToManyField需要显示指定related_name的值
      from django.db import models
      
      class Place(models.Model):
          name = models.CharField(max_length=50)
          address = models.CharField(max_length=80)
      
      class Restaurant(Place):
          serves_hot_dogs = models.BooleanField(default=False)
          serves_pizza = models.BooleanField(default=False)
      
      class Supplier(Place):
          #需要显示指定related_name参数
          customers = models.ManyToManyField(Place,related_name='provider')
       
    14. 关于related_name以及relatd objects:如果在一个model中通过ForeignKey,OneToOneField或者ManyToManyField定义了relationship,relationship的另一端就是related objects.model可以直接访问related model,related model通过related_name可以访问model,related_name默认的名字是modelclassname_set,是一个Manager对象,示例代码:
      from django.db import models
      
      class Blog(models.Model):
          name = models.CharField(max_length=100)
          tagline = models.TextField()
      
          def __str__(self):             
              return self.name
      
      class Entry(models.Model):
         
          #blog 是related object
          blog = models.ForeignKey(Blog)
          headline = models.CharField(max_length=255)
          body_text = models.TextField()
          pub_date = models.DateField()
      
          def __str__(self):              
              return self.headline
      
      b = Blog.objects.get(id=1)
      b.entry_set.all() # Returns all Entry objects related to Blog.
      
      # b.entry_set is a Manager that returns QuerySets.
      b.entry_set.filter(headline__contains='Lennon')
      b.entry_set.count()
    15. 要注意的问题:
      • 抽象类中定义了relationship时,如果要显示指定related_name,则抽象类的多个子类会都包含相同的related_name会导致错误,正确的方式是在related_name中包含‘%(app_label)s’和’%(class)s’,app_label会用app name替换,class用class name替换
        from django.db import models
        
        class Base(models.Model):
            m2m = models.ManyToManyField(OtherModel, related_name="%(app_label)s_%(class)s_related")
        
            class Meta:
                abstract = True
        
        class ChildA(Base):
            pass
        
        class ChildB(Base):
            pass
        
        #如果related_name指定了固定名字如"refer",那么m2m.refer无法确定是引用ChildA还是ChildB,如果
        #Base类中隐式指定related_name,则不会有错误,ChildA中的related_name默认为childa_set,ChildB中
        #related_name默认为childb_set
    16. Proxy models:如果需要改变一个model的behavior,如添加新方法,改变默认的manager等,不需要添加新数据时可以使用proxy model.创建,删除,更新model数据都同使用original model一样会被保存。区别是在proxy model中改变默认的ordering,manager等则不会改变original model. original model的所有实例都可以在Proxy model中访问,反之亦然。对于非抽象model类,proxy model只能继承一个model,对于抽象model类,如果抽象类中没有field则可以继承任意多个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:
              #定义proxy model的方法
              proxy = True
              ordering = ["last_name"]
      
          def do_something(self):
              # ...
              pass
      
       #可以在proxy model中访问original model实例,反之亦然
       p = Person.objects.create(first_name="foobar")
       MyPerson.objects.get(first_name="foobar")
       
  • 相关阅读:
    关于敏捷开发的一些思考。
    【转】浅谈程序猿的职业规划,看你如何决定自己的未来吧。
    Individual Project
    homework_06 围棋程序改进
    homework 08_2 C++11新特性作业之二
    homework_08
    软件工程个人作业——Agile Software Development读后感
    附加题——软件工程之结对编程
    软件工程——PairProject
    软件工程第一次个人项目——词频统计by11061153柴泽华
  • 原文地址:https://www.cnblogs.com/phenixyu/p/3993775.html
Copyright © 2011-2022 走看看