98django_model2

发布时间:2020-08-02 14:02:11 作者:chaijowin
来源:网络 阅读:238

 

目录

queries... 1

exclude()... 3

关联对象查询:... 3

反向查询对<field-name>_set改名:... 4

复杂查询:... 4

保存ForeignKeyManyToMany字段:... 5

QuerySet链式过滤:... 5

lookup,高级条件过滤:... 5

跨关联关系查询:... 6

限制返回个数:... 6

查询对象比较... 7

不常用查询API... 7

事务:... 10

自定义管理器:... 11

 

 

 

queries

 

user.groups.set(groups)

user.groups.all()

group.user_set.all()   #反查会加上_set

 

Author.objects.exclude(name='jowin')

 

Entry.objects.get(id=1).blog   #一对多,前向查询,通过属性访问关联的(外部)对象

Blog.objects.get(id=1).entry_set.all()   #一对多,反向查询,模型中有fk,该fk所指的模型实例可通过一个管理器返回前一个模型的所有实例,默认这个管理器的名字是<field-name>_set<field-name>是源模型的小写名称,该管理器返回的查询集可用getfilterexclude再次操作;如CourseLessonLesson中的course = models.ForeignKey(Course, verbose_name='课程'),在Course中可定义方法def get_lesson(self): return self.lesson_set.all()

 

 

例:

class Group(models.Model):

    name = models.CharField(max_length=20)

 

    def __str__(self):

        return self.name

 

class User(models.Model):

    name = models.CharField(max_length=20)

    groups = models.ManyToManyField(Group)   #ManyToMany会自动生成中间表publish_user_groups

 

    def __str__(self):

        return self.name

 

>>> from publish.models import Group,User

>>> user = User.objects.create(name='jowin')

>>> group1 = Group.objects.create(name='magedu1')

>>> group2 = Group.objects.create(name='magedu2')

>>> user = User.objects.first()

>>> groups = Group.objects.all()

>>> type(groups)

<class 'django.db.models.query.QuerySet'>

>>> user.groups.set(groups)   #将用户为'jowin'加入多个组里

>>> user.groups.all()

<QuerySet [<Group: magedu1>, <Group: magedu2>]>

>>> group = Group.objects.get(id=1)

>>> group.user_set.all()   #反查会加上_set

<QuerySet [<User: jowin>]>

 

 

例,多对多,自己加中间表:

class Group(models.Model):

    name = models.CharField(max_length=20)

 

    def __str__(self):

        return self.name

 

class User(models.Model):

    name = models.CharField(max_length=20)

    # groups = models.ManyToManyField(Group)

 

    def __str__(self):

        return self.name

 

class UserGroupRelation(models.Model):   #多对多,自己加中间表

    user = models.ForeignKey(User)

    group = models.ForeignKey(Group)

 

sqlite> .schema publish_usergrouprelation

CREATE TABLE IF NOT EXISTS "publish_usergrouprelation" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "group_id" integer NOT NULL REFERENCES "publish_group

" ("id"), "user_id" integer NOT NULL REFERENCES "publish_user" ("id"));

CREATE INDEX "publish_usergrouprelation_group_id_e393f98c" ON "publish_usergrouprelation" ("group_id");

CREATE INDEX "publish_usergrouprelation_user_id_0e041f81" ON "publish_usergrouprelation" ("user_id");

sqlite> .schema publish_group

CREATE TABLE IF NOT EXISTS "publish_group" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(20) NOT NULL);

sqlite> .schema publish_user

CREATE TABLE IF NOT EXISTS "publish_user" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(20) NOT NULL);

 

 

例:

class Blog(models.Model):

    name = models.CharField(max_length=100)

    tagline = models.TextField()

 

    def __str__(self):

        return self.name

 

class Author(models.Model):

    name = models.CharField(max_length=50)

    email = models.EmailField()

 

    def __str__(self):

        return self.name

 

class Entry(models.Model):

    blog = models.ForeignKey(Blog)

    headline = models.CharField(max_length=255)

    body_text = models.TextField()

    pub_date = models.DateField()

    authors = models.ManyToManyField(Author)

    n_comments = models.IntegerField()

    n_pingbacks = models.IntegerField()

    rating = models.IntegerField()

 

    def __str__(self):

        return self.headline

 

