Django-orm數據庫相關

django-orm

###數據庫設定 Django默認使用的爲sqlite,因此在使用mysql或其餘數據庫的時候須要對其進行相關設定前端

####1.settings.pypython

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME':'dbname',
        'USER': 'root',
        'PASSWORD': 'xxx',
        'HOST': '',
        'PORT': '',
    }
}

####2. project項目下的_init_.pymysql

因爲Django默認使用MySQLdb,python3中無此模塊,使用pymysql的話須要再次添加:
    import pymysql
    pymysql.install_as_MySQLdb()

####3. 註冊 在settings中INSTALLED_APPS註冊咱們的appsql

####4.app的models.py中建立表數據庫

from django.db import models
# Create your models here.
class UserInfo(models.Model):
    # django會默認幫你建立一個自增id字段做爲主鍵
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    email = models.EmailField()

####5. makemigrationsdjango

python manage.py makemigrations
建立更改的文件

####6.migratesession

python manage.py migrate
將生成的py文件應用到數據庫

####7. 生成的表:app

+----------------------------+
| Tables_in_cmdb             |
+----------------------------+
| app_cmdb_userinfo          |
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
+----------------------------+ 

mysql> desc app_cmdb_userinfo;
+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| id       | int(11)      | NO   | PRI | NULL    | auto_increment |
| username | varchar(32)  | NO   |     | NULL    |                |
| password | varchar(64)  | NO   |     | NULL    |                |
| email    | varchar(254) | NO   |     | NULL    |                |
+----------+--------------+------+-----+---------+----------------+

Django ORM操做相關

###1.添加數據函數

from app_cmdb import models
# 有幾個字段,傳幾個參數就好了
models.UserInfo.objects.create(username="leon", password="123123", email='4641231@qq.com')

# 方法2
stu1 = user(username="leon", password="123123", email='4641231@qq.com')
stu1.save() # flush到數據庫中

###2.數據修改測試

# 單個數據的多個字段同時跟新
models.UserInfo.objects.get(username="leon", password="123123", email='4641231@qq.com').update(username="Leon",password="qweasdC")

# 跟新某個字段
user_obj = models.UserInfo.objects.get(username="leon", password="123123")
user_obj.username="Jack"
user_obj.save()

# 多條數據同時跟新
models.UserInfo.objects.all().update(username='Zhang')

###3.數據刪除

# 刪除表中全部數據
models.UserInfo.objects.all().delete()
# 篩選單個刪除
models.UserInfo.objects.get(username="leon").delete()
# 過濾多個刪除
models.UserInfo.objects.filter(username="leon").delete()

###4.數據查詢 全部查詢、過濾、排序、取值方法能夠結合本身的使用場景來使用,以達到最佳的效果,下面是一些基礎的查詢操做,在文末會有更加詳細的介紹

# 查詢全部記錄
models.UserInfo.objects.all()


# 帶字段名的全部記錄,就是將全部記錄以key-value的形式保存在字典中
models.UserInfo.objects.all().values()
>>><QuerySet [{'id': 1, 'username': 'leon', 'password': '123123', 'email': '4641231@qq.com'}, {'id': 2, 'username': 'leon', 'password': '1123123', 'email': '4641231@qq.com'}]>

# 查詢單條記錄,使用get查詢單條數據,若是沒有查到,會直接報錯,結合try來使用
models.UserInfo.objects.get(name='Aaron')

# 查詢多條中的第一條記錄,多個過濾條件,須要在filter中用逗號分隔開
models.UserInfo.objects.filter(username='leon', password="123123").first()

# 模糊過濾,字段只要包含就能夠
models.UserInfo.objects.filter(username__contains='leo').first()

# 模糊-不區分大小寫
models.UserInfo.objects.filter(username__icontains='leo').first()


# 將字段內容排序後顯示
models.UserInfo.objects.order_by('username')


# 查詢記錄的個數
models.UserInfo.objects.filter().conut()

# 篩選之大於小於,多個用逗號分開
models.UserInfo.objects.filter(id__gt=1)  # 大於1
models.UserInfo.objects.filter(id__gte=1)  # 大於等於1
models.UserInfo.objects.filter(id__lt=1)  # 小於1
models.UserInfo.objects.filter(id__lte=1)  # 小於等於1
models.UserInfo.objects.filter(id_gt=1,id__lte=10) # 大於1小於等於10


