看我多久能學(xué)會(huì)Django(四):Django模型(數(shù)據(jù)庫(kù))

Django模型是與數(shù)據(jù)庫(kù)相關(guān)的十厢,與數(shù)據(jù)庫(kù)相關(guān)的代碼一般寫在model.py中,Django 支持 sqlite3, MySQL, PostgreSQL等數(shù)據(jù)庫(kù)探橱,只需要在settings.py中配置即可申屹,不用更改models.py中的代碼,豐富的API極大的方便了使用隧膏。

下面哗讥,看栗子:
我們先創(chuàng)建項(xiàng)目,再創(chuàng)建應(yīng)用:

django-admin startproject zjyd
cd  zjyd/
python  manage.py   startapp  people

將我們新建的應(yīng)用(people)添加到 settings.py 中的 INSTALLED_APPS中胞枕,也就是告訴Django有這么一個(gè)應(yīng)用杆煞。

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
 
    'people',
)

然后編輯 people/models.py 文件,修改其中的代碼:

from django.db import models
 
class Person(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField()

我們創(chuàng)建了一個(gè)Person類腐泻,繼承自models.Model决乎,并設(shè)置了name和age兩個(gè)屬性

接下來(lái)同步數(shù)據(jù)庫(kù)

首先執(zhí)行:
# python manage.py  makemigrations 
Migrations for 'people':
  people/migrations/0001_initial.py:
    - Create model Person

接著執(zhí)行:
# python manage.py  migrate  
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, people, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying people.0001_initial... OK
  Applying sessions.0001_initial... OK

這樣的話,Django已經(jīng)為我們創(chuàng)建了需要的表派桩,下面看看如何使用:

# python manage.py  shell 
In [1]: from people.models import Person 

In [2]: Person.objects.create(name="django",age=13)
Out[2]: <Person: Person object>

我們新創(chuàng)建了一個(gè)用戶django构诚,下面看看如何從數(shù)據(jù)庫(kù)查詢:

In [3]: Person.objects.get(name="django") 
Out[3]: <Person: Person object>

我們用了一個(gè) .objects.get() 方法查詢出來(lái)符合條件的對(duì)象,但是大家注意到了沒(méi)有铆惑,查詢結(jié)果中顯示<Person: Person object>范嘱,這里并沒(méi)有顯示出與WeizhongTu的相關(guān)信息,如果用戶多了就無(wú)法知道查詢出來(lái)的到底是誰(shuí)员魏,查詢結(jié)果是否正確丑蛤,我們重新修改一下 people/models.py

name 和 age 等字段中不能有 __(雙下劃線,因?yàn)樵贒jango QuerySet API中有特殊含義(用于關(guān)系逆趋,包含盏阶,不區(qū)分大小寫,以什么開頭或結(jié)尾闻书,日期的大于小于名斟,正則等)

也不能有Python中的關(guān)鍵字,name 是合法的魄眉,student_name 也合法砰盐,但是student__name不合法,try, class, continue 也不合法坑律,因?yàn)樗荘ython的關(guān)鍵字( import keyword; print(keyword.kwlist) 可以打出所有的關(guān)鍵字)

from django.db import models

