第十九章 Django進階html
到目前爲止,當咱們的程序涉及到數據庫相關操做時,咱們通常都會這麼搞:python
import MySQLdb def GetList(sql): db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost') cursor = db.cursor() cursor.execute(sql) data = cursor.fetchall() db.close() return data def GetSingle(sql): db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost') cursor = db.cursor() cursor.execute(sql) data = cursor.fetchone() db.close() return data
django爲使用一種新的方式,即:關係對象映射(Object Relational Mapping,簡稱ORM)。mysql
PHP:activerecordgit
Java:Hibernate 正則表達式
C#:Entity Frameworksql
django中遵循 Code Frist 的原則,即:根據代碼中定義的類來自動生成數據庫表。數據庫
1、建立表django
一、基本結構json
1 from django.db import models 2 3 class userinfo(models.Model): 4 name = models.CharField(max_length=30) 5 email = models.EmailField() 6 memo = models.TextField()
1 一、models.AutoField 自增列 = int(11) 2 若是沒有的話,默認會生成一個名稱爲 id 的列,若是要顯示的自定義一個自增列,必須將給列設置爲主鍵 primary_key=True。 3 2、models.CharField 字符串字段 4 必須 max_length 參數 5 三、models.BooleanField 布爾類型=tinyint(1) 6 不能爲空,Blank=True 7 四、models.ComaSeparatedIntegerField 用逗號分割的數字=varchar 8 繼承CharField,因此必須 max_lenght 參數 9 5、models.DateField 日期類型 date 10 對於參數,auto_now = True 則每次更新都會更新這個時間;auto_now_add 則只是第一次建立添加,以後的更新再也不改變。 11 6、models.DateTimeField 日期類型 datetime 12 同DateField的參數 13 七、models.Decimal 十進制小數類型 = decimal 14 必須指定整數位max_digits和小數位decimal_places 15 八、models.EmailField 字符串類型(正則表達式郵箱) =varchar 16 對字符串進行正則表達式 17 九、models.FloatField 浮點類型 = double 18 10、models.IntegerField 整形 19 11、models.BigIntegerField 長整形 20 integer_field_ranges = { 21 'SmallIntegerField': (-32768, 32767), 22 'IntegerField': (-2147483648, 2147483647), 23 'BigIntegerField': (-9223372036854775808, 9223372036854775807), 24 'PositiveSmallIntegerField': (0, 32767), 25 'PositiveIntegerField': (0, 2147483647), 26 } 27 12、models.IPAddressField 字符串類型(ip4正則表達式) 28 13、models.GenericIPAddressField 字符串類型(ip4和ip6是可選的) 29 參數protocol能夠是:both、ipv四、ipv6 30 驗證時,會根據設置報錯 31 14、models.NullBooleanField 容許爲空的布爾類型 32 15、models.PositiveIntegerFiel 正Integer 33 16、models.PositiveSmallIntegerField 正smallInteger 34 17、models.SlugField 減號、下劃線、字母、數字 35 18、models.SmallIntegerField 數字 36 數據庫中的字段有:tinyint、smallint、int、bigint 37 1九、models.TextField 字符串=longtext 38 20、models.TimeField 時間 HH:MM[:ss[.uuuuuu]] 39 21、models.URLField 字符串,地址正則表達式 40 22、models.BinaryField 二進制 41 23、models.ImageField 圖片 42 2四、models.FilePathField 文件
二、連表結構session
應用場景:
- 一對多:當一張表中建立一行數據時,有一個單選的下拉框(能夠被重複選擇)
例如:建立用戶信息時候,須要選擇一個用戶類型【普通用戶】【金牌用戶】【鉑金用戶】等。- 多對多:在某表中建立一行數據是,有一個能夠多選的下拉框
例如:建立用戶信息,須要爲用戶指定多個愛好- 一對一:在某表中建立一行數據時,有一個單選的下拉框(下拉框中的內容被用過一次就消失了
例如:原有含10列數據的一張表保存相關信息,通過一段時間以後,10列沒法知足需求,須要爲原來的表再添加5列數據
2、操做表
一、基本操做
1 增 2 # 3 # models.Tb1.objects.create(c1='xx', c2='oo') 增長一條數據,能夠接受字典類型數據 **kwargs 4 5 # obj = models.Tb1(c1='xx', c2='oo') 6 # obj.save() 7 8 # 查 9 # 10 # models.Tb1.objects.get(id=123) # 獲取單條數據,不存在則報錯(不建議) 11 # models.Tb1.objects.all() # 獲取所有 12 # models.Tb1.objects.filter(name='seven') # 獲取指定條件的數據 13 14 # 刪 15 # 16 # models.Tb1.objects.filter(name='seven').delete() # 刪除指定條件的數據 17 18 # 改 19 # models.Tb1.objects.filter(name='seven').update(gender='0') # 將指定條件的數據更新,均支持 **kwargs 20 # obj = models.Tb1.objects.get(id=1) 21 # obj.c1 = '111' 22 # obj.save() # 修改單條數據
二、進階操做(了不得的雙下劃線)
利用雙下劃線將字段和對應的操做鏈接起來
1 # 獲取個數 2 # 3 # models.Tb1.objects.filter(name='seven').count() 4 5 # 大於,小於 6 # 7 # models.Tb1.objects.filter(id__gt=1) # 獲取id大於1的值 8 # models.Tb1.objects.filter(id__lt=10) # 獲取id小於10的值 9 # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 獲取id大於1 且 小於10的值 10 11 # in 12 # 13 # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 獲取id等於十一、2二、33的數據 14 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in 15 16 # contains 17 # 18 # models.Tb1.objects.filter(name__contains="ven") 19 # models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感 20 # models.Tb1.objects.exclude(name__icontains="ven") 21 22 # range 23 # 24 # models.Tb1.objects.filter(id__range=[1, 2]) # 範圍bettwen and 25 26 # 其餘相似 27 # 28 # startswith,istartswith, endswith, iendswith, 29 30 # order by 31 # 32 # models.Tb1.objects.filter(name='seven').order_by('id') # asc 33 # models.Tb1.objects.filter(name='seven').order_by('-id') # desc 34 35 # limit 、offset 36 # 37 # models.Tb1.objects.all()[10:20] 38 39 # group by 40 from django.db.models import Count, Min, Max, Sum 41 # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) 42 # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id" 43 44 進階操做
三、連表操做(了不得的雙下劃線)
利用雙下劃線和 _set 將表之間的操做鏈接起來
class UserProfile(models.Model): user_info = models.OneToOneField('UserInfo') username = models.CharField(max_length=64) password = models.CharField(max_length=64) def __unicode__(self): return self.username class UserInfo(models.Model): user_type_choice = ( (0, u'普通用戶'), (1, u'高級用戶'), ) user_type = models.IntegerField(choices=user_type_choice) name = models.CharField(max_length=32) email = models.CharField(max_length=32) address = models.CharField(max_length=128) def __unicode__(self): return self.name class UserGroup(models.Model): caption = models.CharField(max_length=64) user_info = models.ManyToManyField('UserInfo') def __unicode__(self): return self.caption class Host(models.Model): hostname = models.CharField(max_length=64) ip = models.GenericIPAddressField() user_group = models.ForeignKey('UserGroup') def __unicode__(self): return self.hostname 表結構實例
1 user_info_obj = models.UserInfo.objects.filter(id=1).first() 2 print user_info_obj.user_type 3 print user_info_obj.get_user_type_display() 4 print user_info_obj.userprofile.password 5 6 user_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first() 7 print user_info_obj.keys() 8 print user_info_obj.values() 9 10 一對一操做
一對多相似一對一
1、搜索條件使用 __ 鏈接 二、獲取值時使用 . 鏈接
1 user_info_obj = models.UserInfo.objects.get(name=u'武沛齊') 2 user_info_objs = models.UserInfo.objects.all() 3 4 group_obj = models.UserGroup.objects.get(caption='CEO') 5 group_objs = models.UserGroup.objects.all() 6 7 # 添加數據 8 #group_obj.user_info.add(user_info_obj) 9 #group_obj.user_info.add(*user_info_objs) 10 11 # 刪除數據 12 #group_obj.user_info.remove(user_info_obj) 13 #group_obj.user_info.remove(*user_info_objs) 14 15 # 添加數據 16 #user_info_obj.usergroup_set.add(group_obj) 17 #user_info_obj.usergroup_set.add(*group_objs) 18 19 # 刪除數據 20 #user_info_obj.usergroup_set.remove(group_obj) 21 #user_info_obj.usergroup_set.remove(*group_objs) 22 23 # 獲取數據 24 #print group_obj.user_info.all() 25 #print group_obj.user_info.all().filter(id=1) 26 27 # 獲取數據 28 #print user_info_obj.usergroup_set.all() 29 #print user_info_obj.usergroup_set.all().filter(caption='CEO') 30 #print user_info_obj.usergroup_set.all().filter(caption='DBA') 31 32 多對多操做
1 # F 使用查詢條件的值 2 # 3 # from django.db.models import F 4 # models.Tb1.objects.update(num=F('num')+1) 5 6 # Q 構建搜索條件 7 from django.db.models import Q 8 # con = Q() 9 # 10 # q1 = Q() 11 # q1.connector = 'OR' 12 # q1.children.append(('id', 1)) 13 # q1.children.append(('id', 10)) 14 # q1.children.append(('id', 9)) 15 # 16 # q2 = Q() 17 # q2.connector = 'OR' 18 # q2.children.append(('c1', 1)) 19 # q2.children.append(('c1', 10)) 20 # q2.children.append(('c1', 9)) 21 # 22 # con.add(q1, 'AND') 23 # con.add(q2, 'AND') 24 # 25 # models.Tb1.objects.filter(con) 26 27 # 28 # from django.db import connection 29 # cursor = connection.cursor() 30 # cursor.execute("""SELECT * from tb where name = %s""", ['Lennon']) 31 # row = cursor.fetchone() 32 33 其餘操做
注意:xx_set中的【_set】是多對多中的固定搭配
擴展:
a、自定義上傳
1 def upload_file(request): 2 if request.method == "POST": 3 obj = request.FILES.get('fafafa') 4 f = open(obj.name, 'wb') 5 for chunk in obj.chunks(): 6 f.write(chunk) 7 f.close() 8 return render(request, 'file.html')
b、Form上傳文件實例
class FileForm(forms.Form): ExcelFile = forms.FileField()
from django.db import models class UploadFile(models.Model): userid = models.CharField(max_length = 30) file = models.FileField(upload_to = './upload/') date = models.DateTimeField(auto_now_add=True)
django中的Form通常有兩種功能:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 from django import forms 5 from django.core.exceptions import ValidationError 6 7 8 def mobile_validate(value): 9 mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') 10 if not mobile_re.match(value): 11 raise ValidationError('手機號碼格式錯誤') 12 13 14 class PublishForm(forms.Form): 15 16 user_type_choice = ( 17 (0, u'普通用戶'), 18 (1, u'高級用戶'), 19 ) 20 21 user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice, 22 attrs={'class': "form-control"})) 23 24 title = forms.CharField(max_length=20, 25 min_length=5, 26 error_messages={'required': u'標題不能爲空', 27 'min_length': u'標題最少爲5個字符', 28 'max_length': u'標題最多爲20個字符'}, 29 widget=forms.TextInput(attrs={'class': "form-control", 30 'placeholder': u'標題5-20個字符'})) 31 32 memo = forms.CharField(required=False, 33 max_length=256, 34 widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': u'詳細描述', 'rows': 3})) 35 36 phone = forms.CharField(validators=[mobile_validate, ], 37 error_messages={'required': u'手機不能爲空'}, 38 widget=forms.TextInput(attrs={'class': "form-control", 39 'placeholder': u'手機號碼'})) 40 41 email = forms.EmailField(required=False, 42 error_messages={'required': u'郵箱不能爲空','invalid': u'郵箱格式錯誤'}, 43 widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'郵箱'})) 44 45 Form
def publish(request): ret = {'status': False, 'data': '', 'error': '', 'summary': ''} if request.method == 'POST': request_form = PublishForm(request.POST) if request_form.is_valid(): request_dict = request_form.clean() print request_dict ret['status'] = True else: error_msg = request_form.errors.as_json() ret['error'] = json.loads(error_msg) return HttpResponse(json.dumps(ret)) View
擴展:ModelForm
在使用Model和Form時,都須要對字段進行定義並指定類型,經過ModelForm則能夠省去From中字段的定義
1 class AdminModelForm(forms.ModelForm): 2 3 class Meta: 4 model = models.Admin 5 #fields = '__all__' 6 fields = ('username', 'email') 7 8 widgets = { 9 'email' : forms.PasswordInput(attrs={'class':"alex"}), 10 }
筆記:一、Django請求生命週期 -> URL對應關係(匹配) -> 視圖函數 -> 返回用戶字符串 -> URL對應關係(匹配) -> 視圖函數 -> 打開一個HTML文件,讀取內容 二、建立django projcet django-admin startproject mysite .. mysite mysite - 配置文件 - url.py - settings.py cd mysite python manage.py startapp cmdb mysite mysite - 配置文件 - url.py - settings.py cmdb - views.py - admin.py - models.py # 建立數據庫表 三、配置 模板路徑 靜態文件路徑 # CSRF 四、編寫程序 a. url.py /index/ -> func b. views.py def func(request): # 包含全部的請求數據 ... return HttpResponse('字符串') return render(request, 'index.html', {''}) retrun redirect('URL') c. 模板語言 return render(request, 'index.html', {'li': [11,22,33]}) {% for item in li %} <h1>{{item}}</h1> {% endfor %} *********** 索引用點 ********** <h2> {{item.0 }} </h2>1、路由系統,URL 一、url(r'^index/', views.index), url(r'^home/', views.Home.as_view()), 二、url(r'^detail-(\d+).html', views.detail), 三、url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail) PS: def detail(request, *args,**kwargs): pass 實戰: a. url(r'^detail-(\d+)-(\d+).html', views.detail), def func(request, nid, uid): pass def func(request, *args): args = (2,9) def func(request, *args, **kwargs): args = (2,9) b. url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail) def func(request, nid, uid): pass def funct(request, **kwargs): kwargs = {'nid': 1, 'uid': 3} def func(request, *args, **kwargs): args = (2,9) 四、 name 對URL路由關係進行命名, ***** 之後能夠根據此名稱生成本身想要的URL ***** url(r'^asdfasdfasdf/', views.index, name='i1'), url(r'^yug/(\d+)/(\d+)/', views.index, name='i2'), url(r'^buy/(?P<pid>\d+)/(?P<nid>\d+)/', views.index, name='i3'), def func(request, *args, **kwargs): from django.urls import reverse url1 = reverse('i1') # asdfasdfasdf/ url2 = reverse('i2', args=(1,2,)) # yug/1/2/ url3 = reverse('i3', kwargs={'pid': 1, "nid": 9}) # buy/1/9/ xxx.html {% url "i1" %} # asdfasdfasdf/ {% url "i2" 1 2 %} # yug/1/2/ {% url "i3" pid=1 nid=9 %} # buy/1/9/ 注: # 當前的URL request.path_info 五、多級路由 project/urls.py from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ url(r'^cmdb/', include("app01.urls")), url(r'^monitor/', include("app02.urls")), ] app01/urls.py from django.conf.urls import url,include from django.contrib import admin from app01 import views urlpatterns = [ url(r'^login/', views.login), ] app02/urls.py from django.conf.urls import url,include from django.contrib import admin from app02 import views urlpatterns = [ url(r'^login/', views.login), ] 六、默認值(欠) 七、命名空間(欠) 2、視圖 一、獲取用戶請求數據 request.GET request.POST request.FILES PS: GET:獲取數據 POST:提交數據 二、checkbox等多選的內容 request.POST.getlist() 三、上傳文件 # 上傳文件,form標籤作特殊設置 obj = request.FILES.get('fafafa') obj.name f = open(obj.name, mode='wb') for item in obj.chunks(): f.write(item) f.close() 四、FBV & CBV function base view url.py index -> 函數名 view.py def 函數(request): ... ====》 /index/ -> 函數名 /index/ -> 類 ====》 建議:二者都用 五、裝飾器 欠 3、模板 4、ORM操做 select * from tb where id > 1 # 對應關係 models.tb.objects.filter(id__gt=1) models.tb.objects.filter(id=1) models.tb.objects.filter(id__lt=1) 建立類 a. 先寫類 from django.db import models # app01_userinfo class UserInfo(models.Model): # id列,自增,主鍵 # 用戶名列,字符串類型,指定長度 username = models.CharField(max_length=32) password = models.CharField(max_length=64) b. 註冊APP INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', ] c. 執行命令 python manage.py makemigrations python manage.py migrate d. ********** 注意 *********** Django默認使用MySQLdb模塊連接MySQL 主動修改成pymysql,在project同名文件夾下的__init__文件中添加以下代碼便可: import pymysql pymysql.install_as_MySQLdb() 1. 根據類自動建立數據庫表 # app下的models.py python manage.py makemigrations python manage.py migrate 字段: 字符串類型 數字 時間 二進制 自增(primary_key=True) 字段的參數: null -> db是否能夠爲空 default -> 默認值 primary_key -> 主鍵 db_column -> 列名 db_index -> 索引 unique -> 惟一索引 unique_for_date -> unique_for_month unique_for_year auto_now -> 建立時,自動生成時間 auto_now_add -> 更新時,自動更新爲當前時間 # obj = UserGroup.objects.filter(id=1).update(caption='CEO') # obj = UserGroup.objects.filter(id=1).first() # obj.caption = "CEO" # obj.save() choices -> django admin中顯示下拉框,避免連表查詢 blank -> django admin是否能夠爲空 verbose_name -> django admin顯示字段中文 editable -> django admin是否能夠被編輯 error_messages -> 錯誤信息欠 help_text -> django admin提示 validators -> django form ,自定義錯誤信息(欠) 建立 Django 用戶:python manage.py createsuperuser 2. 根據類對數據庫表中的數據進行各類操做 一對多: a. 外檢 b. 外鍵字段_id c. models.tb.object.create(name='root', user_group_id=1) d. userlist = models.tb.object.all() for row in userlist: row.id row.user_group_id row.user_group.caption