溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

97django_model

發(fā)布時間:2020-06-21 16:36:47 來源:網(wǎng)絡(luò) 閱讀:215 作者:chaijowin 欄目:編程語言

?

目錄

model 1

model... 2

常用Field types... 5

Relationship fields. 5

Field options... 6

Meta options... 6

重寫save()方法:... 7

模型繼承:... 7

抽象基類:... 7

多表繼承:... 8

代理繼承:... 9

多重繼承:... 10

?

?

?

model

?

模型的價值在于定義數(shù)據(jù)模型,使用py代碼ORM形式操作數(shù)據(jù)庫;

?

mysite/mysite/settings.py?? #只有在settings.py中激活app才能使用models

INSTALLED_APPS = [

??? 'publish.apps.PublishConfig',

??? 'bootstrap3',

??? 'books.apps.BooksConfig',

??? 'polls.apps.PollsConfig',

??? 'django.contrib.admin',

??? 'django.contrib.auth',

??? 'django.contrib.contenttypes',

??? 'django.contrib.sessions',

??? 'django.contrib.messages',

??? 'django.contrib.staticfiles',

]

?

?

model

支持sqlitemysql、postgresql、oracle;

py3.5以上版本,不支持MySQLdb驅(qū)動;

可用pymysql,py寫的;

可用mysqlclient,c寫的,速度快,forkMySQLdb,官方推薦;

?

ORM,用py的方法、數(shù)據(jù)結(jié)構(gòu),來訪問db,可兼容不同的DB;

?

一個class代表一張表,多對多會產(chǎn)生額外一張關(guān)系表;

默認pkid,也可自定義pk

表名默認為$APP_NAME$CLASS_NAME.lower(),表名小寫(跨平臺支持),可重寫;

?

models migrations

定義好models.py需應(yīng)用到dbdjango為了能跟蹤表結(jié)構(gòu)的變化,增加了migration版本控制功能,如果沒有該功能,需手動編寫表結(jié)構(gòu)變化的語句,重新導(dǎo)入數(shù)據(jù);

makemigrationsmigrate;

?

models CRUD

增:

q = Question(**kwargs)?? #方式1,實例化,Model(kwargs).save()

q.save()

?

q = Question.objects.create(**kwargs)?? #方式2,用管理器形式,Model.objects.create(**kwargs)

?

刪:

q = Question.objects.get(id=1)?? #QuerySet.delete()

q.delete()?? #object.delete()

?

Question.objects.filter(id=1).delete()

Question.objects.all().delete()

?

改:

q = Question.objects.get(id=1)

q.question_text = 'some text'?? #object.attr = value.object.save()

q.save()

?

Question.objects.filter(id=1).update(question_text='why ?')?? #QuerySet.update(**kwargs)

?

查:

Question.objects.all()?? #Model.objects.all(kwargs),Model.objects.filter(kwargs),Model.objects.get(**kwargs)

Question.objects.filter(question_text="what's up?")?? #objects,model默認的manager管理器

Question.objects.get(id=1)

latest_question_list = Question.objects.order_by('-pub_date')[:3]?? #默認升序,加上-為倒序

?

for p in Person.objects.raw('select * from myapp_person'):?? #執(zhí)行原生sql

???????? print(p)

?

注:

>>> from django.utils import timezone

>>> import datetime

>>> timezone.now()?? #datetime.datetime.now()多了時區(qū),在頁面展示時,django內(nèi)部會轉(zhuǎn)為適合用戶所在的時區(qū)

datetime.datetime(2019, 1, 2, 7, 2, 18, 244920, tzinfo=<UTC>)

>>> datetime.datetime.now()

datetime.datetime(2019, 1, 2, 15, 2, 32, 837755)

?

models中方法:

def __str__(self):

???????? return self.question_text

def was_published_recently(self):

???????? return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

?

?

mysite/mysite/settings.py

DATABASES = {

??? 'default': {

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

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

??? }

}

?

?

