Django目錄介紹 django-admin startproject mysite 在終端建立目錄 cd mysite python manage.py startapp app01 建立一個app project - app01 -migrations 和數據庫相關,和modal相關 - admin Django自帶後臺管理相關配置 - modal 寫類,根據類建立數據庫表 - test 單元測試 - views 業務處理,業務能夠分類 - app02 - app03 1. 路由系統(位置參數和形式參數不要不要混用,*args,**kwargs能夠接收參數) url -> 函數 a. /login/ -> def login SEO權重不高 b. /add-user/(\d+)/ -> def add_user(request,a1) /add-user/(\d+)/(\d+)/ -> def add_user(request,a1,a2) 位置參數 c. /add-user/(?P<a1>\d+)/ -> def add_user(request,a1) 形式參數 url(r'^index/', views.index), 訪問時必須index/這種形式 url(r'^index$', views.index), 訪問時必須index這種形式 url(r'^index', views.index), 訪問時index開頭的任意字符串均可以訪問 url(r'^index/(\d+).html', views.index), 訪問時必須index/(\d+).html開頭的這種形式 url(r'^', views.index) 沒有匹配成功,設置默認html PS: 終止符: ^edit$ 僞靜態 提升SEO權重 url(r'^edit/(\w+).html$', views.edit), d. 路由分發 urls.py中 導入from django.conf.urls import include url(r'^app01/', include('app01.urls')), 先在總路由匹配app路徑,而後去該app下urls.py中去匹配路徑 app01.urls.py url(r'^index.html$', views.index), e. 路由系統之別名反向生成url 根據名稱能夠反向生成URL 1. url(r'^index/', views.index,name="n1) 在Python代碼中,在viws.py中 def index(request): from django.urls import reverse v = reverse('n1') print(v) #生成url路徑/index/ url(r'^index/(\d+)/', views.index,name="n1) 在Python代碼中,在viws.py中 def index(request,a1): from django.urls import reverse v = reverse('n1',args={451}) print(v) #生成url路徑/index/451/ url(r'^index/(?P<a1>\d+)/', views.index,name="n1) 在Python代碼中,在viws.py中 def index(request,a1): from django.urls import reverse v = reverse('n1',kwargs={'a1':1111}) print(v) #生成url路徑/index/1111/ 2. 在路由文件中 url(r'^login/', views.login,name='m1') 在html文件中 {% url "m1" %} 提交就能夠找到/login/路徑 在路由文件中 url(r'^login/(\W)/', views.login,name='m1') url(r'^login/(\W).html$', views.login,name='m1') 在html文件中 {% for i in user_list %} <li>{{ i }}|<a href="{% url "m1" i %}">編輯</a></li> {% endfor %} 提交就能夠找到/login/i路徑 提交就能夠找到/login/i.html路徑 3. ORM操做 ORM利用pymysql第三方工具鏈接數據庫 默認:使用SQLlite 數據庫 Http請求: url -> 視圖(模板+數據) 步驟: 1. 建立數據庫:在數據庫建立70db 2. 在settings中設置 # DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # } # } DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'70db', 'USER': 'root', 'PASSWORD': '', 'HOST': 'localhost', 'PORT': 3306, } } 3. 在項目__init__.py中更換默認鏈接數據庫的方式,MySQLDB(修改django默認鏈接mySQL方式) import pymysql pymysql.install_as_MySQLdb() 4.在app下的models.py下:建立表 from django.db import models class user_group(models.Model): title = models.CharField(max_length=32) class user_info(models.Model): id = models.BigAutoField(primary_key=True) #這一列不寫也會自動生成 username=models.CharField(max_length=32) password=models.CharField(max_length=64) # age = models.IntegerField(null=True) #設置能夠爲空,建立表後插入這一列時能夠這麼設置 age = models.IntegerField(default=1) #默認生成ug_id,設置能夠爲空,建立表後插入這一列時能夠這麼設置 ug = models.ForeignKey("user_group",null=True) 5.在配置中註冊app INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01' ] 6.建立數據表 命令: python manage.py makemigrations python manage.py migrate
ORM操做表: 建立表 修改表 刪除表 操做數據行: 增刪改查 基於ORM實現組表操做 #新增 models.user_group.objects.create(title="銷售部") models.user_info.objects.create(user='root',password='pwd',age=18,ug_id=1) 查找 group_list = models.user_group.objects.all() models.user_group.objects.all().count() 統計個數
group_list = models.user_group.objects.filter(id=1) group_list = models.user_group.objects.filter(id__gt=1) #大於 group_list = models.user_group.objects.filter(id__lt=1) #小於 print(group_list) #group_list是QuerySet類型,能夠當作列表 group_list QuerySet類型(列表) QuerySet類型[obj,obj,obj] for row in group_list: print(row.id,row.title) models.user_info.objects.all() 刪除 models.user_group.objects.filter(id=2).delete() 更新 models.user_group.objects.filter(id=2).update(title='公關部') 基於ORM實現員工表操做 1.增長 models.UserInfo.objects.create(user='root',password='123',age=10,ug_id=1) obj = models.UserGroup.objects.filter(id=1).first() #直接取一個值
models.UserInfo.objects.create(user='root',password='123',age=10,ug=obj) 2. 刪除: models.UserInfo.objects.filter(id=2).delete() 3. 修改: models.UserInfo.objects.filter(id=2).update(title='公關部') 4. 查詢: group_list = models.UserInfo.objects.all() group_list獲取的是QuerySet,內部元素是UserInfo對象,每個對象代指一行數據, 對象中若是包含ForeignKey,則代指與其關聯表的一行數據 for row in group_list: print(row.user) print(row.age) print(row.ug_id) # 用戶信息關聯的部門ID print(row.ug.title) # 用戶信息關聯的部門名稱
# 獲取QuerySet(查詢集) 1.正向操做、反向操做(連表查詢) QuerySet[obj,obj,obj] result = models.UserInfo.objects.all() for obj in result: print(obj.name,obj.age,obj.ut_id,obj.ut.title) 正向操做
UserInfo,ut是FK字段 - PS: 一個用戶只有一個用戶類型 obj = models.UserInfo.objects.all().first() print(obj.name,obj.age,obj.ut.title) 反向操做
UserType, 表名小寫_set.all() - PS: 一個用戶類型下能夠有不少用戶 obj = models.UserType.objects.all().first() print('用戶類型',obj.id,obj.title) for row in obj.userinfo_set.all(): print(row.name,row.age) result = models.UserType.objects.all() for item in result: print(item.title,item.userinfo_set.filter(name='xx'))
2.數據獲取多個數據時 1.列表查詢集 [obj,obj,obj,] models.UserInfo.objects.all() models.UserInfo.objects.filter(id__gt=1) result = models.UserInfo.objects.all() for item in result: print(item.name,item.ut.title) 反向跨表:
1. 小寫的表名_set
obj = UserGroup.objects.all().first()
result = obj.userinfo_set.all() [userinfo對象,userinfo對象,]
2.字典查詢集 [{id:1,name:fd},{id:1,name:fd},{id:1,name:fd},] models.UserInfo.objects.all().values('id','name') models.UserInfo.objects.filter(id__gt=1).values('id','name') 沒法跨表 result = models.UserInfo.objects.all().values('id','name') for item in result: print(item['id'],item['name']) 字典查詢集正向跨表 __ result = models.UserInfo.objects.all().values('id','name',"ut__title") for item in result: print(item['id'],item['name'],item['ut__title']) 反向跨表:
2. 小寫的表名
v = UserGroup.objects.values('id','title')
v = UserGroup.objects.values('id','title','小寫的表名稱')
v = UserGroup.objects.values('id','title','小寫的表名稱__age')
3.元組查詢集 [(1,df),(2,'df')] models.UserInfo.objects.all().values_list('id','name') models.UserInfo.objects.filter(id__gt=1).values_list('id','name') 沒法跨表 result = models.UserInfo.objects.all().values_list('id','name') for item in result: print(item[0],item[1]) 元組查詢集正向跨表 __ result = models.UserInfo.objects.all().values_list('id','name',"ut__title") for item in result: print(item[0],item[1],item[2])
反向跨表:
3. 小寫的表名
v = UserGroup.objects.values_list('id','title')
v = UserGroup.objects.values_list('id','title','小寫的表名稱')
v = UserGroup.objects.values_list('id','title','小寫的表名稱__age')
select_related()主要針一對一和多對一關係進行優化,使用SQL的JOIN語句進行優化css
prefetch_related()對於多對多字段和一對多字段進行優化html
參考:http://blog.csdn.net/secretx/article/details/43964607python
select_related: 查詢主動作連表,連表查詢速度慢(適用外鍵對應的表數據量少時使用) q = models.UserInfo.objects.all().select_related('ut','gp') # select * from userinfo # select * from userinfo inner join usertype on ... for row in q: print(row.name,row.ut.title) prefetch_related: 不作連表,作屢次查詢(使用外鍵對應的表數據量大,數據頻繁查詢時使用) q = models.UserInfo.objects.all().prefetch_related('ut') # select * from userinfo; # Django內部:ut_id = [2,4] # select * from usertype where id in [2,4] for row in q: print(row.id,row.ut.title)
related_query_name和related_name的操做:mysql
class Boy(models.Model): name=models.CharField(max_length=32) bpwd = models.IntegerField() class Girl(models.Model): nick = models.CharField(max_length=32) gpwd = models.IntegerField() class Love(models.Model): b=models.ForeignKey('Boy') g=models.ForeignKey('Girl') #能夠如上這麼寫,會自動關聯表的自增id,也能夠指定表和關聯id,以下: #b = models.ForeignKey(to='Boy',to_field='id') #g = models.ForeignKey(to='Girl',to_field='id')
class UserInfo(models.Model): nickname = models.CharField(max_length=32) username = models.CharField(max_length=32) password = models.CharField(max_length=64) gender_choices = ( (1,'男'), (2,'女'), ) gender = models.IntegerField(choices=gender_choices) class U2U(models.Model): #g = models.ForeignKey('UserInfo',related_query_name='boys') #b = models.ForeignKey('UserInfo',related_query_name='girls') g = models.ForeignKey('UserInfo',related_name='boys') b = models.ForeignKey('UserInfo',related_name='girls') 外鍵的操做: related_query_name obj對象男.girls_set.all() obj對象女.boys_set.all() related_name obj對象男.girls.all() obj對象女.boys.all() def test(request): #兩種建立數據的方式: models.U2U.objects.create(b_id=2,g_id=6) models.U2U.objects.create(b_id=1,g_id=6) boy = models.UserInfo.objects.filter(gender=1,id=2).first() girl = models.UserInfo.objects.filter(gender=2,id=6).first() models.U2U.objects.create(b=boy,g=girl) #建立數據時能夠放對象 外鍵的操做舉例: UserInfo對象 xz = models.UserInfo.objects.filter(id=1).first() # 和徐崢有關係的全部信息:U2U列表[U2U對象,2U對象,2U對象,] result = xz.girls.all() for u in result: # U2U對象 print(u.g.nickname)
v.query 查詢原生sql語句
一對一操做的正反向:ajax
# obj = models.Blog.objects.filter(site=site).first()
# print(obj.user.nickname)
# obj = models.UserInfo.objects.filter(username='sw').first() # print(obj.blog.site) onetoone 反向操做時
多對多操做:有外鍵的狀況查詢操做sql
class Boy(models.Model): name = models.CharField(max_length=32) class Girl(models.Model): nick = models.CharField(max_length=32) class Love(models.Model): b = models.ForeignKey('Boy') g = models.ForeignKey('Girl') class Meta: #聯合惟一索引 unique_together = [ ('b','g'), ] 1. 和方少偉有關係的姑娘 obj = models.Boy.objects.filter(name='方少偉').first() love_list = obj.love_set.all() for row in love_list: print(row.g.nick) love_list = models.Love.objects.filter(b__name='方少偉') for row in love_list: print(row.g.nick) 連表操做: love_list = models.Love.objects.filter(b__name='方少偉').values('g__nick') for item in love_list: print(item['g__nick']) 連表操做: love_list = models.Love.objects.filter(b__name='方少偉').select_related('g') for obj in love_list: print(obj.g.nick)
多對多操做:ManyToManyField、雜交、自定義關係表數據庫
1. ManyToManyField class Boy(models.Model): name = models.CharField(max_length=32) m = models.ManyToManyField('Girl') #django內置方式這一行會生成第三張關係表,即app01_boy_m,只能生成三列,若是有多行信息,本身寫在第三張表 #m = models.ManyToManyField('Girl',through="Love",through_fields=('b','g',)) #雜交,若是這樣寫就只生成LOVE表 class Girl(models.Model): nick = models.CharField(max_length=32) #自定義關係表 #class Love(models.Model): # b = models.ForeignKey('Boy') # g = models.ForeignKey('Girl') # class Meta: #聯合惟一索引 # unique_together = [ # ('b','g'), # ] 增長: obj = models.Boy.objects.filter(name='方少偉').first() print(obj.id,obj.name) obj.m.add(2) obj.m.add(2,4) obj.m.add(*[1,]) 刪除: obj.m.remove(1) obj.m.remove(2,3) obj.m.remove(*[4,]) 覆蓋修改: obj.m.set([1,]) q = obj.m.all() # [Girl對象] print(q) obj = models.Boy.objects.filter(name='方少偉').first() girl_list = obj.m.all() obj = models.Boy.objects.filter(name='方少偉').first() girl_list = obj.m.all() girl_list = obj.m.filter(nick='小魚') print(girl_list) 刪除第三張表的數據: obj = models.Boy.objects.filter(name='方少偉').first() obj.m.clear() 反向操做: obj = models.Girl.objects.filter(nick='小魚').first() print(obj.id,obj.nick) v = obj.boy_set.all() print(v) 2.雜交: #m = models.ManyToManyField('Girl',through="Love",through_fields=('b','g',)) obj = models.Boy.objects.filter(name='方少偉').first() # obj.m.add(1) 由於有ManyToManyField,因此不行,由於可能第三張表還有其餘列 # obj.m.remove(1) 由於有ManyToManyField,因此不行,由於可能第三張表還有其餘列 # obj.m.clear() 能夠 v = obj.m.all() 能夠 print(v) 3. 自定義關係表
多對多操做,有無第三張表的狀況:django
# 本身反向關聯,須要通多中間的表 # v= models.Article.objects.filter(blog=blog,article2tag__tag=val) # 經過M2M字段,直接關聯到另外一張表,跳過中間件 # v= models.Article.objects.filter(blog=blog,tags__nid=val)
class Article(models.Model): nid = models.BigAutoField(primary_key=True) title = models.CharField(verbose_name='文章標題',max_length=128) summary = models.CharField(verbose_name='文章簡介',max_length=255) read_count = models.IntegerField(default=0) comment_count = models.IntegerField(default=0) up_count = models.IntegerField(default=0) down_count = models.IntegerField(default=0) create_time = models.DateTimeField(verbose_name='建立時間',auto_now_add=True) blog = models.ForeignKey(verbose_name='所屬博客',to='Blog',to_field='nid') category = models.ForeignKey(verbose_name='文章類型',to='Category',to_field='nid',null=True) type_choices=[ (1,'Python'), (2,'Linux'), (3,'OpenStack'), (4,'GoLang'), ] article_type_id = models.IntegerField(choices=type_choices,default=None) tags = models.ManyToManyField( to = 'Tag', through='Article2Tag', through_fields=('article','tag'), ) class Tag(models.Model): nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='標籤名稱',max_length=32) blog = models.ForeignKey(verbose_name='所屬博客',to='Blog',to_field='nid') class Article2Tag(models.Model): article = models.ForeignKey(verbose_name='文章',to='Article',to_field='nid') tag = models.ForeignKey(verbose_name='標籤',to='Tag',to_field='nid') class Meta: unique_together =[ ('article','tag'), ]
分組: bootstrap
""" 1. 分類 category_list = models.Article.objects.filter(blog=blog).values('category_id','category__title',).annotate(c=Count('nid')) 2. 標籤 tag_list = models.Article2Tag.objects.filter(tag__blog=blog).values('tag_id','tag__title').annotate(c=Count('id')) 3. 時間 # MySQL # date_list = models.Article.objects.filter(blog=blog).extra(select={'c': "date_format(create_time,'%%Y-%%m')"}).values('c').annotate(ct=Count('nid')) # SQLlite # date_list = models.Article.objects.filter(blog=blog).extra(select={'c': "strftime('%%Y-%%m',create_time)"}).values('c').annotate(ct=Count('nid')) """ mysql: date_list = models.Article.objects.filter(blog=blog).values("date_format(create_time,'%%Y-%%m')").annotate(ct=Count('nid')) #錯誤,values裏面參數只能是列名 # date_list = models.Article.objects.filter(blog=blog).extra(select={'c': "date_format(create_time,'%%Y-%%m')"}).values('c').annotate(ct=Count('nid')
類型處理:後端
from django.db.models import functions # models.Article.objects.filter(blog=blog).annotate(x=functions.Extract('create_time','YEAR_MONTH')) # models.Article.objects.filter(blog=blog).annotate(x=functions.ExtractYear('create_time')) """ nid xx create_time x 1 x 2018-09-01 11:11 201809 2 x 2018-09-01 11:11 2018 """ # models.Article.objects.filter(blog=blog).annotate(x=functions.TruncMonth('create_time')) # models.Article.objects.filter(blog=blog).annotate(x=functions.Trunc('create_time','')) """ nid xx create_time x 1 x 2018-09-01 11:11 09 """ # from django.db.models import FloatField # from django.db.models import Value # v = models.Article.objects.annotate(c=functions.Cast('nid', FloatField())) #類型轉換 # v = models.Article.objects.annotate(c=functions.Coalesce('title','summary')) #找到第一個非空 # v = models.Article.objects.annotate(c=functions.Concat('nid','title','summary')) #拼接 # v = models.Article.objects.annotate(c=functions.Concat('nid','title','summary',Value('666'))) # v = models.Article.objects.annotate(c=functions.Greatest('nid','num')) #取較大的值 # v = models.Article.objects.annotate(c=functions.Length('title')) #獲取長度 # v = models.Article.objects.annotate(c=functions.Substr('title',1,1)) #取自定長度的字符串,只能從第一位開始
進階操做:
# 1.增刪改查 # 2. 通常: # models.UserInfo.objects.filter(id__gt=1) 大於 # models.UserInfo.objects.filter(id__lt=1) 小於 # models.UserInfo.objects.filter(id__gte=1) 大於等於 # models.UserInfo.objects.filter(id__lte=1) 小於等於 # models.UserInfo.objects.filter(id__in=[1,2,3]) # models.UserInfo.objects.filter(id__range=[1,2]) # models.UserInfo.objects.filter(name__startswith='xxxx') 以xxxx開頭 # models.UserInfo.objects.filter(name__contains='xxxx') 內容包含xxxx # models.UserInfo.objects.filter(name__icontains='xxxx') 內容包含xxxx,不區分大小寫 # models.UserInfo.objects.exclude(id=1) 不等於exclude models.UserInfo.filter(age__isnull=True) 數據爲空也能夠查詢 # 3. 排序 user_list = models.UserInfo.objects.all().order_by('-id','name') 反向排序 user_list = models.UserInfo.objects.all().order_by('id','name') 正向排序 # 4. 分組 from django.db.models import Count,Sum,Max,Min 分組: v =models.UserInfo.objects.values('ut_id').annotate(xxxx=Count('id')) print(v.query) 結果: #SELECT "app01_userinfo"."ut_id", COUNT("app01_userinfo"."id") AS "xxxx" FROM "app01_userinfo" GROUP BY "app01_userinfo"."ut_id" 分組後再篩選: v =models.UserInfo.objects.values('ut_id').annotate(xxxx=Count('id')).filter(xxxx__gt=2) print(v.query) 結果: SELECT "app01_userinfo"."ut_id", COUNT("app01_userinfo"."id") AS "xxxx" FROM "app01_userinfo" GROUP BY "app01_userinfo"."ut_id" HAVING COUNT("app01_userinfo"."id") > 2 v =models.UserInfo.objects.filter(id__gt=2).values('ut_id').annotate(xxxx=Count('id')).filter(xxxx__gt=2) print(v.query) 結果: SELECT "app01_userinfo"."ut_id", COUNT("app01_userinfo"."id") AS "xxxx" FROM "app01_userinfo" WHERE "app01_userinfo"."id" > 2 GROUP BY "app01_userinfo"."ut_id" HAVING COUNT("app01_userinfo"."id") > 2 5. F,更新時用於獲取原來的值 from django.db.models import F,Q 更新數據庫一列: models.UserInfo.objects.all().update(age=F("age")+1) 6. Q,用於構造複雜查詢條件 # 應用一: # models.UserInfo.objects.filter(Q(id__gt=1)) # models.UserInfo.objects.filter(Q(id=8) | Q(id=2)) # models.UserInfo.objects.filter(Q(id=8) & Q(id=2)) # 應用二: models.UserInfo.objects.filter(id=1,name='root') condition = { 'id':1, 'name': 'root' } models.UserInfo.objects.filter(**condition) 自動添加Q condition_dict = { 'k1':[1,2,3,4], 'k2':[1,], } con = Q() for k,v in condition_dict.items(): q = Q() q.connector = 'OR' for i in v: q.children.append(('id', i)) con.add(q,'AND'