Django model 层之Making Query总结1

简介: Django model 层之Making Query总结

Django model 层之Making Query总结



 

实践环境

Python版本:python-3.4.0.amd64

下载地址:https://www.python.org/downloads/release/python-340/

 

 

Win7 64位

 

Django  1.11.4

下载地址:https://www.djangoproject.com/download/

 

 

API交互

MySQL数据库为例,假设项目目录结构如下:

mysite/

myapp/

   __init__.py

admin.py

apps.py

migrations/

   __init__.py

models.py

tests.py

views.py

   manage.py

   mysite/

       __init__.py

       settings.py

       urls.py

       wsgi.py

 

 

models.py内容如下:

from django.db import models


# Create your models here.
class Person(models.Model):

  first_name = models.CharField(max_length=30)

  last_name = models.CharField(max_length=30)


class Book(models.Model):

   book_name = models.CharField(max_length=30)

   borrower = models.ForeignKey(Person, to_field='id', on_delete=models.CASCADE)



class Blog(Book):

  author = models.CharField(max_length=50)

 

class Store(models.Model):

   id = models.AutoField(primary_key=True)

   name = models.CharField(max_length=50)

   last_update = models.DateField(auto_now=True)

 

class Fruit(models.Model):

   store = models.ManyToManyField(Store)

   name = models.CharField(max_length=100)

onsale_date = models.DateField()

 

class News(models.Model):

  title = models.CharField(max_length=20)

  n_comments = models.IntegerField()

  n_pingbacks = models.IntegerField()

 

进入到项目根目录下,运行python

cd /d F:\project\Django\MyProjects\mysite\

python

 

 

>>> import os

>>> os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")

'mysite.settings'

>>>

 

说明:

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project_name.settings")

 

添加以上代码避免出现以下问题:

django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing

 

 

>>> import django

>>> django.setup()

 

说明:

添加以上代码,避免出现以下问题

……

raise AppRegistryNotReady("Apps aren't loaded yet.")

django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

 

创建对象

>>> from myapp.models import Person

 

说明:

from app_name.models import module

 

python当前目录为项目根目录下,models位于app目录下,所以如上 app_name.models

 

>>> person = Person(first_name="ke", last_name="shou")

>>> person.save()

 

执行save()方法时,等同于执行以下sql INSERT语句。

INSERT INTO `myapp_person` (`id`, `first_name`, `last_name`) values('1','ke','shou');

 

说明:创建对象时也可以使用字典解引的方式,如下:

>>> fields_dict = {"first_name":"ke", "last_name":"shou"}

>>> person = Person(**fields_dict)

 

 

创建包含外键field的对象

>>> from myapp.models import Person,Book

 

方式1:创建对象时,外键Field名称要写为“外键Field名称_id”的形式

>>> book1 = Book(borrower_id='1', book_name='mybook')

>>> book1.save()

 

 

注意:如果,外键Field名称直接使用所在模块类中的定义的类属性名称,直接设置值为外键Field的值,则会提示外键Field的值必须为外键Field所关联类的实例,如下:

>>> book1 = Book(borrower='1', book_name='mybook')

……

   self.field.remote_field.model._meta.object_name,

ValueError: Cannot assign "'1'": "Book.borrower" must be a "Person" instance.

 

方式2:解决以上依赖问题

>>> person2 = Person(first_name="ku", last_name="shou")

>>> person2.save()

>>> book2 = Book(borrower=person2, book_name='mybook2')

>>> book2.save()

 

 

创建包含多对多Field的对象

 

针对多对多Field,除了建立model对应的表外,django还会新增一张关联表:app名称_包含ManyToManyField类型Field的model名称_ManyToManyField类型Field指定的model名称(例中myapp_fruit_store),存放两个model对应的表对应记录的id

 

>>> from myapp.models import Store,Fruit

>>> amy_store = Store.objects.create(name='aimi')

 

SELECT * FROM `myapp_store` WHERE `name` = 'aimi';

显示:

id   name   last_update

7    aimi   2018-03-25

 

说明:以create方式建立对象,无需执行obj.save()函数就会在表新增对应的记录,如上,如果添加,amy_store.save()代码,则会在此基础上,再新增一条记录。内容和amy_store对象的一样。

 

 

 

注意:针对多对多,不能按以下方式创建对象,会报错:

>>> apple = Fruit(name='apple',onsale_date='2018-03-24')

>>> apple.save()

 

SELECT * FROM `myapp_fruit` WHERE `name` = 'apple';

显示:

id    name    onsale_date

3     apple   2018-03-24

 

注意:调用add之前,必须保证对象自身已存在,即已创建,否则会报类似如下的错误:

ValueError: "<Fruit: Fruit object>" needs to have a value for field "id" before this many-to-many relationship can be used.

 

由此可见,我们不能通过类似以下语句,一次性创建包含ManyToManyField类型Field的对象

banana = Fruit(store=aimi_store,name='banana',

onsale_date='2018-03-24')

banana.save()

 

到目前为止,关联表myapp_fruit_store里还是没有记录

>>> apple.add(aimi_store)

 

SELECT * FROM `myapp_fruit_store`

显示:

id    fruit_id     store_id

1     3             7

 

 

修改对象

person.last_name="yu"

person.save()

 

执行save()方法时,等同于执行以下sql UPDATE语句。

UPDATE `myapp_person` SET last_name ='yu'  where id =1;

 

修改包含外键的对象

清空Person,Book moduel关联的表数据后,执行以下操作

 

例:

>>> person = Person(first_name='ke', last_name="shou")

>>> person.save()

>>> book = Book(book_name="yueding", borrower=person)

>>> book.save()

 

SELECT * FROM myapp_person

显示:

id   first_name    last_name

1    ke            shou

 

SELECT * FROM myapp_book

显示:

id   book_name  borrower_id

1    yueding    1

 

>>> person = Person(first_name='yu', last_name='lai')

>>> person.save()

>>> book.borrower = person

>>> book.save()

 

SELECT * FROM myapp_person

显示:

id   first_name    last_name

1    ke            shou

2    yu            lai

 

SELECT * FROM myapp_book

显示:

id   book_name  borrower_id

1    yueding    2

 

修改包含多对多Field的对象

add

增加model对象到关联对象,即在model对应表中增加关联记录

>>> ximi_store = Store.objects.create(name='ximi')

>>> apple = Fruit.objects.get(id=3)

>>> apple.store.add(ximi_store)

 

SELECT * FROM `myapp_fruit_store`

显示:

id    fruit_id     store_id

1     3             7

2     3             8

 

结果如上,新增一条关联记录,关联新增的ximi_store

 

当然,我们也可以一次性关联多个对象

>>> xima_store = Store.objects.create(name='xima')

>>> masu_store = Store.objects.create(name='masu')

>>> apple.store.add(xima_store, masu_store)

 

SELECT * FROM `myapp_fruit_store`

显示:

id    fruit_id     store_id

1     3             7

2     3             8

3     3             9

4     3             10

 

remove

从已关联对象中,删除指定关联对象

承接add

>>> apple.store.remove(masu_store)

 

SELECT * FROM `myapp_fruit_store`

显示:

id    fruit_id     store_id

1     3             7

2     3             8

3     3             9

 

注意:上面是基于“add”中操作的,如果还没获取对象,则需要通过类似 model_name.objects.get(id=1)的方式,先获取对象,然后操作对象。

 

set

注:以下基于remove之后的操作

>>> gami_store = Store.objects.create(name='gami')

>>> gama_store = Store.objects.create(name='gama')

>>> new_list = [gami_store, gama_store]

>>> apple.store.set(new_list)

 

SELECT * FROM `myapp_store`

显示:

id    name   last_update

7     aimi   2018-03-25

8     ximi   2018-03-25

9     xima   2018-03-25

10    masu   2018-03-25

11    gami   2018-03-25

12    gama   2018-03-25

 

 

SELECT * FROM `myapp_fruit_store`

显示:

id    fruit_id     store_id

6     3             11

5     3             12

 

如上,关联的对象,全部被替换为最新的了

 

clear

清空所有已关联对象

>>> apple.store.clear()

 

结果myapp_fruit_store表中的记录全部被清空了。

 

参考链接:

https://docs.djangoproject.com/en/1.11/ref/models/relations/#django.db.models.fields.related.RelatedManager.add

 

检索对象

检索所有对象

例:

>>> person = Person(first_name="ke", last_name="shou")

>>> person.save()

 

>>> all_entries = Person.objects.all()

>>> all_entries

<QuerySet [<Person: Person object>]>

>>> print(all_entries.query) # 查看获取结果集执行对sql语句

说明:

all()方法会返回数据库表中所有记录的结果集,等同于以下sql SELECT 语句

SELECT * FROM `myapp_person`

 

另外,我们可以通过list(QueryResultSet)把QuerySet类型的查询结果转为列表类型

 

通过过滤器检索特定对象

例:

>>> entries = Person.objects.filter(first_name='ke')

 

说明:

等同于

>>> entries = Person.objects.all().filter(first_name='ke')

 

执行以上filter方法,等同于执行以下SQL方法

SELECT * FROM `myapp_person` WHERE first_name = 'ke'

 

 

>>> entries = Person.objects.exclude(last_name='yu')

 

执行以上exclude方法,等同于执行以下SQL方法

SELECT * FROM `myapp_person` WHERE first_name != 'yu'

 

 

链式过滤器

例:

>>> Person.objects.filter(first_name='ke').filter(last_name='shou')

 

说明:先过滤出first_name值为ke的,然后再从这里面筛选出last_name为 shou的。

等同于

>>> Person.objects.filter(first_name='ke', last_name='shou')

 

 

>>> Person.objects.filter(first_name='ke').exclude(last_name='shou')

 

说明:先过滤出first_name值为ke的,然后再从这里面筛选出last_name不为 shou的

 

当然,也可以拆分成多条语句

>>> q1 = Person.objects.filter(first_name='ke')

>>> q2 = q1.exclude(last_name='shou')

>>> print(q2)

 

注意:只有真正用到查询结果时,才会执行数据库操作,比如上述代码,只有执行最后一行,print(q2)时才会真正去数据库查询。

 

注意:exclude并不是filter的完全实现。如下:

SELECT * FROM `myapp_person`

显示:

id  first_name last_name

1   ke             shou

2   yu             lai

3   ke             lai

4   yu             laiyu

 

SELECT * FROM `myapp_book`

显示:

id  book_name  borrower_id

1   yueding    2

2   duzhe      1

3   zhazhi     2

4   shenghuo   3

5   qinglv      4

 

获取myapp_person表记录,排除在myapp_book表中存在外键引用,且对应记录book_name为yueding, id=1的。

>>> persons = Person.objects.exclude(book__book_name='yueding', book__id=1)

>>> for person in persons:

...     print(person.first_name, person.last_name, person.id)

...

ke shou 1

ke lai 3

yu laiyu 4

 

注意:

1、“反向查找”,条件左侧表达式填写格式:model名称__field名称

2、“正向查找”,不能按以上方式查找,比如以下,会报错:

>>> books = Book.objects.exclude(Person__first_name='ke', Person__last_name='shou')

 

反向查找和正向查找是我个人定义。定义不太好表达,具体参考以上例子。

 

如果结合filter方法来实现,则可采用“嵌套”的方式

>>> persons = Person.objects.exclude(book__in=Book.objects.filter(book_name='yueding', id=1))

>>> for person in persons:

...     print(person.first_name, person.last_name, person.id)

...

ke shou 1

ke lai 3

yu laiyu 4

>>>

 

 

目录
相关文章
|
1月前
|
关系型数据库 MySQL Java
Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。
这篇文章是关于如何使用Django框架配置MySQL数据库,创建模型实例,并自动或手动创建数据库表,以及对这些表进行操作的详细教程。
61 0
Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。
|
数据库 Python
[Python]Django模型(Model)(二)
[Python]Django模型(Model)(二)
|
设计模式 SQL 数据库
|
Python
django model进阶学习
django model进阶学习
49 0
|
存储 关系型数据库 MySQL
Django第2步_创建model数据库表
Django第2步_创建model数据库表
112 0
|
数据库 Python
Django model 层之事务管理总结
Django model 层之事务管理总结
134 0
|
SQL JSON 测试技术
Django model层之执行原始SQL查询
Django model层之执行原始SQL查询
119 0
|
关系型数据库 MySQL 数据库
Django model 层之聚合查询总结
Django model 层之聚合查询总结
108 0
|
SQL 存储 缓存
Django model 层之Making Query总结2
Django model 层之Making Query总结
107 0
|
SQL JavaScript 前端开发
Django之Model世界
Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行数据库操作     import MySQLdb def GetList(sql): db = MySQLdb.
1020 0