mysite/polls/models.py

from django.db import models

?

class Question(models.Model):?? #一個class代表一張表,多對多會產(chǎn)生額外一張關(guān)系表;默認pkid,也可自定義pk;表名默認為$APP_NAME$CLASS_NAME.lower(),可重寫

??? question_text = models.CharField(max_length=200)

??? pub_date = models.DateTimeField('date published')

?

class Choice(models.Model):

??? question = models.ForeignKey(Question, on_delete=models.CASCADE)

??? choice_text = models.CharField(max_length=200)

??? votes = models.IntegerField(default=0)

?

(webproject) C:\webproject\mysite>python manage.py makemigrations?? #生成遷移記錄,先makemigrations才能migrate

(webproject) C:\webproject\mysite>python manage.py migrate?? #應(yīng)用到db

(webproject) C:\webproject\mysite>sqlite3 db.sqlite3

sqlite> .tables

auth_group???????????????? ?django_admin_log

auth_group_permissions????? django_content_type

auth_permission???????????? django_migrations

auth_user?????????????????? django_session

auth_user_groups??????????? polls_choice

auth_user_user_permissions? polls_question

sqlite> .quit

?

(webproject) C:\webproject\mysite>dir polls\migrations\

?驅(qū)動器 C 中的卷是 OS

?卷的序列號是 000B-5D26

C:\webproject\mysite\polls\migrations 的目錄

2019/01/02? 14:24??? <DIR>????????? .

2019/01/02? 14:24??? <DIR>????????? ..

2019/01/02? 14:24???????????? 1,266 0001_initial.py

2019/01/02? 11:29???????????????? 0 __init__.py

2019/01/02? 14:25??? <DIR>????????? __pycache__

?????????????? 2 個文件????????? 1,266 字節(jié)

?????????????? 3 個目錄 77,168,365,568 可用字節(jié)

(webproject) C:\webproject\mysite>python manage.py sqlmigrate polls 0001_initial?? #查看sql語句是否是指定要求的

?

(webproject) C:\webproject\mysite>python manage.py shell? ?#進入交互式命令行

>>> from django.utils import timezone

>>> from polls.models import Question,Choice

>>> q = Question(question_text="what's new", pub_date=timezone.now())

>>> q.save()

>>> q.id

1

>>> q.pk?? #django默認會增加idpk

1

>>> q.question_text

"what's new"

>>> q.pub_date

datetime.datetime(2019, 1, 2, 6, 49, 16, 612213, tzinfo=<UTC>)

?

>>> from polls.models import Question,Choice

>>> from django.utils import timezone

>>> q = Question.objects.create(question_text="how are you?", pub_date=timezone.now())

>>> q = Question.objects.create(question_text="what's the weather?", pub_date=timezone.now())

>>> q = Question.objects.create(question_text="fuck you!", pub_date=timezone.now())

>>> q

<Question: fuck you!>

>>> q.was_published_recently()

True

>>> d = timezone.now() - timezone.timedelta(days=2)

>>> q.pub_date = d

>>> q.save()

>>> q.was_published_recently()

False

?

?

常用Field types

?

https://docs.djangoproject.com/en/2.1/ref/models/fields/#choices

?

name = models.CharField(max_length=30)?? #實例化時是py中的數(shù)據(jù)類型

num = models.IntegerField()

website = models.URLField()

email = models.EmailField()

models.AutoField()?? #定義AIPK時用

models.BooleanField()

models.TextField()

models.DateField()?? #接收pydatetime對象,自動轉(zhuǎn)為sql中的數(shù)據(jù)結(jié)構(gòu)

models.PositiveIntegerField()?? #正數(shù)

?

?

Relationship fields

關(guān)系:

authors = models.ManyToManyField(Author)?? #many-to-many,如用戶和組,博客項目中文章和標(biāo)簽;

publisher = models.ForeignKey(Publisher)?? #many-to-one,如外鍵,1個問題有多個選項,1個選項只能屬1個問題;如汽車-工廠;

