【python】-- Django ORM(基礎)

Django ORM(基礎)

Django 框架十分強大,自帶數據庫操做功能。Django 跟 SQLAchemy 同樣,也是經過ORM(Object Relational Mapping,關係對象映射)的方式對數據庫進行操做,django中遵循 Code Frist (根據代碼中定義的類來自動生成數據庫表)的原則。html

 

1、建立表

一、在SQLite中建立表python

1.一、在app中的models.py中先寫類:mysql

from django.db import models
# Create your models here.


class UserInfo(models.Model):
    # id列,Django框架會默認生成id(自增,主鍵),也能夠經過AutoField類型自定義主鍵,不過Django框架默認生成ID列會失效
    # 用戶名列,字符串類型,最大長度長度
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
  1  AutoField(Field)
  2         - int自增列,必須填入參數 primary_key=True
  3 
  4     BigAutoField(AutoField)
  5         - bigint自增列,必須填入參數 primary_key=True
  6 
  7         注:當model中若是沒有自增列,則自動會建立一個列名爲id的列
  8         from django.db import models
  9 
 10         class UserInfo(models.Model):
 11             # 自動建立一個列名爲id的且爲自增的整數列
 12             username = models.CharField(max_length=32)
 13 
 14         class Group(models.Model):
 15             # 自定義自增列
 16             nid = models.AutoField(primary_key=True)
 17             name = models.CharField(max_length=32)
 18 
 19     SmallIntegerField(IntegerField):
 20         - 小整數 -3276832767
 21 
 22     PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
 23         - 正小整數 032767
 24     IntegerField(Field)
 25         - 整數列(有符號的) -21474836482147483647
 26 
 27     PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
 28         - 正整數 02147483647
 29 
 30     BigIntegerField(IntegerField):
 31         - 長整型(有符號的) -92233720368547758089223372036854775807
 32 
 33     自定義無符號整數字段
 34 
 35         class UnsignedIntegerField(models.IntegerField):
 36             def db_type(self, connection):
 37                 return 'integer UNSIGNED'
 38 
 39         PS: 返回值爲字段在數據庫中的屬性,Django字段默認的值爲:
 40             'AutoField': 'integer AUTO_INCREMENT',
 41             'BigAutoField': 'bigint AUTO_INCREMENT',
 42             'BinaryField': 'longblob',
 43             'BooleanField': 'bool',
 44             'CharField': 'varchar(%(max_length)s)',
 45             'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
 46             'DateField': 'date',
 47             'DateTimeField': 'datetime',
 48             'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
 49             'DurationField': 'bigint',
 50             'FileField': 'varchar(%(max_length)s)',
 51             'FilePathField': 'varchar(%(max_length)s)',
 52             'FloatField': 'double precision',
 53             'IntegerField': 'integer',
 54             'BigIntegerField': 'bigint',
 55             'IPAddressField': 'char(15)',
 56             'GenericIPAddressField': 'char(39)',
 57             'NullBooleanField': 'bool',
 58             'OneToOneField': 'integer',
 59             'PositiveIntegerField': 'integer UNSIGNED',
 60             'PositiveSmallIntegerField': 'smallint UNSIGNED',
 61             'SlugField': 'varchar(%(max_length)s)',
 62             'SmallIntegerField': 'smallint',
 63             'TextField': 'longtext',
 64             'TimeField': 'time',
 65             'UUIDField': 'char(32)',
 66 
 67     BooleanField(Field)
 68         - 布爾值類型
 69 
 70     NullBooleanField(Field):
 71         - 能夠爲空的布爾值
 72 
 73     CharField(Field)
 74         - 字符類型
 75         - 必須提供max_length參數, max_length表示字符長度
 76 
 77     TextField(Field)
 78         - 文本類型
 79 
 80     EmailField(CharField):
 81         - 字符串類型,Django Admin以及ModelForm中提供驗證機制
 82 
 83     IPAddressField(Field)
 84         - 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制
 85 
 86     GenericIPAddressField(Field)
 87         - 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6
 88         - 參數:
 89             protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
 90             unpack_ipv4, 若是指定爲True,則輸入::ffff:192.0.2.1時候,可解析爲192.0.2.1,開啓刺功能,須要protocol="both"
 91 
 92     URLField(CharField)
 93         - 字符串類型,Django Admin以及ModelForm中提供驗證 URL
 94 
 95     SlugField(CharField)
 96         - 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下劃線、鏈接符(減號)
 97 
 98     CommaSeparatedIntegerField(CharField)
 99         - 字符串類型,格式必須爲逗號分割的數字