# in,not in
models.UserInfo.objects.filter(id__in=[11, 22, 33]) # 獲取id等於十一、2二、33的數據
models.UserInfo.objects.exclude(id__in=[11, 22, 33])  # not in


# 排序值逆序
models.UserInfo.objects.order_by('-username')

# 限制數據條數,由於返回的是一個QuerySet類型的列表,咱們可使用列表的分片來獲取想要的數據內容,依然按照`顧首不顧尾`的原則
models.UserInfo.objects.filter(username="leon")[0]  # 第一條數據
models.UserInfo.objects.filter(username="leon")[0:3]  # 去前三條數據

###5.數據字段類型

  • 幾種主要的類型之-數字類型
1. AutoField int類型(1 to 2147483647)的自增id列,須加參數 primary_key=True
2. BigAutoField bigint類型(1 to 9223372036854775807),同上
3. BigIntegerField
4. IntegerField
5. FloatField 
6. SmallIntegerField
7. PositiveIntegerField
8. PositiveSmallIntegerField
  • 字符串類型
1. CharField
2. EmailField (admin)
3. GenericIPAddressField (admin)
4. URLField (admin)
5. UUIDField
  • 時間類型
1. DateField (Python:datetime.date)
2. DateTimeField (Python: datetime.datetime )
3. DecimalField (python : Decimal)
4. DurationField (python :  timedelta)
5. TimeField  (python : datetime.time)
  • 二進制類型
1. BinaryField
  • 布爾類型
1. BooleanField
  • 文件類型
1. FileField

###6.參數

  • 基本
- null 是否能夠爲空
- default 默認值
- primary_key 主鍵
- db_column 舍子數據庫中的列名
- db_index  創建普通索引
- unique 惟一索引
- unique_for_data 只對時間作索引
- unique_for_month 只對月份作索引
- unique_for_year 只對年份作索引
- auto_now  添加仍是修改對象,時間爲你添加或者修改的時間,須要使用obj.save()來跟新,而update不能跟新
- auto_now_add 建立時自動建立時間,跟新不動
  • admin:
- choices 兩個做用
	user_type_choices = (  # 將這些字段放進內存,而避免數據庫連表操做
        (1,'root'),
        (2,'root1'),
        (3,'root1')
    ) 並且在django-admin中能夠經過select直接選擇
    user_type_id = models.IntegerField(choices=user_type_choices,default=1)
- blank admin中是否能夠爲空
- verbose_name="用戶名"  前端顯示的別名
- editable 是否能夠被編輯
- error_messages 輸入錯誤提示消息自定義   error_messages={'required':u'郵箱不能爲空'}????
- help_text help_text="user_name"  輸入框下的用戶提示信息
- validators  Django的form自定義驗證機制設置

###7.外鍵的連表操做 表結構

class Host(models.Model):
    nid = models.AutoField(primary_key=True)
    hostname = models.CharField(max_length=32, db_index=True)
    ip = models.GenericIPAddressField(db_index=True, protocol='ipv4')
    port = models.IntegerField()
    b = models.ForeignKey(to='Business', to_field='id')


    def __str__(self):
        # 定製輸出對象的時候,自動輸出name字段
        return self.name


class Business(models.Model):
    caption = models.CharField(max_length=32)
    code = models.CharField(max_length=32)

測試數據

####1.單表相關

  • 查詢
# QuerySet內部爲對象,模板獲取的時候用"."來獲取
v1 = models.Business.objects.all() 

# QuerySet內部爲key、value的字典,由於是字典,在模板中獲取的時候用"."來獲取,
v2 = models.Business.objects.all().values('id', 'caption')  #只獲取特定字段