moodels.OneToOneField(<field-name>)?? #one-to-one,如Restaurant餐館和place地點,如丈夫-妻子;

?

?

Field options

field參數(shù):

null?? #default is False,mysql中空值用null表示,不能用''''表示字符串的空串)

blank

choices?? #sqlalchemyenum,展示在前端為不能讓用戶自己定義,而是在下拉列表中選擇

default

help_text?? #sql中的comment;form中的備注信息

primary_key?? #默認自動加id作為主鍵,若顯式指定將不會有默認id主鍵

unique

verbose_name?? #若有定義,在form中將把此處定義的值大寫,中間的_改為空格,顯示為form中的label

?

例:

class Group(models.Model):

??? pass

?

class User(models.Model):

??? groups = models.ManyToManyField(Group)

?

例:

class Place(models.Model):

??? name = models.CharField(max_length=50)

??? address = models.CharField(max_length=80)

?

class Restaurant(models.Model):

??? place = models.OneToOneField(Place, primary_key=True)

??? servers_hot_dogs = models.BooleanField(default=False)

??? servers_pizza = models.BooleanField(default=False)

?

例:

class Manufacturer(models.Model):

??? pass

?

class Car(models.Model):

??? manufacturer = models.ForeignKey(Manufacturer)

?

?

Meta options

?

元編程,改變之前表中定義的元數(shù)據(jù)信息;

?

abstract?? #abstract = True,this model will be an abstract base class,聲明是基類,數(shù)據(jù)庫將不會建此表

db_table?? #db_table = 'music_album'指定表名

get_latest_by?? #get_latest_by = 'order_date'指定此字段按升序,get_latest_by = ['-priority','order_date']指定priority按降序,order_date按升序;查詢時Question.objects.latest()要先定義get_latest_by根據(jù)哪個字段走

ordering?? #對象的默認順序,獲取對象列表,默認升序,前綴-降序,前綴?隨機randomlyordering = ['pub_date'],ordering = ['-pub_date', 'author']

unique_together?? #聯(lián)合唯一鍵,unique_together('driver','restaurant')

indexes?? #聯(lián)合索引

managed

verbose_name?? #admin后臺中顯示的名字

?

?

重寫save()方法:

?

from django.db import models

?

class Blog(models.Model):

???????? name = models.CharField(max_length=100)

???????? tagline = models.TextField()

?

???????? def save(self, *args, **kwargs):

?????????????????? do_something()

?????????????????? super(Blog, self).save(*args, **kwargs)?? #import,call the real save() method,一定要調(diào)用父類的save(),否則不會保存到數(shù)據(jù)庫

?????????????????? do_something()

?

?

模型繼承:

?

抽象基類:

若只使用父類中的信息,用繼承,而不用在子類模型中重復(fù)輸入與父類相同的那些字段;

抽象出的基類不會單獨使用;

使用Meta option,abstract = True,聲明是基類,數(shù)據(jù)庫將不會建此表;.

若子類不實現(xiàn)Meta,默認會繼承;

例:

class CommonInfo(models.Model):

??? name = models.CharField(max_length=100)

??? age = models.PositiveIntegerField()

?

??? class Meta:

??????? abstract = True

??????? ordering = ['name']

?

class Student(CommonInfo):

??? home_group = models.CharField(max_length=5)

?

??? class Meta:?? #若子類不實現(xiàn)Meta,默認會繼承

??????? db_table = 'student_info'

?

?

多表繼承:

若繼承一個已存在的模型且想讓每個模型都有它自己的數(shù)據(jù)庫表,應(yīng)使用多表繼承;

每一個層級下的每個model都是一個真正意義上完整的model,每個model都有專屬的數(shù)據(jù)庫表,都可查詢和創(chuàng)建數(shù)據(jù)庫表;

繼承關(guān)系在子model和它的每個父類之間都添加一個鏈接,自動創(chuàng)建OneToOneField;

