?
成都地區(qū)優(yōu)秀IDC服務(wù)器托管提供商(創(chuàng)新互聯(lián)).為客戶提供專(zhuān)業(yè)的成都西信服務(wù)器托管,四川各地服務(wù)器托管,成都西信服務(wù)器托管、多線服務(wù)器托管.托管咨詢專(zhuān)線:13518219792
目錄
model 1
model:...2
常用Field types:...5
Relationship fields.5
Field options:...6
Meta options:...6
重寫(xiě)save()方法:...7
模型繼承:...7
抽象基類(lèi):...7
多表繼承:...8
代理繼承:...9
多重繼承:...10
?
?
?
?
模型的價(jià)值在于定義數(shù)據(jù)模型,使用py代碼ORM形式操作數(shù)據(jù)庫(kù);
?
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',
]
?
?
支持sqlite、MySQL、postgresql、oracle;
py3.5以上版本,不支持MySQLdb驅(qū)動(dòng);
可用pymysql,py寫(xiě)的;
可用mysqlclient,c寫(xiě)的,速度快,fork的MySQLdb,官方推薦;
?
ORM,用py的方法、數(shù)據(jù)結(jié)構(gòu),來(lái)訪問(wèn)db,可兼容不同的DB;
?
一個(gè)class代表一張表,多對(duì)多會(huì)產(chǎn)生額外一張關(guān)系表;
默認(rèn)pk為id,也可自定義pk;
表名默認(rèn)為$APP_NAME$CLASS_NAME.lower(),表名小寫(xiě)(跨平臺(tái)支持),可重寫(xiě);
?
models migrations:
定義好models.py需應(yīng)用到db,django為了能跟蹤表結(jié)構(gòu)的變化,增加了migration版本控制功能,如果沒(méi)有該功能,需手動(dòng)編寫(xiě)表結(jié)構(gòu)變化的語(yǔ)句,重新導(dǎo)入數(shù)據(jù);
先makemigrations再migrate;
?
models CRUD:
增:
q = Question(**kwargs)?? #方式1,實(shí)例化,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默認(rèn)的manager管理器
Question.objects.get(id=1)
latest_question_list = Question.objects.order_by('-pub_date')[:3]?? #默認(rèn)升序,加上-為倒序
?
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()多了時(shí)區(qū),在頁(yè)面展示時(shí),django內(nèi)部會(huì)轉(zhuǎn)為適合用戶所在的時(shí)區(qū)
datetime.datetime(2019, 1, 2, 7, 2, 18, 244920, tzinfo=
>>> 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):?? #一個(gè)class代表一張表,多對(duì)多會(huì)產(chǎn)生額外一張關(guān)系表;默認(rèn)pk為id,也可自定義pk;表名默認(rèn)為$APP_NAME$CLASS_NAME.lower(),可重寫(xiě)
??? 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ū)動(dòng)器 C 中的卷是 OS
?卷的序列號(hào)是 000B-5D26
C:\webproject\mysite\polls\migrations 的目錄
2019/01/02? 14:24???
2019/01/02? 14:24???
2019/01/02? 14:24???????????? 1,266 0001_initial.py
2019/01/02? 11:29???????????????? 0 __init__.py
2019/01/02? 14:25???
?????????????? 2 個(gè)文件????????? 1,266 字節(jié)
?????????????? 3 個(gè)目錄 77,168,365,568 可用字節(jié)
(webproject) C:\webproject\mysite>python manage.py sqlmigrate polls 0001_initial?? #查看sql語(yǔ)句是否是指定要求的
?
(webproject) C:\webproject\mysite>python manage.py shell??#進(jìn)入交互式命令行
>>> 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默認(rèn)會(huì)增加id為pk
1
>>> q.question_text
"what's new"
>>> q.pub_date
datetime.datetime(2019, 1, 2, 6, 49, 16, 612213, tzinfo=
?
>>> 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
>>> q.was_published_recently()
True
>>> d = timezone.now() - timezone.timedelta(days=2)
>>> q.pub_date = d
>>> q.save()
>>> q.was_published_recently()
False
?
?
?
https://docs.djangoproject.com/en/2.1/ref/models/fields/#choices
?
name = models.CharField(max_length=30)?? #實(shí)例化時(shí)是py中的數(shù)據(jù)類(lèi)型
num = models.IntegerField()
website = models.URLField()
email = models.EmailField()
models.AutoField()?? #定義AI或PK時(shí)用
models.BooleanField()
models.TextField()
models.DateField()?? #接收py中datetime對(duì)象,自動(dòng)轉(zhuǎn)為sql中的數(shù)據(jù)結(jié)構(gòu)
models.PositiveIntegerField()?? #正數(shù)
?
?
關(guān)系:
authors = models.ManyToManyField(Author)?? #many-to-many,如用戶和組,博客項(xiàng)目中文章和標(biāo)簽;
publisher = models.ForeignKey(Publisher)?? #many-to-one,如外鍵,1個(gè)問(wèn)題有多個(gè)選項(xiàng),1個(gè)選項(xiàng)只能屬1個(gè)問(wèn)題;如汽車(chē)-工廠;
moodels.OneToOneField(
?
?
field參數(shù):
null?? #default is False,mysql中空值用null表示,不能用''(''表示字符串的空串)
blank
choices?? #同sqlalchemy中enum,展示在前端為不能讓用戶自己定義,而是在下拉列表中選擇
default
help_text?? #sql中的comment;form中的備注信息
primary_key?? #默認(rèn)自動(dòng)加id作為主鍵,若顯式指定將不會(huì)有默認(rèn)id主鍵
unique
verbose_name?? #若有定義,在form中將把此處定義的值大寫(xiě),中間的_改為空格,顯示為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)
?
?
?
元編程,改變之前表中定義的元數(shù)據(jù)信息;
?
abstract?? #abstract = True,this model will be an abstract base class,聲明是基類(lèi),數(shù)據(jù)庫(kù)將不會(huì)建此表
db_table?? #db_table = 'music_album'指定表名
get_latest_by?? #get_latest_by = 'order_date'指定此字段按升序,get_latest_by = ['-priority','order_date']指定priority按降序,order_date按升序;查詢時(shí)Question.objects.latest()要先定義get_latest_by根據(jù)哪個(gè)字段走
ordering?? #對(duì)象的默認(rèn)順序,獲取對(duì)象列表,默認(rèn)升序,前綴-降序,前綴?隨機(jī)randomly,ordering = ['pub_date'],ordering = ['-pub_date', 'author']
unique_together?? #聯(lián)合唯一鍵,unique_together('driver','restaurant')
indexes?? #聯(lián)合索引
managed
verbose_name?? #admin后臺(tái)中顯示的名字
?
?
?
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)用父類(lèi)的save(),否則不會(huì)保存到數(shù)據(jù)庫(kù)
?????????????????? do_something()
?
?
?
若只使用父類(lèi)中的信息,用繼承,而不用在子類(lèi)模型中重復(fù)輸入與父類(lèi)相同的那些字段;
抽象出的基類(lèi)不會(huì)單獨(dú)使用;
使用Meta option,abstract = True,聲明是基類(lèi),數(shù)據(jù)庫(kù)將不會(huì)建此表;.
若子類(lèi)不實(shí)現(xiàn)Meta,默認(rèn)會(huì)繼承;
例:
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:?? #若子類(lèi)不實(shí)現(xiàn)Meta,默認(rèn)會(huì)繼承
??????? db_table = 'student_info'
?
?
若繼承一個(gè)已存在的模型且想讓每個(gè)模型都有它自己的數(shù)據(jù)庫(kù)表,應(yīng)使用多表繼承;
每一個(gè)層級(jí)下的每個(gè)model都是一個(gè)真正意義上完整的model,每個(gè)model都有專(zhuān)屬的數(shù)據(jù)庫(kù)表,都可查詢和創(chuàng)建數(shù)據(jù)庫(kù)表;
繼承關(guān)系在子model和它的每個(gè)父類(lèi)之間都添加一個(gè)鏈接,自動(dòng)創(chuàng)建OneToOneField;
父類(lèi)Place中未在Meta中定義abstract=True,子類(lèi)Restaurant在查看表結(jié)構(gòu)時(shí),不會(huì)繼承父類(lèi)的name和address,而是主鍵place_str_id上有指針指向父類(lèi)中的字段;
子類(lèi)繼承父類(lèi),子類(lèi)創(chuàng)建的記錄,父類(lèi)中會(huì)自動(dò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')
>>> Restaurant.objects.create(name='jia',address='bj',servers_hot_dogs=True,servers_pizza=False)
>>> 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
?
?
使用多表繼承時(shí),model的每個(gè)子類(lèi)都會(huì)創(chuàng)建一張新數(shù)據(jù)表,因?yàn)樽宇?lèi)需要一個(gè)空間來(lái)存儲(chǔ)不包含在基類(lèi)中的字段數(shù)據(jù)(如servers_hot_dogs、servers_pizza),有時(shí)只想更改model在py層的行為實(shí)現(xiàn),如改默認(rèn)的manager,或添加一個(gè)新方法,這時(shí)用代理繼承;
為原始模型創(chuàng)建一個(gè)代理,可創(chuàng)建、刪除、更新代理model的實(shí)例,而且所有的數(shù)據(jù)都可象使用原始model一樣被保存;
不同之處在于,可在代理model中改變默認(rèn)的排序設(shè)置和默認(rèn)的manager,更不會(huì)對(duì)原始model產(chǎn)生影響;
使用Meta option,proxy = True,對(duì)代理model的聲明;
MyPerson只是一個(gè)代理,數(shù)據(jù)庫(kù)中不會(huì)創(chuàng)建該表,MyPerson類(lèi)和其父類(lèi)Person操作同一個(gè)數(shù)據(jù)表,特別之處,Person的實(shí)例也可通過(guò)MyPerson訪問(wèn);
例:
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')
?
?
同多表繼承,會(huì)自動(dòng)添加2個(gè)OneToOneField,注意,2個(gè)基類(lèi)的默認(rèn)id要重新命名,否則添加OneToOneField會(huì)有問(wèn)題,也不允許子類(lèi)重寫(xiě)父類(lèi)字段;
例:
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
?
?
?
?
?