# Create your models here.
class Person(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField()

    def __str__(self):
        return self.name

重新調(diào)用shell:

In [1]: from people.models import Person 

In [2]: Person.objects.get(name="django") 
Out[2]: <Person: django>

新建一個(gè)對(duì)象的方法有以下幾種:
方法一:Person.objects.create(name=name,age=age)
方法二:p = Person(name="django", age=13)
p.save()
方法三:p = Person(name="django")
p.age = 23
p.save()
方法四:Person.objects.get_or_create(name="django", age=13)
這種方法是防止重復(fù)很好的方法岩梳,但是速度要相對(duì)慢些,返回一個(gè)元組,第一個(gè)為Person對(duì)象冀值,第二個(gè)為True或False也物,新建時(shí)返回的時(shí)True,已經(jīng)存在時(shí)返回False列疗。

In [3]: Person.objects.get_or_create(name="django", age=13)
Out[3]: (<Person: django>, False)
In [5]: Person.objects.get_or_create(name="flask", age=6)
Out[5]: (<Person: flask>, True)

獲取對(duì)象有以下方法:
方法一:Person.objects.all()

In [6]: Person.objects.all() 
Out[6]: <QuerySet [<Person: django>, <Person: flask>]>

方法二:Person.objects.all()[:1] 切片操作滑蚯,獲取1個(gè)人,不支持負(fù)索引抵栈,切片可以節(jié)約內(nèi)存

In [7]: Person.objects.all()[:1]
Out[7]: <QuerySet [<Person: django>]>

方法三:Person.objects.get(name=name)

get是用來(lái)獲取一個(gè)對(duì)象的告材,如果需要獲取滿足條件的一些人,就要用到filter
方法四:Person.objects.filter(name="abc") # 等于Person.objects.filter(name__exact="abc") 名稱嚴(yán)格等于 "abc" 的人

In [8]: Person.objects.filter(name="django")  
Out[8]: <QuerySet [<Person: django>]>

方法五:Person.objects.filter(name__iexact="abc") # 名稱為 abc 但是不區(qū)分大小寫古劲,可以找到 ABC, Abc, aBC斥赋,這些都符合條件

方法六:Person.objects.filter(name__contains="abc") # 名稱中包含 "abc"的人

方法七:Person.objects.filter(name__icontains="abc") #名稱中包含 "abc",且abc不區(qū)分大小寫

方法八:Person.objects.filter(name__regex="^abc") # 正則表達(dá)式查詢

方法九:Person.objects.filter(name__iregex="^abc")# 正則表達(dá)式不區(qū)分大小寫

filter是找到滿足條件的产艾,當(dāng)然也有排除符合條件的
方法十:Person.objects.exclude(name__contains="WZ") # 排除包含 WZ 的Person對(duì)象

方法十一:Person.objects.filter(name__contains="abc").exclude(age=23) # 找出名稱含有abc, 但是排除年齡是23歲的

Django 自定義Field

Django 的官方提供了很多的 Field疤剑,但是有時(shí)候還是不能滿足我們的需求,不過(guò)Django提供了自定義 Field 的方法:

栗子:

#coding:utf-8
from django.db import models
 
 
class CompressedTextField(models.TextField):
    """
    model Fields for storing text in a compressed format (bz2 by default)
    """
 
    def from_db_value(self, value, expression, connection, context):
        if not value:
            return value
        try:
            return value.decode('base64').decode('bz2').decode('utf-8')
        except Exception:
            return value
 
    def to_python(self, value):
        if not value:
            return value
        try:
            return value.decode('base64').decode('bz2').decode('utf-8')
        except Exception:
            return value
 
    def get_prep_value(self, value):
        if not value:
            return value
        try:
            value.decode('base64')
            return value
        except Exception:
            try:
                return value.encode('utf-8').encode('bz2').encode('base64')
            except Exception:
                return value

from_db_value 函數(shù)用于轉(zhuǎn)化數(shù)據(jù)庫(kù)中的字符到 Python的變量胰舆。

我們想保存一個(gè) 列表到數(shù)據(jù)庫(kù)中骚露,在讀取用的時(shí)候要是 Python的列表的形式,我們來(lái)自己寫一個(gè) ListField:
這個(gè)ListField繼承自 TextField缚窿,代碼如下:

from django.db import models
import ast
 
class ListField(models.TextField):
    __metaclass__ = models.SubfieldBase
    description = "Stores a python list"
 
    def __init__(self, *args, **kwargs):
        super(ListField, self).__init__(*args, **kwargs)
 
    def to_python(self, value):
        if not value:
            value = []
 
        if isinstance(value, list):
            return value
 
        return ast.literal_eval(value)
 
    def get_prep_value(self, value):
        if value is None:
            return value
 
        return unicode(value) # use str(value) in Python 3
 
    def value_to_string(self, obj):
        value = self._get_val_from_obj(obj)
        return self.get_db_prep_value(value)

使用它很簡(jiǎn)單棘幸,首先導(dǎo)入 ListField,像自帶的 Field 一樣使用:

class Article(models.Model):
    labels = ListField()

在終端上嘗試(運(yùn)行 python manage.py shell 進(jìn)入):

>>> from app.models import Article
>>> d = Article()
>>> d.labels
[]
>>> d.labels = ["Python", "Django"]
>>> d.labels
["Python", "Django"]

本文章來(lái)自自強(qiáng)學(xué)堂:http://www.ziqiangxuetang.com/django/django-tutorial.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末倦零,一起剝皮案震驚了整個(gè)濱河市误续,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扫茅,老刑警劉巖蹋嵌,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異葫隙,居然都是意外死亡栽烂,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門恋脚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)腺办,“玉大人,你說(shuō)我怎么就攤上這事糟描』澈恚” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵船响,是天一觀的道長(zhǎng)躬拢。 經(jīng)常有香客問(wèn)我躲履,道長(zhǎng),這世上最難降的妖魔是什么聊闯? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任工猜,我火速辦了婚禮,結(jié)果婚禮上菱蔬,老公的妹妹穿的比我還像新娘域慷。我一直安慰自己,他們只是感情好汗销,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著抵窒,像睡著了一般弛针。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上李皇,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天削茁,我揣著相機(jī)與錄音,去河邊找鬼掉房。 笑死茧跋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的卓囚。 我是一名探鬼主播瘾杭,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼哪亿!你這毒婦竟也來(lái)了粥烁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蝇棉,失蹤者是張志新(化名)和其女友劉穎讨阻,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體篡殷,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡钝吮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了板辽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奇瘦。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖戳气,靈堂內(nèi)的尸體忽然破棺而出链患,到底是詐尸還是另有隱情,我是刑警寧澤瓶您,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布麻捻,位于F島的核電站纲仍,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏贸毕。R本人自食惡果不足惜郑叠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望明棍。 院中可真熱鬧乡革,春花似錦、人聲如沸摊腋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)兴蒸。三九已至视粮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間橙凳,已是汗流浹背蕾殴。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留岛啸,地道東北人钓觉。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像坚踩,于是被迫代替她去往敵國(guó)和親荡灾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容