100 
101     UUIDField(Field)
102         - 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證
103 
104     FilePathField(Field)
105         - 字符串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能
106         - 參數:
107                 path,                      文件夾路徑
108                 match=None,                正則匹配
109                 recursive=False,           遞歸下面的文件夾
110                 allow_files=True,          容許文件
111                 allow_folders=False,       容許文件夾
112 
113     FileField(Field)
114         - 字符串,路徑保存在數據庫,文件上傳到指定目錄
115         - 參數:
116             upload_to = ""      上傳文件的保存路徑
117             storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage
118 
119     ImageField(FileField)
120         - 字符串,路徑保存在數據庫,文件上傳到指定目錄
121         - 參數:
122             upload_to = ""      上傳文件的保存路徑
123             storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage
124             width_field=None,   上傳圖片的高度保存的數據庫字段名(字符串)
125             height_field=None   上傳圖片的寬度保存的數據庫字段名(字符串)
126 
127     DateTimeField(DateField)
128         - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
129 
130     DateField(DateTimeCheckMixin, Field)
131         - 日期格式      YYYY-MM-DD
132 
133     TimeField(DateTimeCheckMixin, Field)
134         - 時間格式      HH:MM[:ss[.uuuuuu]]
135 
136     DurationField(Field)
137         - 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型
138 
139     FloatField(Field)
140         - 浮點型
141 
142     DecimalField(Field)
143         - 10進制小數
144         - 參數:
145             max_digits,小數總長度
146             decimal_places,小數位長度
147 
148     BinaryField(Field)
149         - 二進制類型
models字段類型
 1 class User(models.Model):
 2     name = models.CharField(max_length=32)
 3     pwd = models.CharField(max_length=32)
 4 #class User(models.Model):
 5 #    name = models.CharField(max_length=32,db_index=True)
 6 #    pwd = models.CharField(max_length=32,db_index=True)
 7 class Meta:
 8     #指定數據庫表名:tb1,若是不指定表名將會默認生成表名:app名稱 + 下劃線 + 類名
 9     db_table = "tb1"
10 
11     #索引,mysql每一列加上索引就會生成一個文件,所以當上面被註釋的User表生成是mysql數據庫就會生成一個表,兩個文件,
12     #所以不想數據庫生成太多索引文件,又想個別列名可以支持索引查詢,這個時候就須要用到聯合索引,
13     index_together = [  # 聯合索引,只會生成一個索引文件 可是有一個缺點就是,遵循最左前綴模式查詢
14         ("name", 'pwd'),
15     ]
16 
17     # 最左前綴的模式:
18     # select * from where name='xx'
19     # select * from where name='xx' and email = 'xx'
20     # select * from where email = 'xx' # 沒法命中索引
21 
22     #聯合惟一索引,與上面的聯合索引同樣,就是多了一個列名組合惟一的限制
23     unique_together = (("driver", "restaurant"),)
24 
25     #admin中的配置
26     verbose_name = 「name」  #在admin中會將name顯示成names,多加一個「s」
27     verbose_name_plural=「「name」」  #在admin中會將name顯示成name,顯示原生自定義的名字
db_table、聯合索引、聯合惟一索引
 1     null                數據庫中字段是否能夠爲空
 2     db_column           數據庫中字段的列名
 3     db_tablespace
 4     default             數據庫中字段的默認值
 5     primary_key         數據庫中字段是否爲主鍵
 6     db_index            數據庫中字段是否能夠創建索引
 7     unique              數據庫中字段是否能夠創建惟一索引
 8     unique_for_date     數據庫中字段【日期】部分是否能夠創建惟一索引
 9     unique_for_month    數據庫中字段【月】部分是否能夠創建惟一索引
10     unique_for_year     數據庫中字段【年】部分是否能夠創建惟一索引
11 
12     verbose_name        Admin中顯示的字段名稱
13     blank               Admin中是否容許用戶輸入爲空
14     editable            Admin中是否能夠編輯
15     help_text           Admin中該字段的提示信息
16     choices             Admin中顯示選擇框的內容,用不變更的數據放在內存中從而避免跨表操做
17                         如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) 想要在HTML中顯示choice中的字段值,而不是數學索引,須要用到{{k.get_帶choices參數的字段_display}}方法
18 
19     error_messages      自定義錯誤信息(字典類型),從而定製想要顯示的錯誤信息;
20                         字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
21                         如:{'null': "不能爲空.", 'invalid': '格式錯誤'}
22 
23     validators          自定義錯誤驗證(列表類型),從而定製想要的驗證規則
24                         from django.core.validators import RegexValidator
25                         from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
26                         MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
27                         如:
28                             test = models.CharField(
29                                 max_length=32,
30                                 error_messages={
31                                     'c1': '優先錯信息1',
32                                     'c2': '優先錯信息2',
33                                     'c3': '優先錯信息3',
34                                 },
35                                 validators=[
36                                     RegexValidator(regex='root_\d+', message='錯誤了', code='c1'),
37                                     RegexValidator(regex='root_112233\d+', message='又錯誤了', code='c2'),
38                                     EmailValidator(message='又錯誤了', code='c3'), ]
39                             )
models中的參數

