models进阶

models基本操作

增:
1)创建对象实例,然后调用save方法:
au = Author(first_name='zhang', last_name='san') 
au.save()
2)使用create方法
Author.objects.create(first_name='li', last_name='si')
删:
使用queryset的delete方法:
# 删除指定条件的数据
Author.objects.filter(first_name='zhang').delete()
# 删除所有数据
Author.objects.all().delete() 
objects不能直接调用delete方法。
使用模型对象的delete方法:
a = Author.objects.get(id=5)
a.delete()
改:
Author.objects.filter(last_name='dfdf').update(last_name='san')
模型没有定义update方法,直接给字段赋值,并调用save,能实现update的功能,比如:
>>> a = Author.objects.get(id=3)
>>> a.first_name = 'zhang'
>>> a.save()
save更新时会更新所有字段。如果只想更新某个字段,减少数据库操作,可以这么做:
a.first_name = 'li'
a.save(update_fields=['first_name'])
注意:更新操作不能更新关联表的属性,比如下面的语句是不起作用的。
Author.objects.update(book__title='b')
查:
返回queryset:
all: Book.objects.all()
filter: Book.objects.filter(id__gt=1)
exclude: Book.objects.exclude(id__exact=1)
order_by: Book.objects.all().order_by('-id')
values: Book.objects.all().values('title')
返回单个对象:
get : Book.objects.get(id=1)
count: Book.objects.all().count()
first: Book.objects.all().first()
last: Book.objects.all().last()
exists: Book.objects.all().exists()

Model连表结构

ORM核心知识回顾:
django根据代码中定义的类来自动生成数据库表。
我们写的类表示数据库的表。
根据这个类创建的对象是数据库表里的一行数据。
对象.id 对象.value 是每一行里的数据

一对多:models.ForeignKey(其他表)
多对多:models.ManyToManyField(其他表)
一对一:models.OneToOneField(其他表)
应用场景:
一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)
例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。
多对多:在某表中创建一行数据时,有一个可以多选的下拉框。
例如:创建用户信息,需要为用户指定多个爱好。
一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了)
例如:有个身份证表,有个person表。每个人只能有一张身份证,一张身份证也只能对应一个人,这就是一对一关系。

1.1 一对多关系,即外键

为什么要用一对多。先来看一个例子。有一个用户信息表,其中有个用户类型字段,存储用户的用户类型。如下:
class UserInfo(models.Model):
    username = models.CharField(max_length=32)
    age = models.IntegerField()
user_type = models.CharField(max_length=10)
不使用外键时用户类型存储在每一行数据中。如使用外键则只需要存储关联表的id即可,能够节省大量的存储空间。同时使用外键有利于维持数据完整性和一致性。
当然也有缺点,数据库设计变的更复杂了。每次做DELETE 或者UPDATE都必须考虑外键约束。
刚才的例子使用外键的情况:单独定义一个用户类型表:
class UserType(models.Model):
    caption = models.CharField(max_length=32)

class UserInfo(models.Model):
    user_type = models.ForeignKey('UserType')
    username = models.CharField(max_length=32)
    age = models.IntegerField()
我们约定:
ForeignKey在UserInfo表里,如果根据UserInfo去操作就是正向操作。
ForeignKey不在UserType里,如果根据UserType去操作就是反向操作。
一对多的关系的增删改查:
正向:增
1)使用create直接创建userinfo对象,django自动给外键关系加上了一个user_type_id字段。
dic = {'username':'zhangsan','age':18,'user_type_id':3}
UserInfo.objects.create(**dic)
2)通过对象添加
usertype = UserType.objects.filter(id=2)[0]
UserInfo.objects.create(username='shuaige',age=18,user_type=usertype)
正向:删 和普通模式一样删除即可。如:
UserInfo.objects.filter(id=1).delete()

正向:改  和普通模式一样修改即可。如:
UserInfo.objects.filter(id=2).update(user_type_id=4)
正向:查
正向查找所有用户类型为钻石用户的用户,使用双下划线:
users = UserInfo.objects.filter(user_type__caption='钻石用户')
注意:获取属性值用点,比如获取users列表第一个用户的用户类型,应该这么写:
users[0].user_type.caption
反向:增 通过usertype来创建userinfo
1)通过userinfo_set的create方法
#获取usertype实例
ut = UserType.objects.get(id=2)
#创建userinfo对象
ut.userinfo_set.create(username='smith',age=33)
2)通过userinfo_set的add方法
michael = UserInfo(username='michael', age=13)
michael.save()
ut.userinfo_set.add(michael)


