Django - Models学习笔记

注意事项

  • admin.StackedInline

    堆栈类型的内部关联

  • admin.TabularInline

    表格类型的内部关联

list_display = ()
list_filter = []
search_fields = []
date_hierarchy = ‘’

was_published_recently.admin_order_field = ‘pub_date’
was_published_recently.boolean = True
变成图标
was_published_recently.short_description = ‘Published recently?’

urlpatterns 正则记得以/结尾

shortcuts

get_object_or_404 get()
get_list_or_404 filter()

render

‘polls:detail’ question.id

命名空间:后面不要加空格

forloop.counter指示for标签已经循环多少次。

简而言之,所有针对内部URL的POST表单都应该使用csrf_token模板标签。
你应该永远在成功处理POST数据后返回一个HttpResponseRedirect

views
template_name
pk = primary key
lte = less than or equal to

Models

tips

  • 每一个model都是django.db.models.Model.的子类
  • 类的属性相当于db的字段
  • db表的名字自动加上的 格式appname_classname
  • id字段是自动定义的 想要定制自己的pk 只需加上(primary_key=True)

using models 使用模型

  • 修改后在配置文件setting.py中INSTALLED_APPS添加新的app名
  • 每次添加新的model时候记得migrate
  • 第一次建立迁移文件时使用makemigrations

field 字段

字段就是类的属性

要注意选择字段名称的时候不要和models API 冲突,比如clean, save, 或者delete.

字段类型

普通字段

  • AutoField
  • BigIntegerField
  • BinaryField
  • BooleanField
  • CharField
  • CommaSeparatedIntegerField
  • DateField
  • DateTimeField
  • DecimalField
  • DurationField(New in Django1.8)
  • EmailField
  • FileField
  • FilePathField
  • FloatField
  • ImageField
  • IntegerField
  • IPAddressField
  • GenericIPAddressField
  • NullBooleanField
  • PositiveIntegerField(0 ~ 2147483647<2^32-1>)
  • PositiveSmallIntegerField(0 ~ 32767<2^8-1>)
  • SlugField
  • SmallIntegerField
  • TextField
  • TimeField
  • URLField
  • UUIDField(New in Django1.8)

关系型字段

  • ForeignKey
  • ManyToManyField
  • OneToOneField

字段选项

每个字段都有特殊的属性
大多数都有max_length
下面是一些常用的属性,默认都是false

  • null 把空值’’储存为null
  • blank 允许储存空值’’,与null不同,null是数据库关联,blank是校验关联
  • choice 先定义一个可迭代的二元组T 然后choice=T 会显示选项框
  • default 设置默认值
  • help_text 备注
  • primary_key 主键 不设置是默认添加id的
  • unique 唯一

自增主键字段

默认情况下会加id = models.AutoField(primary_key=True)

如果你想指定一个自定义主键字段,只要在某个字段上指定 primary_key=True 即可。 你自定义了 Field.primary_key,就不会自动添加 id 列。

字段详述名

first_name = models.CharField(“person’s first name”, max_length=30)

详述名是Person’s First Name
不加详述名就是first_name

关系型字段要在后面加verbose_name=”abc”, 不用刻意设置大小写, Django会自动大写首字母

关系

ForeignKey 一对多

from django.db import models

class Manufacturer(models.Model):
    # ...
    pass

class Car(models.Model):
    manufacturer = models.ForeignKey(Manufacturer)
    # ...

一个生产商Manufacturer 可以生产多个Car,但是每一辆Car 却只能有一个Manufacturer
类似这样的例子就用ForeignKey
还有一种递归的关系关联,自己关联自己
models.ForeignKey(‘self’)

ManyToManyField 多对多

需要定义中介model

OneToOneField 一对一

字段命名限制

  1. 不能使用python的保留字
  2. 不能使用超过1个下划线,因为这样会影响Django 的查询
    可以使用sql的保留字 例如select where join

可以自定义模型字段

元选择

metadata 是除了默认字段外的所有选择,例如排序选择