1.二、在settings.py中註冊app:git

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app1',
]

1.三、在控制檯輸出cmd 命令:sql

python3 manage.py  makemigrations #至關於在該app的migrations目錄,記錄下該app下modes.py全部表結構類型的改動(普通增刪改查不記錄)
python3 manage.py  migrate        #將剛剛對於表結構的改動做用至數據庫

  

二、在MySQL中建立表數據庫

2.一、在上面步驟1.1 先寫類、1.2 註冊app的基礎上,在與Django project中與project同名目錄下的__init__.py文件中配置以下代碼:django

import pymysql
pymysql.install_as_MySQLdb()

注:# 因爲Django內部鏈接MySQL時使用的是MySQLdb模塊,而python3中還無此模塊,因此須要使用pymysql來代替json

2.2,在settings.py中更改數據庫配置session

#將原先數據庫配置註釋,使用mysql配置
# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }



DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test1',       # 數據庫名稱
        'USER': 'root',         # 用戶名
        'PASSWORD': '123456',      # 密碼
        'HOST': 'localhost',             # ip
        'PORT': '3306',             # 端口
    }
}

2.三、執行命令app

python3 manage.py  makemigrations
python3 manage.py  migrate  

注:配置好數據庫爲mysql後,從新啓動Django工程,若是報錯mysql django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.3 or newer is required;的話, 這是由於 mysql client 端的版本小於1.3.3。最簡單的解決辦法是:

#找到Django的安裝路徑的mysql配置下的base.py,如C:\Python36\Lib\site-packages\django\db\backends\mysql\base.py(根據實際安裝路徑)
#註釋這句斷言:
#if version < (1, 3, 3):
    #raise ImproperlyConfigured("mysqlclient 1.3.3 or newer is required; you have %s" % Database.__version__)

 

 

2、增刪改查

 利用Django的ORM鏈接數據庫進行增刪改查和其餘一些進階操做。

一、增:

# 第一種方式
models.UserInfo.objects.create(username='root', password='123')
# 第二種方式
dic = {'username': 'root1', 'password': '456'}
models.UserInfo.objects.create(**dic)
#第三種方式
obj = models.UserInfo(username='root2', password='789')
obj.save()

二、刪:

models.UserInfo.objects.filter(id="2").delete()

三、改:

models.UserInfo.objects.filter(id=1).update(password="111")

四、查:

models.User.objects.filter(id=1)             #id=1
models.User.objects.filter(id=1,name='root') #id=1 and name = root
models.User.objects.filter(id__gt=1)         #id>1
models.User.objects.filter(id__lt=1)	     #id<1
models.User.objects.filter(id__gte=1)		 #id>=1
models.User.objects.filter(id__lte=1)		 #id<=1
models.Tb1.objects.filter(id__lt=10, id__gt=1)  #1<id<10 dic = {'name': 'xx', 'age__gt': 19} #**字典形式多條件查詢 models.User.objects.filter(**dic) models.Business.objects.all() #QuerySet ,內部元素都是對象 [obj(id,caption,code),obj(id,caption,code),obj(id,caption,code) ] models.Business.objects.all().values('id','caption') # QuerySet ,內部元素都是字典 [{'id':1,'code': 'QA'},{'id':2,'code': 'PM'},...] models.Business.objects.all().values_list('id','caption') # QuerySet ,內部元素都是元組 [(1,"QA"),(2,"PM")] models.Business.objects.get(id=1) # 獲取到的一個對象,若是不存在就報錯 models.Business.objects.filter(id=1).first() # 獲取到的一個對象,若是不存在返回NONE

五、更多進階操做:

 1 # 獲取個數
 2         #
 3         # models.Tb1.objects.filter(name='seven').count()
 4 
 5         # in
 6         #
 7         # models.Tb1.objects.filter(id__in=[11, 22, 33])   # 獲取id等於十一、2二、33的數據
 8         # models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
 9 
