十一、【用django2.0來開發】Django的ORM到底如何用——QuerySet

有一周沒寫專欄了, 最近確實有點忙。今天講一下比較中的Django中的ORM吧。本來想融合到項目中的, 但是發現無法全面的講解。 所以單獨拿一章出來講吧

項目demo地址: gitee.com/ccnv07/django

實例中用到的Model

from django.db import models
class Account(models.Model):
account = models.CharField(max_length=64, blank=True, verbose_name=用戶名)
nickname = models.CharField(max_length=64, blank=True, verbose_name=昵稱)
password = models.CharField(max_length=128, blank=True, verbose_name=密碼)
email = models.EmailField(max_length=32, blank=True, verbose_name=郵箱)
phone = models.CharField(max_length=11, blank=True, verbose_name=手機號)
status = models.IntegerField(
default=1,
blank=True,
verbose_name=狀態,
choices=((1, 啟用), (0, 禁用)))

def __str__(self):
return self.account

class Article(models.Model):
navigation_id = models.IntegerField(default=0, verbose_name=所屬欄目)
thumb = models.CharField(max_length=255, verbose_name=縮略圖, default=)
title = models.CharField(
max_length=64, blank=True, default=, verbose_name=文章標題)
# 如果投稿, 則是會員id, 否則為0(管理員)
author_id = models.IntegerField(default=0, verbose_name=文章作者)
content = models.TextField(blank=True, default=, verbose_name=文章內容)

class Tag(models.Model):

文章標籤類

name = models.CharField(
max_length=32, blank=True, default=, verbose_name=標籤名稱)

class ArticleTagMap(models.Model):

文章和標籤的對應表

article_id = models.IntegerField(default=0)
tag_id = models.IntegerField(default=0)

class Navigation(models.Model):
navigation_name = models.CharField(
max_length=64, blank=True, default=, verbose_name=欄目名稱)
pid = models.IntegerField(default=0, verbose_name=上級欄目)
url = models.CharField(
max_length=32, blank=True, default=, verbose_name=鏈接)

一共有四張表 Account(會員表)、Article(文章表)、Tag(文章標籤表)、ArticleTagMap(文章和標籤對應表)、Navigation(欄目表)

  1. Account和Article通過Article.author_id建立關聯, 每個會員可以發布多篇文章
  2. Article和Tag通過ArticleTagMap表關聯, 每個文章可能有多個標籤, 每個標籤下也可能有多個文章
  3. Article和Navigation通過Article.navigation_id建立關聯, 每個欄目下有多篇文章

新增數據

In [1]: from article.models import Navigation

In [2]: navigation = Navigation(navigation_name=日記, pid=0, url=riji)

In [3]: navigation.save()
In [7]: Navigation.objects.all()
Out[7]: <QuerySet [<Navigation: 日記>, <Navigation: 音樂>, <Navigation: 北京新聞>, <Navigation: 娛樂>, <Navigation: 資訊>, <Navigation: 新聞>]>

只有調用save(), 才會真正執行新增操作

更新數據

通過更新對象來更新數據

In [11]: navigation = Navigation.objects.get(navigation_name=日記)

In [12]: navigation.url = my_note

In [13]: navigation.save()

In [14]: navigation = Navigation.objects.get(navigation_name=日記)

In [15]: navigation.url
Out[15]: my_note

如果對象已經被查詢出來, 然後通過更改模型對象的屬性值, 之後調用save()方法, 則可以更新到數據

使用update方法來更新數據

In [18]: Navigation.objects.filter(navigation_name=日記).update(url=my_note)
Out[18]: 1

In [19]: navigation = Navigation.objects.get(navigation_name=日記)

In [20]: navigation.url
Out[20]: my_note

這句話執行的sql是update navigation set url=my_node where navigation_name=日記

當對象並沒有被查出的時候, 可以直接指定要更新的欄位來更新。

刪除對象

直接通過模型對象的方法刪除

In [21]: navigation.delete()
Out[21]: (1, {article.Navigation: 1})

In [22]: Navigation.objects.all()
Out[22]: <QuerySet [<Navigation: 音樂>, <Navigation: 北京新聞>, <Navigation: 娛樂>, <Navigation: 資訊>, <Navigation: 新聞>]>

如果模型對象已經被查出, 則可以直接指定delete來更新

通過delete方法來刪除

Navigation.objects.filter(navigation_name=日記).delete()

執行的sql就是delete from navigation where navigation_name=日記

查詢數據

all,get,filter和exclude

這四個方法是查詢後最終會返回數據的方法。區別在於

  1. all() 返回多條數據
  2. get() 返回一條數據,並且get方法內可以直接指定查詢條件
  3. filter() 返回指定條件的所有數據
  4. exclude() 返回除了滿足條件以外的數據

In [23]: Navigation.objects.all()
Out[23]: <QuerySet [<Navigation: 音樂>, <Navigation: 北京新聞>, <Navigation: 娛樂>, <Navigation: 資訊>, <Navigation: 新聞>]>

In [24]: Navigation.objects.get(navigation_name=新聞)
Out[24]: <Navigation: 新聞>

In [25]: Navigation.objects.filter(navigation_name=新聞)
Out[25]: <QuerySet [<Navigation: 新聞>]>

In [26]: Navigation.objects.exclude(navigation_name=新聞)
Out[26]: <QuerySet [<Navigation: 音樂>, <Navigation: 北京新聞>, <Navigation: 娛樂>, <Navigation: 資訊>]>

對比一下區別, 是不是會發現, get()查詢最後返回的是Navigation的模型對象, 而其他三個都返回的是QuerySet對象, QuerySet對象是一個包含了Navigation模型對象的list。


推薦閱讀:

TAG:Django(框架) | DjangoORM | Python |