例:

 

 

exclude()

filter相反:

>>> b = Blog(name='beatles blog', tagline='all the latest beatles news')

>>> b.save()

>>> a1 = Author.objects.create(name='jowin',email='jowin@ane56.com')

>>> a2 = Author.objects.create(name='mage',email='mage@ane56.com')

>>> Author.objects.exclude(name='jowin')

<QuerySet [<Author: mage>]>

 

 

关联对象查询:

>>> e = Entry(blog=Blog.objects.get(id=1),headline='test',body_text='test',pub_date=timezone.now(),n_comments=20,n_pingbacks=50,rating=100)

>>> e.save()

>>> e = Entry.objects.get(id=1)

>>> e.blog   #一对多,前向查询,通过属性访问关联的(外部)对象

<Blog: beatles blog>

>>> e.authors.set(Author.objects.all())

>>> e.authors.all()

<QuerySet [<Author: jowin>, <Author: mage>, <Author: jowin>]>

 

>>> b = Blog.objects.get(id=1)

>>> b.entry_set.all()   #一对多,反向查询,模型中有fk,该fk所指的模型实例可通过一个管理器返回前一个模型的所有实例,默认这个管理器的名字是<field-name>_set<field-name>是源模型的小写名称,该管理器返回的查询集可用getfilterexclude再次操作

<QuerySet [<Entry: test>]>

>>> b.entry_set.filter(headline__contains='test')

<QuerySet [<Entry: test>]>

>>> b.entry_set.count()

1

 

 

反向查询对<field-name>_set改名:

class Entry(models.Model):

         blog = models.ForeignKey(Blog, related_name='entries')

使用时用entries_set

 

 

复杂查询:

filter中的关键字参数默认是AND的关系;

若用OR的关系,得用Q对象(from django.db.models import Q),Q对象用于封装一组关键字参数;