10         # isnull
11         # Entry.objects.filter(pub_date__isnull=True)
12 
13         # contains
14         #
15         # models.Tb1.objects.filter(name__contains="ven")
16         # models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感
17         # models.Tb1.objects.exclude(name__icontains="ven")
18 
19         # range
20         #
21         # models.Tb1.objects.filter(id__range=[1, 2])   # 範圍bettwen and
22 
23         # 其餘相似
24         #
25         # startswith,istartswith, endswith, iendswith,
26 
27         # order by
28         #
29         # models.Tb1.objects.filter(name='seven').order_by('id')    # asc
30         # models.Tb1.objects.filter(name='seven').order_by('-id')   # desc
31 
32         # group by
33         #
34         # from django.db.models import Count, Min, Max, Sum
35         # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
36         # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
37 
38         # limit 、offset
39         #
40         # models.Tb1.objects.all()[10:20]
41 
42         # regex正則匹配,iregex 不區分大小寫
43         #
44         # Entry.objects.get(title__regex=r'^(An?|The) +')
45         # Entry.objects.get(title__iregex=r'^(an?|the) +')
46 
47         # date
48         #
49         # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
50         # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))
51 
52         # year
53         #
54         # Entry.objects.filter(pub_date__year=2005)
55         # Entry.objects.filter(pub_date__year__gte=2005)
56 
57         # month
58         #
59         # Entry.objects.filter(pub_date__month=12)
60         # Entry.objects.filter(pub_date__month__gte=6)
61 
62         # day
63         #
64         # Entry.objects.filter(pub_date__day=3)
65         # Entry.objects.filter(pub_date__day__gte=3)
66 
67         # week_day
68         #
69         # Entry.objects.filter(pub_date__week_day=2)
70         # Entry.objects.filter(pub_date__week_day__gte=2)
71 
72         # hour
73         #
74         # Event.objects.filter(timestamp__hour=23)
75         # Event.objects.filter(time__hour=5)
76         # Event.objects.filter(timestamp__hour__gte=12)
77 
78         # minute
79         #
80         # Event.objects.filter(timestamp__minute=29)
81         # Event.objects.filter(time__minute=46)
82         # Event.objects.filter(timestamp__minute__gte=29)
83 
84         # second
85         #
86         # Event.objects.filter(timestamp__second=31)
87         # Event.objects.filter(time__second=2)
88         # Event.objects.filter(timestamp__second__gte=31)
進階操做

注:all()、all().values()、all().values_list()示例:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title></title>
 6 </head>
 7 <body>
 8     <h1>業務線列表(對象)</h1>
 9     <ul>
10         {% for row in v1 %}
11             <li>{{ row.id }} - {{ row.caption }} - {{ row.code }}</li>
12         {% endfor %}
13     </ul>
14     <h1>業務線列表(字典)</h1>
15     <ul>
16         {% for row in v2 %}
17             <li>{{ row.id }} - {{ row.code }}</li>
18         {% endfor %}
19     </ul>
20     <h1>業務線列表(元組)</h1>
21     <ul>
22         {% for row in v3 %}
23             <li>{{ row.0 }} - {{ row.1 }}</li>
24         {% endfor %}
25     </ul>
26 </body>
27 </html>
templates模板中的模板語言
 1 from django.shortcuts import render
 2 from app1 import models
 3 
 4 
 5 
 6 def business(request):
 7     v1 = models.Business.objects.all()
 8     #  QuerySet [obj(id,caption,code),obj(id,caption,code),obj(id,caption,code) ]
 9 
10     v2 = models.Business.objects.all().values("id", "code")
11     # QuerySet [{'id':1,'code': 'QA'},{'id':2,'code': 'PM'},...]
12 
13     v3 = models.Business.objects.all().values_list('id', 'code')
14     # QuerySet [(1,"QA"),(2,"PM")]
15     return render(request, 'business.html', {'v1': v1, 'v2': v2, 'v3': v3})
views.py中all()、all().values()、all().values_list()示例

 

3、ORM基礎操做示例:

簡單模擬用戶登錄跳轉後臺,實現編輯用戶、新增用戶、刪除用戶、查看用戶詳情等功能小示例

一、templates:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8     <form action="/app2/login/" method="POST" enctype="multipart/form-data">
 9         <p>
10             <input type="text" name="user" placeholder="用戶名" />
11         </p>
12         <p>
13             <input type="password" name="pwd" placeholder="密碼" />
14         </p>
15         <input type="submit" value="提交"/>
16     </form>
17 </body>
18 </html>
login.html
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <style>
 7         body {
 8             margin: 0;
 9         }
10 
11         .menu {
12             display: block;
13             padding: 5px;
14 
15         }
16     </style>
17 </head>
18 <body>
19 <div style="height: 48px;background-color: antiquewhite;color: burlywood">
20     oms後臺
21 </div>
22 <div>
23     <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: sandybrown;">
24         <a class="menu" href="/app2/user_info/">用戶管理</a>
25         <a class="menu" href="/app2/user_group/">用戶組管理</a>
26     </div>
27     <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto">
28         <h3>添加用戶</h3>
29 
30         <form method="POST" action="/app2/user_info/">
31             <input type="text" name="user"/>
32             <input type="text" name="pwd"/>
33             <input type="submit" value="添加"/>
34         </form>
35 
36         <h3>用戶列表</h3>
37         <ul>
38             {% for row in user_list %}
39                 <li>
40                     <a href="/app2/userDetail-{{ row.id }}">{{ row.username }}</a> |
41                     <a href="/app2/userDel-{{ row.id }}">刪除</a> |
42                     <a href="/app2/userEdit-{{ row.id }}">編輯</a>
43                 </li>
44             {% endfor %}
45         </ul>
46     </div>
47 
48 </div>
49 
50 </body>
51 </html>
user_info.html
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <style>
 7         body{
 8             margin: 0;
 9         }
