模型基础知识

字段选项

null和blank区别:

null指的是数据库范畴,字段是否允许为空,blank则是表单数据输入验证范畴,如果为true表示表单验证允许输入一个空值。

 

模型中的外键关系

 

one to one relationships

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

    def __str__(self):
        return self.name


class Restaurant(models.Model):
    place = models.OneToOneField(Place, primary_key=True)
    serves_hot_dogs = models.BooleanField(default=False)
    serves_pizza = models.BooleanField(default=False)

    def __str__(self):
        return '%s the restaurant ' % self.place.name

地方和饭馆是一对一的关系

p1 = Place(name='北京', address='西城区55号')
p1.save()
p2 = Place(name='上海', address='西北街道22')
p2.save()
r = Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False)
r.save()

从饭馆对象访问地方,从地方访问饭馆

r.place
<Place: 北京>
p1.restaurant
<Restaurant: 北京 the restaurant >

p2 没有设置相关的餐厅,使用hasattr 来避免异常

hasattr(p2, 'restaurant')
False

通过地方得到饭馆

Restaurant.objects.get(place__pk=1)
<Restaurant: 北京 the restaurant 

通过饭馆的属性帅选得到地方

Place.objects.filter(restaurant__place__name__icontains='北')
<QuerySet [<Place: 北京>, <Place: 北京>, <Place: 北京>]>

 

many to many

 

class Publication(models.Model):
    title = models.CharField(max_length=30)

    def __str__(self):  # __unicode__ on Python 2
        return self.title

    class Meta:
        ordering = ('title',)


class Article(models.Model):
    headline = models.CharField(max_length=100)
    publications = models.ManyToManyField(Publication)

    def __str__(self):  # __unicode__ on Python 2
        return self.headline

    class Meta:
        ordering = ('headline',)

创建添加实例

p1 = Publication(title='The Python Journal')
p1.save()
p2 = Publication(title='Science News')
p2.save()
p3 = Publication(title='Science Weekly')
p3.save()

创建article

a1 = Article(headline='Django lets you build Web apps easily')
a1.save()  # 必须要保存之后才能添加

创建并将publications添加到article

a1.publications.add(p1)
new_pub = a1.publications.create(title='hahahah')

m2m可以互相访问

a1.publications.all()
<QuerySet [<Publication: hahahah>, <Publication: The Python Journal>]>
p1.article_set.all()
<QuerySet [<Article: Django lets you build Web apps easily>]>
Article.objects.filter(publications__title__icontains='he')
<QuerySet [<Article: Django lets you build Web apps easily>]>
# 支持反向m2m查询(即,从不具有ManyToManyField的表开始
Publication.objects.filter(article__in=[1,2])
<QuerySet [<Publication: hahahah>, <Publication: The Python Journal>]>

从Article中删除Publication:

a1.publications.remove(p1)

从Publication删除Article:

p1.article_set.remove(a1)


分配关系集,分配清除现有集成员:

a1.publications=[p1]
a1.publications=[]  # 分配空集,全部清除
a1.publications.all()
[]

清除关系集:

p2.article_set.all()
<QuerySet [<Article: Django lets you build Web apps easily>]>
p2.article_set.clear()
p2.article_set.all()
<QuerySet []>
a1.publications.all()
<QuerySet [<Publication: hahahah>, <Publication: Science Weekly>]>
a1.publications.clear()
a1.publications.all()
<QuerySet []>

批量清除:

>>> q = Article.objects.filter(headline__startswith='Django')
>>> print(q)
[<Article: Django lets you build Web apps easily>]
>>> q.delete()

在delete后需要清除QuerySet 缓存,并且引用的对象应该消失:

q = Article.objects.filter(headline__startswith='Django')
q
<QuerySet [<Article: Django lets you build Web apps easily>]>
q.delete()
(1, {'demo1.Article_publications': 0, 'demo1.Article': 1})
q
<QuerySet []>
q=None

多对多的中介模型 

http://usyiyi.cn/translate/django_182/topics/db/models.html

 

重写预定义模型方法

 

封装数据库行为的模型方法,自定义经常改变save() 和delete() 的工作方式。

在将博客保存到数据库之前对摘要进行处理