# QuerySet內部爲元組,由於是元組,在模板中獲取的時候使用0,1,2的index來獲取
v3 = models.Business.objects.all().values_list('id', 'caption')
class Host(models.Model):
    class Meta:
        # django建立表的時候未指定此字段,則默認爲app名稱_類名小寫
        db_table = "host"    # 數據庫中生成的表名稱 

        # 多字段聯合索引,注意mysql聯合索引的最左前綴原則!!!
        index_together = [
            ("hostname", "ip"),
        ]

        # 多字段聯合惟一索引
        unique_together = (("hostname", "ip"),)

        # admin中一種易於理解展現形式,默認展現爲類名,設定此字段後顯示爲該字段加's'
        verbose_name='主機'

        # 同上,可是不會加上's'
        verbose_name_plural='主機'

......待補充~

verbose_name結果

verbose_name_plural結果


####2. 一對多ForeignKey 1) 數據查詢

  • 正向數據查詢
# QuerySet內部爲對象
v1 = models.Host.objects.filter(nid__gt=0)

# QuerySet內部爲key、value的字典,由於是字典
v2 = models.Host.objects.all().values('nid', 'hostname', 'b_id', 'b__caption', 'b__code')

# QuerySet內部爲元組,由於是元組
v2 = models.Host.objects.all().values_list('nid', 'hostname', 'b_id', 'b__caption', 'b__code')

# 經過host字段查business
v = models.Host.objects.filter(id=1).all()
v[0].b.caption 或 v[0].b.code
  • 數據反向查詢,從Business查詢Host
# QuerySet對象
v = models.Business.objects.filter(id=1).all()
# 這樣就能夠獲取全部綁定business.id=1的全部Host的對象
v[0].host_set.all()
# 獲取對應的值  
v[0].b.caption 或 v[0].b.code

# QuerySet字典
models.Business.objects.all().values('caption','host__hostname')

# QuerySet元組
models.Business.objects.all().values_list('caption','host__hostname')

2) 可用的字段以及參數

  • to要進行關聯的表名

  • to_field要關聯的表中的字段名稱

  • db_constraint=True 是否在數據庫中建立外鍵約束。例如,默認django在建立host數據的時候對他的b_id字段沒有約束性,只是在建立sql語句的時候對sql語句進行了約束。當你設定該字段爲False的時候,django支持你的b_id不建立與business表的約束條件,你能夠隨意設定該值

  • on_delete:外鍵指向的對象刪除時,本對象應該採起的措施,默認級聯刪除CASCADE。假如刪除business表中的一條數據,在新版本的django中也會把與其關聯的host表中的數據也刪除,可是在mysql中使用delete語句是會引起異常的。on_delete定製當刪除關聯表中的數據時,定製當前表與其關聯的行的行爲官方文檔:

- models.CASCADE,刪除外鍵對象(Business)數據,與之關聯的全部數據也徹底刪除(默認行爲)

- models.DO_NOTHING,刪除外鍵對象(Business)數據,不刪除被關聯(Host)的數據,引起db層錯誤IntegrityError

- models.PROTECT,刪除外鍵對象(Business)數據,不刪除被關聯(Host)的數據,引起django層錯誤ProtectedError

- models.SET_NULL,刪除外鍵對象(Business)數據,與之關聯的(Host)對應字段值設置爲null,且前提外鍵字段須要設置爲可爲空

- models.SET_DEFAULT,刪除外鍵對象(Business)數據,與之關聯的(Host)對應字段值設置爲默認值,前提外鍵字段須要設置默認值

- models.SET,刪除外鍵對象(Business)數據,
    a. 與之關聯的(Host)對應字段值設置爲指定值,設置:models.SET(值)
    b. 與之關聯的(Host)對應字段值設置爲可執行對象的返回值,設置:models.SET(可執行對象)

on_delete中的models.SET舉例:

# 咱們能夠在func函數中自定製返回結果,這樣開發起來就會有更多選擇,能夠對數據判斷等等~
def func1():
   return 10

class MyModel(models.Model):
    user =models.ForeignKey(to="User",to_field="id"on_delete=models.SET(func1),)
  • related_name='connFK' 上面反向操做時,使用的是表名,用於代替表名_set成爲obj.connFK.all(),例如:
v = models.Business.objects.filter(id=1).all()  
v[0].connFK.all()
  • related_query_name='host_table' 反向操做時,原來使用的是表名,此字段只是用來替換表名,例如:
models.Business.objects.all().values_list('caption','host__hostname')
# 變爲
models.Business.objects.all().values_list('caption','host_table__hostname')
  • limit_choices_to=None 顯示關聯數據時,提供的篩選條件:
limit_choices_to={'id__gt': 1}
limit_choices_to=lambda : {'id__gt': 1}
  • swappable??

####2. 一對一:OneToOneField

Stack Overflow熱帖,這個問答講解的其實特別的好,分享一下~

表結構,一個汽車只能夠對應一個引擎,一個引擎也只能對應一個汽車

class Engine(models.Model):
    name = models.CharField(max_length=25)

    def __unicode__(self):
        return self.name

class Car(models.Model):
    name = models.CharField(max_length=25)
    engine = models.OneToOneField(Engine)

    def __unicode__(self):
        return self.name

其實OneToOneField其實能夠理解爲 ForeignKey加上 unique=True的另外一種展示形式,可是外鍵不加unique=True的約束的時候,反向查詢返回的是一個QuerSet列表,而OneToOneField反向查詢只返回一個QuerSet對象,由於他是一對一的

class Engine2(models.Model):
    name = models.CharField(max_length=25)

    def __unicode__(self):
        return self.name

class Car2(models.Model):
    name = models.CharField(max_length=25)
    engine = models.ForeignKey(Engine2, unique=True)

    def __unicode__(self):
        return self.name

####3. 多對多:ManyToManyField 官方文檔

表結構,一個做者能夠出版不少本書,一本書有不少個做者

class Author(models.Model):
    name = models.CharField(max_length=64)
    age = models.IntegerField()
    
    def __unicode__(self):
        return self.name

class Book(models.Model):
    book_name = models.CharField(max_length=128)
    pub_date = models.DateField()
    book_to_author = models.ManyToManyField('Author')

    def __unicode__(self):
        return self.book_name

這樣就會生成三張表,一個做者表,一個書表,還有一個Django自動生成的第三張表,存放做者與書之間的關係表:

在Django中,多對多關係中的第三張表,咱們可讓Django自動建立,也能夠選擇本身建立第三張表,當本身建立的時候,又有兩種狀況:

  • ManyToManyField 字段, 當存在這個字段的時候,Django支持咱們對數據的查詢、清除操做可使用這個字段,可是其餘操做是不可使用這個字段的:

  • 沒有ManyToManyField 字段,當沒有這個字段的時候,第三張表中就是所有是ForiegnKey,而咱們對數據的操做就只能經過這個第三張表來操做:

有ManyToManyField字段

無ManyToManyField字段

1)數據查詢

# 經過book_to_author字段來正向查詢
v = models.Book.objects.filter(id=1).first()
print(v.book_to_author.all())
>>>> <QuerySet [<Author: Author object>, <Author: Author object>]>
# 反向查詢
v1 = models.Author.objects.filter(id=1).first().book_set.all()
v2 = models.Author.objects.filter(id=1).values('name','book__book_name')
v3 = models.Author.objects.filter(id=1).values_list('name','book__book_name')

2)其餘操做

v = models.Book.objects.filter(id=1).first()
v.book_to_author.remove   # 能夠刪除某一條對應關係
v.book_to_author.add      # 添加一條關係
v.book_to_author.set      # 直接設定,會覆蓋原值
v.book_to_author.clear    # 清除v對象的全部與之聯繫

3)參數以及字段

  • to 同ForeignKey中解釋,指定須要關聯的表名

  • db_table 設定表名,再也不使用Django默認建立的表名

  • related_name 同ForeignKey中解釋

  • related_query_name 同ForeignKey中解釋

  • limit_choices_to 同ForeignKey中解釋

  • db_constraint 同ForeignKey中解釋

  • through 當第三張表是本身建立的的時候,此字段用於指定第三張關係表。若是不指定,且還有ManyToManyField字段的時候,Django會在數據庫中多建立第四張表(本身建立和自動建立都會存在)。使用該字段來定製關係表,就不會建立你本身的那張表

  • through_fieldsDjango默認建立第三張關係表的時候,這個關係表只有三個字段,當第三張表是本身建立的時候,不能規定你的第三張表中的有多少列數據,可是能夠經過該字段傳入一個多字段的列表來指定那些字段作多對多關係

  • swappable

  • symmetrical

orm數據操做補充

相關文章
相關標籤/搜索