以下是所有可用的元选择

  • abstract = True 将不会在数据库中创建表 只有当其他class继承这个abstract base class的时候才会创建
  • app_label = ‘myapp’ 如果一个模型存在在规定位置之外,那么这个模型必须定义属于哪个app
  • db_table = ‘tablename’ 重命名数据表的名称 默认名称是appname_classname
  • db_tablespace 只支持PostgreSQL Oracle, 不支持SQLite MySQL
  • default_related_name
  • get_latest_by 定义了它就不能用get(), earliest() and latest()来筛选
  • managed
  • order_with_respect_to
  • ordering
  • permissions permissions = ((“can_deliver_pizzas”, “Can deliver pizzas”),)
  • default_permissions 设置为空表示不需要默认的(‘add’, ‘change’, ‘delete’)任何权限
  • proxy = True 多表继承的时候使用 如果你要给父模型定义一个新的方法 又不想修改父模型的话
  • select_on_save Django1.6 之前
  • unique_together
  • index_together
  • verbose_name 人类可读的对象命名 如果不写CamelCase -> camel case
  • verbose_name_plural 复数命名 如果不写就是verbose_name + ‘s’

model属性

最重要的属性是models.Manager() 给管理员命名

Manager只能通过模型类使用,不能通过实例化

model方法

  • 自定义的方法是给你的对象增加一个行级别的功能,然而Manager方法是表范围的。
    model是一个很有价值的技术,它将业务逻辑聚集在一个地方

  • str()

  • get_absolute_url()

  • 重写预定义的模型方法

    执行自定义的 SQL
    如果django自带的model query APIs 不够用的话 可以自定义raw query

model继承

Django中有三种继承方式:

  1. 通常情况下,你只需要使用父类来保存你不希望在每子模型显示的信息,
    想让这个类不被单独的使用的话,请用Abstract base classes(抽象基准类 abstract = True)。

  2. 如果你想继承现有模型(也许是完全从另一个app继承),
    并希望每个模型都有自己的数据库表,请用Multi-table inheritance(多表继承)

  3. 最后,如果你只是想修改模型的Python级行为,不以任何方式改变模型字段,您可以使用代理模式。
    (proxy = True)。

Abstract base classes 抽象基类

meta继承

继承自抽象基类的子类,需要定义meta继承,然后重命名表(db_table)

注意related_name

举例说明app common/models.py:

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

另外一个app rare/models.py:

from common.models import Base

class ChildB(Base):
    pass
是否定义related_name的情况下各种字段字段名 不定义related_name 定义related_name
common.ChildA.m2m childa_set common_childa_related
common.ChildA.m2m childb_set common_childb_related
rare.ChildB.m2m childb_set rare_childb_related

Multi-table inheritance 多表继承

事实上就是OneToOneField

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)

Restaurant继承自Place,Place下所有的字段都存在于Restaurant中

Meta and multi-table inheritance

在multi-table inheritance情况下,子类继承父类的meta类是没有意义的,
所有的meta选择都在父类中应用了,再次应用它们通常只会导致矛盾的行为

在少数限制条件下的子类继承父类的行为:
如果子类没有指定一个ordering属性或者get_latest_by属性,那么他将继承父类的这个属性
如果父类有个ordering属性,而你希望子类用自然的方式排序,可以明确的禁用它

class ChildModel(ParentModel):
    # ...
    class Meta:
        # Remove parent's ordering effect
        ordering = []
Inheritance and reverse relations

如果要在父类的子类中使用这个方法,你必须在每一个字段中都指定related_name属性

class Supplier(Place):
    customers = models.ManyToManyField(Place, related_name='provider')

多表继承中,Django会自动给non-abstract父类模型的子类加上OneToOneField
如果你想创建属于自己的OneToOneField
那么就设置 parent_link=True 来表明你的字段是连接到父类的

Proxy models 代理模型

给原始模型创建一个代理,你就可以增加、删除、修改代理模型的实例,所有的数据都会被储存

不同的是你可以在代理模型中改变默认模型的排序方式或者管理员,而不必修改原始模型

代理模型必须继承自单一的非抽象模型类,不能继承多个非抽象模型

也能继承任意个抽象模型类,假如他们没有定义任何模型字段

Proxy model managers

如果你没有在代理模型中指定任何管理员,他会从父类继承管理员。
如果你在代理模型中定义了管理员,他会成为默认的,尽管父类中定义的管理员也是有效的

Multiple inheritance

继承自父类的子类,字段名不能与父类的字段名一样