def save(self, *args, **kwargs):
    # 如果没有填写摘要
    if not self.excerpt:
        # 首先实例化一个 Markdown 类,用于渲染 body 的文本
        md = markdown.Markdown(extensions=[
            'markdown.extensions.extra',
            'markdown.extensions.codehilite',
        ])
        # 先将 Markdown 文本渲染成 HTML 文本
        # strip_tags 去掉 HTML 文本的全部 HTML 标签
        # 从文本摘取前 54 个字符赋给 excerpt
        self.excerpt = strip_tags(md.convert(self.content))[:54]

    # 调用父类的 save 方法将数据保存到数据库中
    super(Article, self).save(*args, **kwargs)

注意,当使用查询集批量删除对象时,将不会为每个对象调用delete() 方法。为确保自定义的删除逻辑得到执行,你可以使用pre_delete 和/或post_delete 信号。

 

模型继承

 

1.抽象基类继承

from django.db import models

class CommonInfo(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField()

    class Meta:
        abstract = True

class Student(CommonInfo):
    home_group = models.CharField(max_length=5)

Student有三个字段,name, age, home_group. CommonInfo既不能创建表,也不能实例化或者存储

元继承

子类没有自己的Meta类会继承父类的meta

class CommonInfo(models.Model):
    # ...
    class Meta:
        abstract = True
        ordering = ['name']

class Student(CommonInfo):
    # ...
    class Meta(CommonInfo.Meta):
        db_table = 'student_info'

一些属性被包含在抽象基类的Meta类里面是没有意义的。如db_table属性意味着所有子类用同一张表,是没有意义的。

在继承了抽象基类时,有使用了related_name属性时,需要注意继承传递

http://usyiyi.cn/translate/django_182/topics/db/models.html

2.多表继承

使用这种方式继承同普通的python对象继承相似,父模型和子模型都是可以查询创建表。父类和子类隐式的添加一个链接(自动创建 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)

Place里面的所有字段在 Restaurant中也是有效的,只不过没有保存在数据库中的Restaurant表中

>>> Place.objects.filter(name="Bob's Cafe")
>>> Restaurant.objects.filter(name="Bob's Cafe")
>>> p = Place.objects.get(id=12)
# If p is a Restaurant object, this will give the child class:
>>> p.restaurant
<Restaurant: ...>

多表继承中的meta

子 model 并不能访问它父类的 Meta 类。但是在某些受限的情况下,子类可以从父类继承某些 Meta :如果子类没有指定 ordering属性或 get_latest_by 属性,它就会从父类中继承这些属性

父类有了排序设置,而你并不想让子类有任何排序设置,你就可以显式地禁用排序

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

多表继承反向关联

如果哦与父类的另外一个子类做多对一或者多对多必须指明related_name, 否则报错

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

指定链接父类的字段

默认隐式创建 OneToOneField字段将子类链接至非抽象的父 model

创建自己的 OneToOneField字段并设置 parent_link=True ,从而使用该字段链接父类。

 

3.代理继承

为原始模型创建一个代理 。你可以创建,删除,更新代理 model 的实例,而且所有的数据都可以像使用原始 model 一样被保存。 不同之处在于:你可以在代理 model 中改变默认的排序设置和默认的 manager ,更不会对原始 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 = True

    def do_something(self):
        # ...
        pass

MyPerson类和它的父类 Person 操作同一个数据表。特别的是,Person 的任何实例也可以通过 MyPerson访问,反之亦然:

>>> p = Person.objects.create(first_name="foobar")
>>> MyPerson.objects.get(first_name="foobar")
<MyPerson: foobar>

使用代理 model 给 model 定义不同的默认排序设置。 你可能并不想每次都给Person模型排序,但是使用代理的时候总是按照last_name属性排序

class OrderedPerson(Person):
    class Meta:
        ordering = ["last_name"]
        proxy = True

使用Person查询是无序的,而OrderedPerson 则是按照last_name 排序

基类限制:

代理模型必须继承自一个非抽象基类,可以继承任意个抽象基类,但是没有定义任何model字段

 

转载于:https://my.oschina.net/acutesun/blog/1510551

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值