父類Place中未在Meta中定義abstract=True,子類Restaurant在查看表結(jié)構(gòu)時,不會繼承父類的nameaddress,而是主鍵place_str_id上有指針指向父類中的字段;

子類繼承父類,子類創(chuàng)建的記錄,父類中會自動有;

例:

class Place(models.Model):

??? name = models.CharField(max_length=50)

??? address = models.CharField(max_length=80)

?

class Restaurant(Place):

??? servers_hot_dogs = models.BooleanField(default=False)

??? servers_pizza = models.BooleanField(default=False)

?

sqlite> .schema publish_place

CREATE TABLE IF NOT EXISTS "publish_place" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(50) NOT NULL, "address" varchar(80) NOT NULL);

sqlite> .schema publish_restaurant

CREATE TABLE IF NOT EXISTS "publish_restaurant" ("place_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "publish_place" ("id"), "servers_hot_dogs" bool NOT NU

LL, "servers_pizza" bool NOT NULL);

?

>>> from publish.models import Place,Restaurant

>>> Place.objects.create(name='tsinghua', address='zhongguancun')

<Place: Place object>

>>> Restaurant.objects.create(name='jia',address='bj',servers_hot_dogs=True,servers_pizza=False)

<Restaurant: Restaurant object>

>>> p0 = Place.objects.get(name='tsinghua')

>>> p1 = Place.objects.get(name='jia')

>>> p2 = Restaurant.objects.get(name='tsinghua')?? #X

……"C:\Users\Administrator\py_env\webproject\lib\site-packages\django\db\models\query.py", line 379, in get

? ??self.model._meta.object_name

publish.models.DoesNotExist: Restaurant matching query does not exist.

>>> p3 = Restaurant.objects.get(name='jia')

>>> p0.restaurant?? #X

……"C:\Users\Administrator\py_env\webproject\lib\site-packages\django\db\models\fields\related_descriptors.py", line 404, in __get__

??? self.related.get_accessor_name()

django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist: Place has no restaurant.

>>> p1.restaurant

<Restaurant: Restaurant object>

?

?

代理繼承:

使用多表繼承時,model的每個子類都會創(chuàng)建一張新數(shù)據(jù)表,因為子類需要一個空間來存儲不包含在基類中的字段數(shù)據(jù)(如servers_hot_dogsservers_pizza),有時只想更改modelpy層的行為實現(xiàn),如改默認的manager,或添加一個新方法,這時用代理繼承;

為原始模型創(chuàng)建一個代理,可創(chuàng)建、刪除、更新代理model的實例,而且所有的數(shù)據(jù)都可象使用原始model一樣被保存;

不同之處在于,可在代理model中改變默認的排序設(shè)置和默認的manager,更不會對原始model產(chǎn)生影響;

使用Meta option,proxy = True,對代理model的聲明;

MyPerson只是一個代理,數(shù)據(jù)庫中不會創(chuàng)建該表,MyPerson類和其父類Person操作同一個數(shù)據(jù)表,特別之處,Person的實例也可通過MyPerson訪問;

例:

class Person(models.Model):

??? first_name = models.CharField(max_length=30)

??? last_name = models.CharField(max_length=30)

?

class MyPerson(Person):

??? class Meta:

??????? proxy = True

?

??? def do_something(self):

??????? pass

?

>>> from publish.models import Person,MyPerson

>>> p = Person.objects.create(first_name='foobar')

>>> MyPerson.objects.get(first_name='foobar')

<MyPerson: MyPerson object>

?

?

多重繼承:

同多表繼承,會自動添加2OneToOneField,注意,2個基類的默認id要重新命名,否則添加OneToOneField會有問題,也不允許子類重寫父類字段;

例:

class Article(models.Model):

??? article_id = models.AutoField(primary_key=True)

?

class Book2(models.Model):

??? book_id = models.AutoField(primary_key=True)

?

class Book2Review(Book, Article):

??? pass

?

?

?

?

?


向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI