1. 程式人生 > >Django模型層之單表操作

Django模型層之單表操作

MVC或者MVC框架中包括一個重要的部分,就是ORM,它實現了資料模型與資料庫的解耦,即資料模型的設計不需要依賴於特定的資料庫,通過簡單的配置就可以輕鬆更換資料庫。ORM是“物件-關係-對映”的簡稱。

sql中的表
# 建立表
      create TABLE employee(
                  id INT PRIMARY KEY auto_increment,
                  name varchar(20),
                  gender BIT default 1,
                  birthday DATA,
                  department 
VARCHAR(20), salary DECIMAL(8,2) unsigned,) ); # 新增一條表記錄: INSERT employee(name, gender, birthday, salary, department) VALUES ('alex', '1', '1985-12-12', 8000, '保潔部'); # 查詢一條表記錄: SELECT * FROM employee WHERE age=24; # 更新一條表記錄: UPDATE employee SET
birthday='1989-10-24' WHERE id=1; # 刪除一條表記錄: DELETE FROM employee WHERE name='alex'
而對應的Python的類物件
class Employee(models.Model):
      id=models.AutoField(primary_key=True)
      name=models.CharField(max_length=32)
      gender=models.BooleanField()
      birthday=models.DateField()
      department
=models.CharField(max_length=32) salary=models.DecimalField(max_digits=8,decimal_places=2) #新增一條表記錄: emp=Employee(name='alex', gender=True, birthday='1985-12-12',epartment='保潔部') emp.save() # 查詢一條表記錄 Employee.objects.filter(age=24) # 更新一條表記錄 Emplyoee.objects.filter(id=1).update(birthday='1989-10-24') # 刪除一條表記錄 Emplypee.objects.filter(name='alex').delete()

1.生成表模型

在該應用的models.py中建立模型:

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


class Book(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32, unique=True)
    pub_date = models.DateField()
    price = models.DecimalField(max_digits=8, decimal_places=2)  # max number = 999999.99
    publish = models.CharField(max_length=32)

將模型轉為mysql資料庫中的表,需要在settings中配置:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME':'bms',           # 要連線的資料庫,連線前需要建立好
          'USER':'root',        # 連線資料庫的使用者名稱
          'PASSWORD':'',        # 連線資料庫的密碼
          'HOST':'127.0.0.1',       # 連線主機,預設本級
          'PORT':3306            #  埠 預設3306
    }
}

然後我們需要找到總專案包下的__init__.py檔案,寫入

import pymysql
pymysql.install_as_MySQLdb()

最後通過兩條資料庫遷移命令即可在指定的資料庫中建立表 :

>>> python manage.py makemigrations
>>> python manage.py migrate

注意:

確保配置檔案中的INSTALLED_APPS中寫入我們建立的app名稱

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "book"  
]   # book是應用名

如果你的Django版本是1.0而且Python版本高於3.4,可能會報錯如下:

django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.3 or newer is required; you have 0.7.11.None

需要修改:

通過查詢路徑C:\Programs\Python\Python36-32\Lib\site-packages\Django-2.0-py3.6.egg\django\db\backends\mysql\base.py 這個路徑裡的檔案把下面兩行程式碼註釋掉就ok了。(這個路徑並不是固定的,只要找到Python\django裡的mysql檔案)

if version < (1, 3, 3):
     raise ImproperlyConfigured("mysqlclient 1.3.3 or newer is required; you have %s" % Database.__version__)

如果你還想要在螢幕上列印轉換過程中的sql,需要在settings中進行如下配置:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

2.增刪改查

新增表記錄

方法1:

# create方法的返回值book_obj就是插入book表中的python葵花寶典這本書籍紀錄物件
  book_obj=Book.objects.create(title="python葵花寶典",state=True,price=100,publish="蘋果出版社",pub_date="2012-12-12")

方法2:

book_obj=Book(title="python葵花寶典",state=True,price=100,publish="蘋果出版社",pub_date="2012-12-12")
book_obj.save()

例:views.py

from django.shortcuts import render,HttpResponse

# Create your views here.
from app01.models import Book


def index(request):

    book_obj = Book.objects.create(title="Python葵花寶典", state=True, pub_date="2012-12-12", price=100, publish='人民出版社')
    book_obj.save()
    
    book_obj_2 = Book(title="Python一陽指", state=True, pub_date='2012-12-12', price=100, publish='人民出版社')
    book_obj_2.save()

    return HttpResponse("OK!")

urls.py

from django.contrib import admin
from django.urls import path

from app01 import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),
]

用瀏覽器登入首頁後,再查詢結果:

+----+--------------------+-------+------------+--------+-----------------+
| id | title              | state | pub_date   | price  | publish         |
+----+--------------------+-------+------------+--------+-----------------+
|  1 | Python葵花寶典       |     1 | 2012-12-12 | 100.00 | 人民出版社         |
|  2 | Python一陽指         |     1 | 2012-12-12 | 100.00 | 人民出版社         |
+----+--------------------+-------+------------+--------+-----------------+

查詢表記錄

查詢API

<1> all():                  查詢所有結果,返回的是一個queryset物件

<2> filter(**kwargs):       它包含了與所給篩選條件相匹配的物件

<3> get(**kwargs):          返回與所給篩選條件相匹配的物件,返回結果有且只有一個,
                            如果符合篩選條件的物件超過一個或者沒有都會丟擲錯誤。

<4> exclude(**kwargs):      它包含了與所給篩選條件不匹配的物件

<5> order_by(*field):       對查詢結果排序

<6> reverse():              對查詢結果反向排序

<8> count():                返回資料庫中匹配查詢(QuerySet)的物件數量。

<9> first():                返回第一條記錄

<10> last():                返回最後一條記錄

<11> exists():              如果QuerySet包含資料,就返回True,否則返回False

<12> values(*field):        返回一個ValueQuerySet——一個特殊的QuerySet,執行後得到的並不是一系列
                            model的例項化物件,而是一個可迭代的字典序列
<13> values_list(*field):   它與values()非常相似,它返回的是一個元組序列,values返回的是一個字典序列

<14> distinct():            從返回結果中剔除重複紀錄

在models.py的Book類中加上這兩行,讓螢幕打印出具體的書名:

def __str__(self):
    return self.title

例:views.py(注意可能需要重啟下django)

from django.shortcuts import render,HttpResponse

# Create your views here.
from app01.models import Book


def index(request):

    # book_obj = Book.objects.create(title="Python葵花寶典", state=True, pub_date="2012-12-12", price=100, publish='人民出版社')
    # book_obj.save()

    # book_obj_2 = Book(title="Python一陽指", state=True, pub_date='2012-12-12', price=100, publish='人民出版社')
    # book_obj_2.save()

    book_list = Book.objects.all()
    # print(book_list)  # [obj1, obj2,...]

    for obj in book_list:
        print(obj.title, obj.price)

    return HttpResponse("OK!!!")

螢幕列印:

Python葵花寶典 100.00
Python一陽指 100.00

再加一本書:

     book_obj_2 = Book(title="Python降龍十八掌", state=True, pub_date='2015-12-12', price=200, publish='路飛出版社')
     book_obj_2.save()

其他的查詢API示例:(注意只要查詢結果是<QuerySet>型別的都可以繼續用相應方法呼叫,分清呼叫者和返回值)

from django.shortcuts import render,HttpResponse

# Create your views here.
from app01.models import Book


def index(request):

    book_first_1 = Book.objects.all().first()  # 呼叫者:queryset物件,返回值:model
    print("book_first:", book_first_1)
    book_first_2 = Book.objects.all()[2]
    print("book_first:", book_first_2)
    book_filter = Book.objects.filter(title="Python葵花寶典", price=100)   # [obj1, obj2,...]
    print("book_filter:", book_filter)
    book_filter_first = Book.objects.filter(price=100).first()
    print("book_filter_first:", book_filter_first)
    book_get = Book.objects.get(price=200)   # 有且只有一條結果,否則會報錯
    print("book_get.pub_date:", book_get.pub_date)
    book_exclude = Book.objects.exclude(price=200, title="Python降龍十八掌")
    print("book_get.pub_date:", book_exclude)
    book_order_by = Book.objects.order_by("price")  # "-price"表示逆序
    book_order_by_1 = Book.objects.order_by("price", "-id")  # 當price相等時再用id排序
    print("book_order_by:", book_order_by, "book_order_by_1:", book_order_by_1)
    book_exists = Book.objects.all().exists()
    print("book_exists", book_exists)
    book_values = Book.objects.all().values("title")
    print("book_values", book_values)
    book_values_list = Book.objects.all().values_list("price", "title")
    print("book_values_list", book_values_list)
    book_distinct = Book.objects.all().values("price").distinct()
    print("book_distinct:", book_distinct)

    return HttpResponse("OK!!!")

對應的結果:

book_first: Python葵花寶典
book_first: Python降龍十八掌
book_filter: <QuerySet [<Book: Python葵花寶典>]>
book_filter_first: Python葵花寶典
book_get.pub_date: 2015-12-12
book_get.pub_date: <QuerySet [<Book: Python葵花寶典>, <Book: Python一陽指>]>
book_order_by: <QuerySet [<Book: Python葵花寶典>, <Book: Python一陽指>, <Book: Python降龍十八掌>]> book_order_by_1: <QuerySet [<Book: Python一陽指>, <Book: Python葵花寶典>, <Book: Python降龍十八掌>]>
book_exists True
book_values <QuerySet [{'title': 'Python葵花寶典'}, {'title': 'Python一陽指'}, {'title': 'Python降龍十八掌'}]>
book_values_list <QuerySet [(Decimal('100.00'), 'Python葵花寶典'), (Decimal('100.00'), 'Python一陽指'), (Decimal('200.00'), 'Python降龍十八掌')]>
book_distinct: <QuerySet [{'price': Decimal('100.00')}, {'price': Decimal('200.00')}]>

模糊查詢:

Book.objects.filter(price__in=[100, 200, 300])
Book.objects.filter(price__gt=100)  # 大於100
Book.objects.filter(price__lt=100)  # 小於100
Book.objects.filter(price__range=[100, 200])
Book.objects.filter(title__contains="python")  # 包含
Book.objects.filter(title__icontains="python")  # 不管大小寫
Book.objects.filter(title__startswith="py")
Book.objects.filter(pub_date__year=2012)

刪除表記錄

Book.objects.filter(price=200).delete()  # 刪除所有price=200的書
Book.objects.filter(pub_date__year=2005).delete()  # 
Book.objects.filter(price=100).first().delete()
Book.objects.filter(title="Python一陽指").update(title="Python六脈神劍")
# update只能被model物件呼叫

總結:

必須分清這些api能被Queryset物件還是model物件呼叫。