10         .menu{
11             display: block;
12             padding: 5px;
13 
14         }
15     </style>
16 </head>
17 <body>
18     <div style="height: 48px;background-color: antiquewhite;color: burlywood">
19         oms後臺
20     </div>
21     <div>
22         <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: sandybrown;">
23             <a class="menu" href="/app2/user_info/">用戶管理</a>
24             <a class="menu" href="/app2/user_group/">用戶組管理</a>
25         </div>
26         <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto">
27         <h1>編輯用戶</h1>
28             <form method="post" action="/app2/userEdit-{{ obj.id }}/">
29                 <input style="display: none" type="text" name="id" value="{{ obj.id }}" />
30                 <input type="text" name="username" value="{{ obj.username }}" />
31                 <input type="text" name="password" value="{{ obj.password }}"/>
32                 <input type="submit" value="提交" />
33             </form>
34         </div>
35 
36     </div>
37 
38 </body>
39 </html>
user_edit.html
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <style>
 7         body{
 8             margin: 0;
 9         }
10         .menu{
11             display: block;
12             padding: 5px;
13 
14         }
15     </style>
16 </head>
17 <body>
18     <div style="height: 48px;background-color: antiquewhite;color: burlywood">
19         oms後臺
20     </div>
21     <div>
22         <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: sandybrown;">
23             <a class="menu" href="/app2/user_info/">用戶管理</a>
24             <a class="menu" href="/app2/user_group/">用戶組管理</a>
25         </div>
26         <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto">
27             <h1>用戶詳細信息</h1>
28             <h5>id:{{ obj.id }}</h5>
29             <h5>name:{{ obj.username}}</h5>
30             <h5>password:{{ obj.password }}</h5>
31         </div>
32 
33     </div>
34 
35 </body>
36 </html>
user_detail.html

二、app中的models.py:

1 from django.db import models
2 # Create your models here.
3 
4 
5 class UserInfo(models.Model):
6     # id列,Django框架會默認生成id(自增,主鍵),也能夠經過AutoField類型自定義主鍵,不過Django框架默認生成ID列會失效
7     # 用戶名列,字符串類型,最大長度長度
8     username = models.CharField(max_length=32)
9     password = models.CharField(max_length=64)
models.py

二、app中的urls.py:

from django.conf.urls import url
from app2 import views
urlpatterns = [
    url(r'^orm', views.orm_action),
    url(r'^login', views.login),
    url(r'^oms', views.oms),
    url(r'^user_info', views.user_info),
    url(r'^userDetail-(?P<nid>\d+)', views.user_detail),
    url(r'^userDel-(?P<nid>\d+)', views.user_del),
    url(r'^userEdit-(?P<nid>\d+)', views.user_edit),
]
urls.py

三、app中的views.py:

 1 from django.shortcuts import render
 2 from django.shortcuts import redirect
 3 from app2 import models
 4 
 5 
 6 # 登陸
 7 def login(request):
 8     if request.method == "GET":
 9         return render(request, 'login.html')