反向:删 
删除操作可以在定义外键关系的时候,通过on_delete参数来配置删除时做的操作。
on_delete参数主要有以下几个可选值:
models.CASCADE 默认值,表示级联删除,即删除UserType时,相关联的UserInfo也会被删除。
models.PROTECT 保护模式, 阻止删除操作。
models.SET_NULL 置空模式   设为null,null=True参数必须具备
models.SET_DEFAULT 置默认值 设为默认值,default参数必须具备
models.SET() 删除的时候重新动态指向一个实体访问对应元素 ,可传函数
models.DO_NOTHING   什么也不做。
注意修改on_delete参数之后需要重新同步数据库,如果使用python manage.py shell进行models操作,需要退出shell重新进入。
反向:改 和普通模式一样,不会影响级联表。
反向:查 
obj=UserType.objects.get(id=1)
通过这个对象来查用户类型为1的用户有多少
obj.userinfo_set.all() 
可以通过在定义foreignkey时指定related_name来修改默认的userinfo_set,比如指定related_name为info
user_type = models.ForeignKey('UserType',related_name='info')
指定related_name之后,反向查的时候就变成了:
obj.info.all()
获取用户类型为1且用户名为shuaige的用户
obj.info.filter(username='shuaige')
外键关系中,django自动给usertype加了一个叫做userinfo的属性。使用双下划线,可以通过userinfo提供的信息来查usertype
user_type_obj = UserType.objects.get(userinfo__username='shuaige')

1.2 多对多关系

针对多对多关系django会自动创建第三张表。也可以通过through参数指定第三张表。
用户和组是典型的多对多关系:
class UserGroup(models.Model):
    group_name = models.CharField(max_length=20)

    def __str__(self):
        return self.group_name


class User(models.Model):
    username = models.CharField(max_length=64)
    password = models.CharField(max_length=64)
    group = models.ManyToManyField(UserGroup)

    def __str__(self):
        return self.username

把正向操作的related_name认为是group,那么多对多的操作和一对多的操作就一样了。比如:
正向增:
user = User.objects.create(username='abc', password='123')
group = UserGroup.objects.filter(id=1)[0]
user.group.add(group)
反向增:
group.user_set.add(user)
其他操作和一对多类似。

1.3 一对一关系

一对一不是数据库的一个连表操作,而是Django独有的一个连表操作。一对一关系相当于是特殊的一对多关系,只是相当于加了unique=True。
一个人只能有一张身份证,一张身份证对应一个人,是一个典型的一对一关系。
class IdCard(models.Model):
    idnum = models.IntegerField()

    def __str__(self):
        return str(self.idnum)


class Person(models.Model):
    idcard = models.OneToOneField(IdCard)
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name
一对一关系比较简单。两种表互相都有对方。比如:
>>> lisi = Person.objects.get(id=3)
>>> lisi.idcard
<IdCard: 123456>
>>> ids = IdCard.objects.get(id=3)
>>> ids
<IdCard: 456677>
>>> ids.person
<Person: lisi>

2. F和Q

Q查询——对对象的复杂查询
F查询——专门取对象中某列值的操作
F:主要作用
1)和models自身的字段进行对比。比如:
>>> from django.db.models import F
>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks'))
2) 对字段进行数学运算。比如:
>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)

Q:
默认情况下Django的查询只是且操作如下:
models.UserInfo.objects.filter(username='zhangsan',age='18')
找到用户为:zhangsan并且age=18的数据
如果需要执行或操作 ,就需要使用到Q对象了
Q对象可以用& | ~ 去连接
Q(question__startswith='Who') | Q(question__startswith='What')
等于:
WHERE question LIKE 'Who%' OR question LIKE 'What%'
如果Q和关键字参数一起使用的话,Q必须放在关键字参数前面:
Entry.objects.get(Q(question__startswith='Who') | Q(question__startswith='What'),n_comments__gt=30)

3. models的Manager

django通过models的manager来执行数据库操作。
每个django model至少有一个manager。
可以自定义manager。
自定义manager必须继承自models.Manager
给默认的manager改名:
class Person(models.Model):
    #...
    people = models.Manager()
定制manager
1)增加额外的方法:
class BookManager(models.Manager):
    def title_count(self, keyword):
        return self.filter(title__icontains=keyword).count()

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()
    num_pages = models.IntegerField(blank=True, null=True)
    objects = BookManager()

    def __str__(self):
        return self.title

2)修改默认manager的查询集
class DahlBookManager(models.Manager):
    def get_queryset(self):
        return super(DahlBookManager, self).get_queryset().filter(author='Roald Dahl')

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=50)
    # ...

    objects = models.Manager() # The default manager.
    dahl_objects = DahlBookManager() # The Dahl-specific manager.
3)使用多个manager
class MaleManager(models.Manager):
    def get_queryset(self):
        return super(MaleManager, self).get_queryset().filter(sex='M')

class FemaleManager(models.Manager):
    def get_queryset(self):
        return super(FemaleManager, self).get_queryset().filter(sex='F')

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    sex = models.CharField(max_length=1, 
                           choices=(
                                    ('M', 'Male'),  
                                    ('F', 'Female')
                           )
                           )
    people = models.Manager()
    men = MaleManager()
    women = FemaleManager()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值