查询函数getfilterexclude中可混合使用Q对象和关键字参数,所有提供给查询函数的参数都将AND在一起,注意Q对象要在关键字参数前,如Poll.objects.get(Q(question__startswith='who'),Q(pub_date=date(2019,1,8)|Q(pub_date=date(2019,1,2))Poll.objects.get(Q()|Q(),question__startswith='who')

推荐用符号&|

>>> from django.db.models import Q

>>> Author.objects.filter(Q(name='jowin')|Q(name='mage'))

<QuerySet [<Author: jowin>, <Author: mage>, <Author: jowin>]>

 

 

保存ForeignKeyManyToMany字段:

>>> e = Entry.objects.create(blog=b,headline='test2',body_text='test2',pub_date=timezone.now(),n_comments=30,n_pingbacks=60,rating=90)

>>> e.blog

<Blog: test2>

>>> e.blog = b

>>> a3 = Author.objects.create(name='mage2',email='mage2@magedu.com')

>>> a4 = Author.objects.create(name='jowin2',email='jowin2@magedu.com')

>>> e.authors = [a3]

>>> e.save()

>>> e.authors.add(a3,a4)   #e.authors.set([])清空

>>> e.save()

>>> e.authors.create(name='mage3',email='mage3@magedu.com')   #查询创建fkvalue

<Author: mage3>

 

 

QuerySet链式过滤:

Entry.objects.filter(headline__startswith='what').exclude(pub_date__gte=datetime.date.today()).filter(pub_date__gte=datetime(2019,1,8))

 

 

lookup,高级条件过滤:

使用<field-name>__lookup,使用双下划线来查询;

gtgteltlte

contains   #包含

exact   #精确匹配,默认

startswith   #开始于

endswith   #结束于

regex    #RE

icontainsiexactistartswithiendwithiregex   #忽略大小写

in   #在列表中

range   #范围之内

dateyearmonthday   #时间日期类型

 

>>> Entry.objects.filter(pub_date__gt='2018-12-31')

<QuerySet [<Entry: test>, <Entry: test2>]>

>>> Blog.objects.get(name__iexact='beatles blog')

<Blog: beatles blog>

>>> Blog.objects.filter(pk__in=[0,2,4])

<QuerySet [<Blog: test2>]>

>>> Entry.objects.filter(pub_date__range=(datetime.date(2018,12,31),datetime.date(2019,1,9)))

<QuerySet [<Entry: test>, <Entry: test2>]>

>>> Entry.objects.get(body_text__regex=r'^test2')   #

<Entry: test2>

 

 

跨关联关系查询:

>>> Entry.objects.filter(blog__name='beatles blog')

<QuerySet [<Entry: test>]>

>>> Blog.objects.filter(entry__headline__contains='test')   #反向

<QuerySet [<Blog: beatles blog>, <Blog: test2>]>

>>> Blog.objects.filter(entry__authors__name__isnull=True)   #多层

<QuerySet []>

>>> Blog.objects.filter(entry__authors__isnull=False,entry__authors__name__isnull=True)   #多个过滤条件

<QuerySet []>

 

>>> from django.db.models import F   #模型字段查询F,通常是将模型字段与常量比较,或比较2个字段值

>>> Entry.objects.filter(n_pingbacks__gt=F('n_comments'))   #点赞数大于评论数

<QuerySet [<Entry: test>, <Entry: test2>]>

>>> Entry.objects.filter(rating__gt=F('n_comments') + F('n_pingbacks'))

<QuerySet [<Entry: test>]>

 

 

限制返回个数:

>>> Entry.objects.all()[:3]   #limit 5

<QuerySet [<Entry: test>, <Entry: test2>]>

>>> Entry.objects.all()[1:2]   #offset 1 limit 1

<QuerySet [<Entry: test2>]>

 

 

查询对象比较,用==,在后台比较的是2个模型主键的值:

some_entry == other_entry   #some_entry.id == other_entry.id

 

 

不常用查询API

https://docs.djangoproject.com/en/2.1/ref/models/querysets/

 

annotate()

添加注释属性,与聚合函数一起使用,返回聚合值;

>>> from blog.models import Blog,Author,Entry

>>> from django.db.models import Count

>>> q = Blog.objects.annotate(Count('entry'))

>>> q

<QuerySet [<Blog: beatles blog>, <Blog: test2>]>

>>> q[0].name

'beatles blog'

>>> q[0].entry__count

1

>>> qs = Blog.objects.annotate(entry_num=Count('entry'))

>>> for q in qs:

...     print(q.entry_num)

...

1

1

 

 

aggregate()

聚合函数,返回是字典;

>>> qs = Blog.objects.aggregate(Count('entry'))

>>> qs

{'entry__count': 2}

>>> qs = Blog.objects.aggregate(entry_num=Count('entry'))

>>> qs

{'entry_num': 2}

 

 

聚合类函数:

from django.db.models import Avg,Count,Max,Min,StdDev(标准除),Sum,Variance(方差)

聚合类函数配合聚合函数aggregate()或注释函数annotate()使用;

 

 

distinct()

去重;

>>> Author.objects.distinct()

<QuerySet [<Author: jowin>, <Author: mage>, <Author: jowin>, <Author: mage2>, <Author: jowin2>, <Author: mage3>]>

>>> Entry.objects.order_by('blog')

<QuerySet [<Entry: test>, <Entry: test2>]>

>>> Entry.objects.order_by('pub_date')

<QuerySet [<Entry: test>, <Entry: test2>]>

 

 

values()

返回是字典(列表套字典),而不是模型实例对象;

>>> Blog.objects.filter(name__startswith='beatles')

<QuerySet [<Blog: beatles blog>]>

>>> Blog.objects.filter(name__startswith='beatles').values()

<QuerySet [{'name': 'beatles blog', 'id': 1, 'tagline': 'all the latest beatles news'}]>

>>> Blog.objects.values()

<QuerySet [{'name': 'beatles blog', 'id': 1, 'tagline': 'all the latest beatles news'}, {'name': 'test2', 'id': 2, 'tagline': 'test2'}]>

>>> Blog.objects.values('id','name')   #可指定显示某些字段

<QuerySet [{'name': 'beatles blog', 'id': 1}, {'name': 'test2', 'id': 2}]>

 

 

values_list()

返回列表套元组;

>>> Entry.objects.values_list('id')

<QuerySet [(1,), (2,)]>

>>> Entry.objects.values_list('id').order_by('id')

<QuerySet [(1,), (2,)]>

>>> Entry.objects.values_list('id',flat=True)   #可指定显示某些字段;flat扁平,若元组中仅1个元素用flat会将元组脱掉,结果为列表

<QuerySet [1, 2]>

>>> Entry.objects.values_list('id',flat=True).order_by('id')

<QuerySet [1, 2]>

 

 

defer()only()

若模型包含一些含有大量数据的类型,通常模型会将数据库取出的数据转换为py对象,有时可不需要浪费这样的性能,用defer排队、only仅转换指定的(将指定的字段转为可用属性方式访问);

>>> Entry.objects.defer('headline')

<QuerySet [<Entry: test>, <Entry: test2>]>

>>> Entry.objects.only('headline')

<QuerySet [<Entry: test>, <Entry: test2>]>

 

 

using()

使用哪个数据库;

在一主多从情况下,将查询指定到从库上,在settings.py中配;

DATABASES = {

    'default': {

        'ENGINE': 'django.db.backends.sqlite3',

        'NAME': os.path.join(BASE_DIR, 'db0.sqlite3'),

    },

    'backup': {...},

}

>>> Entry.objects.all()

<QuerySet [<Entry: test>, <Entry: test2>]>

>>> Entry.objects.using('default')   #Entry.objects.using('backup')

<QuerySet [<Entry: test>, <Entry: test2>]>

 

 

select_for_update()

返回一个queryset,会锁定相关行直到事务结束,在支持的数据库上产生一个select ... for update语句;

>>> Entry.objects.select_for_update().filter(authors=Author.objects.get(id=1))

<QuerySet [<Entry: test>]>

 

 

raw()

执行原始sql

>>> for s in Blog.objects.raw('select * from blog_blog'):

...     print(s)

...

beatles blog

test2

 

 

get_or_create()update_or_create()

能查到,返回;查不到,创建;

obj, created = Person.objects.get_or_create(

         first_name='John',

         last_name='Lennon',

         defaults={'birthday':date(2019,1,8)},

)

等价于

try:

         obj = Person.objects.get(first_name='John', last_name='Lennon')

except Person.DoesNotExist:

         obj = Person(first_name='John',last_name='Lennon',birthday=date(2019,1,8))

         obj.save()

 

 

bulk_create()

批量创建;

>>> Blog.objects.bulk_create([Blog(name='test3',tagline='test3'),Blog(name='test4',tagline='test4')])

[<Blog: test3>, <Blog: test4>]

 

 

in_bulk()

将主键封装成列表,返回指定主键的记录;

>>> Blog.objects.in_bulk([3,4])

{3: <Blog: test3>, 4: <Blog: test4>}

>>> Blog.objects.in_bulk([1,3])

{1: <Blog: beatles blog>, 3: <Blog: test3>}

 

 

latest()earliestfirst()last()

>>> Entry.objects.latest('pub_date')

<Entry: test>

>>> Entry.objects.earliest('pub_date')

<Entry: test>

 

 

get_lastest_by()经常用,在Meta中指定;

 

 

事务:

事务是在view中实现,在函数执行完后才统一commit,默认是autocommit

例:

from django.db import transaction

 

@transaction.atomic

def my_view(request):

    do_stuff()

   

@transaction.atomic

def viewfunc(request):

    do_stuff()

 

 

 

自定义管理器:

 

1、添加额外管理器,是为类增加“表级”功能的首选方式,可返回你想要的任何数据,而不是返回一个查询集;

如果要添加行级功能,如只对某个模型的实例起作用,应使用模型方法,而不是管理器方法;

 

 

 

2、添加自定义管理器:

from django.utils.translation import ugettext as _

 

class AuthorManager(models.Manager):

    def get_queryset(self):

        return super(AuthorManager, self).get_queryset().filter(role='A')

 

class EditorManager(models.Model):

    def get_queryset(self):

        return super(EditorManager, self).get_queryset().filter(role='E')

 

class Person(models.Model):

    first_name = models.CharField(max_length=50)

    last_name = models.CharField(max_length=50)

    role = models.CharField(max_length=1, choices=(('A', _('Author'), ('E',_('Editor')))))

    people = models.Manager()

    authors = AuthorManager()

    editors = EditorManager()

 

 

 

 

 

 


推荐阅读:
  1. python中函数与全局变量的常见问题和解决方法
  2. python中的元类是什么?怎么用?

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

python django model

上一篇:oracle 归并

下一篇:Windows利用Swarm原生Docker集群踩坑总结

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》