10     elif request.method == "POST":
11         u = request.POST.get('user')
12         p = request.POST.get('pwd')
13         # 兩種方式判斷數據庫中是否有匹配的數據
14         # obj = models.UserInfo.objects.filter(username=u,password=p).first() # 推薦這一種
15         # count = models.UserInfo.objects.filter(username=u, password=p).count()
16         obj = models.UserInfo.objects.filter(username=u, password=p).first()
17         if obj:
18             return redirect('/app2/user_info')
19         else:
20             return render(request, 'login.html')
21     else:
22         # PUT,DELETE,HEAD,OPTION...
23         return redirect('/login')
24 
25 
26 # 後臺頁面
27 def user_info(request):
28     if request.method == "GET":
29         user_list = models.UserInfo.objects.all()
30         print(user_list.query)  # .query 查看原生sql語句
31         return render(request, "user_info.html", {"user_list": user_list})
32     elif request.method == "POST":
33         u = request.POST.get("user")
34         p = request.POST.get("pwd")
35         models.UserInfo.objects.create(username=u, password=p)
36         # 添加用戶後返回添加頁面查看新增數據
37         # 方式一
38         # user_list = models.UserInfo.objects.all()
39         # return render(request, "user_info.html", {"user_list": user_list})
40         # 方式二 有效避免重複代碼
41         return redirect("/app2/user_info")
42 
43 
44 # 查看用戶詳情
45 def user_detail(request, nid):
46     # 取單條數據的兩種方式
47     # 第一種(推薦)
48     obj = models.UserInfo.objects.filter(id=nid).first()
49     # 第二種(當數據爲空,直接報錯)
50     # models.UserInfo.objects.get(id=nid)
51     return render(request, "user_detail.html", {"obj": obj})
52 
53 
54 # 刪除用戶
55 def user_del(request, nid):
56     models.UserInfo.objects.filter(id=nid).delete()
57     return redirect("/app2/user_info")
58 
59 
60 # 編輯用戶
61 def user_edit(request, nid):
62     if request.method == "GET":
63         obj = models.UserInfo.objects.filter(id=nid).first()
64         return render(request, "user_edit.html", {"obj": obj})
65     elif request.method == "POST":
66         user_id = request.POST.get('id')
67         u = request.POST.get('username')
68         p = request.POST.get('password')
69         models.UserInfo.objects.filter(id=user_id).update(username=u, password=p)
70         return redirect("/app2/user_info")
views.py

 

4、QuerySet方法詳細

一、支持鏈式查詢QuerySet方法:

  1 def all(self)
  2     # 獲取全部的數據對象
  3 
  4 def filter(self, *args, **kwargs)
  5     # 條件查詢
  6     # 條件能夠是:參數,字典,Q
  7 
  8 def exclude(self, *args, **kwargs)
  9     # 條件查詢
 10     # 條件能夠是:參數,字典,Q
 11 
 12 def annotate(self, *args, **kwargs)
 13     # 用於實現聚合group by查詢
 14 
 15     from django.db.models import Count, Avg, Max, Min, Sum
 16 
 17     v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id'))
 18     # SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id
 19 
 20     v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')).filter(uid__gt=1)  # 支持having子句,放在最開始的地方就是where子句,放在這邊就是having子句
 21     # SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1
 22 
 23     v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id',distinct=True)).filter(uid__gt=1)  # distinct=True去重
 24     # SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1
 25 
 26 def distinct(self, *field_names)
 27     # 用於distinct去重
 28     models.UserInfo.objects.values('nid').distinct()
 29     # select distinct nid from userinfo
 30 
 31     注:只有在PostgreSQL中才能使用distinct進行去重,不支持mysql數據庫
 32 
 33 def order_by(self, *field_names)
 34     # 用於排序
 35     models.UserInfo.objects.all().order_by('-id','age')
 36 
 37 def reverse(self):
 38     # 倒序
 39     models.UserInfo.objects.all().order_by('-nid').reverse()
 40     # 這個須要跟order_by配合使用,若是不存在order_by,則沒有任何效果
 41     # 若是存在order_by,reverse則是倒序,若是多個排序則一一倒序
 42 
 43 def defer(self, *fields):
 44     #查詢表中的數據,排除username、id列數據,將剩餘列數據組合成querySet對象進行返回
 45     models.UserInfo.objects.defer('username','')
 46     models.UserInfo.objects.filter(...).defer('username','id')
 47 
 48 def only(self, *fields):
 49     #查詢表中的數據,僅取username、id列中的數據組合成querySet對象進行返回,與defer相反
 50      models.UserInfo.objects.only('username','id')
 51      models.UserInfo.objects.filter(...).only('username','id')
 52 
 53 def using(self, alias):
 54      models.Blog.objects.filter(name="root").filter("id=1").all().using(alias="default1") #這個看你settings裏面的設置
 55      #指定使用的數據庫進行操做(從settings中讀取DATABASES配置),使用場景:好比數據庫的讀寫分離,讀的是A庫,寫的是B庫
 56 
 57 
 58 # 在原生的sql語句中會遇到一些複雜的sql,如msyql自定義的函數和過程、額外的查詢條件、映射、子查詢
 59 def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)  #tables可不傳,實例化的時候已傳表名,order_by看使用場景使用
 60 
 61     ## select與select_params配合,以%s進行傳參,參數能夠是元組,是可迭代的序列便可
 62     Entry.objects.extra(select={'new_id': "%s"}, select_params=(1,))#select的參數,%s 就會替換成 1
 63     #select *,1 as cid from Entry
 64     Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
 65     #select *,(select col from sometable where nid = 1) as new_id from Entry
 66     Entry.objects.extra(select={'new_id': "func(1)"}) #能夠直接放函數
 67     #select func(1) as new_id
 68 
 69 
 70     ##where與params配合,加額外的where條件語句,以%s進行傳參,參數能夠是元組,是可迭代的序列便可
 71     Entry.objects.extra(where=["name='a' OR age = 22"]) # or
 72     Entry.objects.extra(where=["age = 22", "name='a'"]) # and
 73     Entry.objects.extra(where=["func(arg)=2000"], params=['5'])
 74     Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])
 75 
 76 
 77 #性能相關的內置方法
 78 def select_related(self, *fields)
 79     #一、
 80     users = User.objects.all()
 81     for row in users:
 82         #僅僅是用戶表的數據不會再去請求數據庫,user_type表須要再次發送請求,可是若是這邊10條用戶表的數據有十條,總共就會請求10+1次數據庫
 83         print(row.name,row.sex)
 84         print(row.ut.type_name) #再次請求一次數據庫
 85 
 86     #二、
 87     users = User.objects.all().values("name","sex","ut__type_name") #若是是這種的話,就會只請求一次數據庫,但數據不是querySet對象類型
 88 
 89     #三、
 90     #只拿ut對應的user_type表一次性拿過來
 91     users = User.objects.all().select_related("ut") #只關聯ut這張表,取出來,其餘的表都不關聯,由於一張表裏面能夠有多個外鍵
 92     for row in users:
 93         print(row.name,row.sex)
 94         print(row.ut.type_name)
 95         print(row.tu.name) #tu沒有加進去,因此這邊會再次django發送數據庫請求
 96 
 97 
 98 
 99 def prefetch_related(self, *lookups)
100     #通常在生產環境,不多連表查詢,由於這樣效率很低,咱們通常都是空間換時間,因此這個就會用到prefetch_related,用到這個,會作屢次查詢,保證每次都是單表查詢
101     users = User.objects.filter(ut_id__gt=30).prefetch_related('ut') #這邊也能夠多加幾個外鍵
102     #解析步驟
103     ## select * from users where id > 30 固然這邊不會用*的,通常會把全部字段都打印出來,效率更高
104     ## 獲取上一步中全部ut_id = [1,2]的數據
105     ## select * from user_type where id in [1,2]
106     #這邊django已經經過以上步驟,把要查詢的數據放到內存中,全部就不用向數據庫發送請求了,就能夠直接從內存中獲取
107     for row in users:
108         print(row.name,row.sex)
109         print(row.ut.type_name)
支持鏈式查詢的QuerySet方法

二、不支持鏈式查詢QuerySet方法:

 1 def raw(self, raw_query, params=None, translations=None, using=None):
 2     # 執行原生SQL
 3     models.UserInfo.objects.raw('select * from userinfo')
 4     #obj = User.objects.raw('select id,name,password from tb ')
 5 
 6     # 若是SQL是其餘表時,必須將名字設置爲當前UserInfo對象的主鍵列名,
 7     models.UserInfo.objects.raw('select id as nid from 其餘表')
 8     #能夠下面的方式將tb2裏面的數據複製在tb中
 9     #obj = User.objects.raw('select nid as id,username as name,email as password from tb2 ')
10 
11     # 爲原生SQL設置參數
12     models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,])
13 
14     # 將獲取的到列名轉換爲指定列名
15     name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
16     Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)
17 
18     # 指定數據庫
19     models.UserInfo.objects.raw('select * from userinfo', using="default")
20 
21     ################### 原生SQL ###################
22     from django.db import connection, connections
23     cursor = connection.cursor()  # cursor = connections['default'].cursor()
24     cursor.execute("""SELECT * from auth_user where id = %s""", [1])
25     row = cursor.fetchone() # fetchall()/fetchmany(..)
26 
27 
28 def values(self, *fields):
29     # 獲取每行數據爲字典格式
30 
31 def values_list(self, *fields, **kwargs):
32     # 獲取每行數據爲元祖
33 
34 def dates(self, field_name, kind, order='ASC'):
35     # 根據數據庫中時間列名進行某一部分進行去重查找並截取指定內容
36     # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日)
37     # order只能是:"ASC"  "DESC"
38     # 並獲取轉換後的時間
39         - year : 年-01-01
40         - month: 年-月-01
41         - day  : 年-月-42 
43     models.DatePlus.objects.dates('ctime','day','DESC')
44 
45 def datetimes(self, field_name, kind, order='ASC', tzinfo=None):
46     # 根據數據庫中時間列名進行某一部分進行去重查找並截取指定內容,將時間轉換爲指定時區時間
47     # kind只能是 "year", "month", "day", "hour", "minute", "second"
48     # order只能是:"ASC"  "DESC"
49     # tzinfo時區對象
50     #指定時區須要下載pytz庫
51     """
52     pip3 install pytz
53     import pytz
54     pytz.all_timezones
55     pytz.timezone(‘Asia/Shanghai’)
56     """
57     models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC)
58     models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai'))
59 
60 
61 
62 def none(self):
63     # 返回一個空QuerySet對象
不支持鏈式查詢的QuerySet方法

三、數據庫操做:

如:批量插入數據庫,對整個數據作聚合操做

 1 def aggregate(self, *args, **kwargs):  2    # 聚合函數,獲取字典類型聚合結果
 3    from django.db.models import Count, Avg, Max, Min, Sum  4    result = models.UserInfo.objects.aggregate(k=Count('u_id', distinct=True), n=Count('nid')) # distinct=True 先去重,再執行聚合 至關於sql以下: #select count(nid) as n from user
 5 
 6 def count(self):  7    # 獲取個數
 8 
 9 def get(self, *args, **kwargs): 10    # 獲取單個對象
11 
12 def create(self, **kwargs): 13    # 建立對象
14 
15 def bulk_create(self, objs, batch_size=None): 16     # 批量插入
17     # batch_size表示一次插入的個數
18     objs = [ 19         models.DDD(name='r11'), 20         models.DDD(name='r22') 21  ] 22     models.DDD.objects.bulk_create(objs, 10) 23 
24 def get_or_create(self, defaults=None, **kwargs): 25     # 若是存在,則獲取,不然,建立
26     # defaults 指定建立時,其餘字段的值
27     obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 2}) 28 
29 def update_or_create(self, defaults=None, **kwargs): 30     # 若是存在,則更新,不然,建立
31     # defaults 指定建立時或更新時的其餘字段
32     obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1}) 33 
34 def first(self): 35    # 獲取第一個
36 
37 def last(self): 38    # 獲取最後一個
39 
40 def in_bulk(self, id_list=None): 41    # 根據主鍵ID進行查找
42    id_list = [11,21,31] 43    models.DDD.objects.in_bulk(id_list) #至關於in操做
44 
45 def delete(self): 46    # 刪除
47 
48 def update(self, **kwargs): 49     # 更新
50 
51 def exists(self): 52    # 是否有結果
53 
54 METHODS THAT DO DATABASE QUERIES
直接對數據庫操做

 四、QuerySet序列化:

 1 #第一種
 2 ##使用Django內置的方法對queryset類型的數據進行序列化
 3 
 4 from django.core import serializers
 5 ret = models.BookType.objects.all()
 6 data = serializers.serialize("json", ret)
 7 
 8 
 9 #第二種
10 ##使用json.dumps對queryset類型的數據進行序列化
11 ####當list中queryset類型中沒有複雜的數據類型(如:時間類型)能夠直接使用json.dumps
12 import json
13 #ret = models.BookType.objects.all().values('caption')
14 ret = models.BookType.objects.all().values_list('id','caption')
15 ret=list(ret)
16 result = json.dumps(ret)
17 
18 ####當list中queryset類型中沒有複雜的數據類型(如:時間)能夠直接使用json.dumps
19 import json
20 from datetime import date
21 from datetime import datetime
22 
23 #自定義encoder
24 class JsonCustomEncoder(json.JSONEncoder):
25 
26     def default(self, field):
27 
28         if isinstance(field, datetime.datetime):
29             return field.strftime('%Y-%m-%d %H:%M:%S')
30         elif isinstance(field, date):
31             return field.strftime('%Y-%m-%d')
32         else:
33             return json.JSONEncoder.default(self, field)
34 
35 #再序列化帶有相似於ctime複雜的數據類型
36 ret = models.BookType.objects.all().values_list('caption','ctime')
37 
38 ret=list(ret)
39 
40 result  = json.dumps(ret, cls=JsonCustomEncoder)
QuerySet序列化的兩種方式

 

5、Model利用鉤子進行數據驗證(弱)

django Model也是支持數據驗證的,只是這個數據驗證比較弱而已,只能支持單個的驗證,可是對於組合的、固定的,就沒法進行相關數據驗證了

一、models.py

class User(models.Model):
    name = models.CharField(max_length=32,db_index=True) #建立索引
    email = models.EmailField(max_length=30)
    #Model經過clean()函數設置鉤子
    def clean(self): #Model內部對全部字段進行正則驗證,完畢以後纔會執行這個clean方法
        from django.core.exceptions import ValidationError
        c = User.objects.filter(name=self.name).count()
        if c:
            raise ValidationError

二、views.py

from app01 import models
 
def index(request):
    obj = models.User(name="root",email="root")
    obj.full_clean()  #沒有這個,name是不作驗證的,有了full_clean是須要作驗證的,驗證不經過是要報錯的,因此驗證的時候,咱們直接本身抓異常,進行異常處理
    obj.save()
 
    return HttpResponse("hello")
相關文章
相關標籤/搜索