Python Django 學習 (二) 【Django 模型】

注: 因爲本身排版確實很難看,本文開始使用markdown編輯,但願有所改善html

官方定義

A model is the single, definitive source of information about your data. It contains the essential fields and behaviors of the data you’re storing. Generally, each model maps to a single database table.node

一個模型是關於你的數據的單個的、肯定的信息源。它包含了你儲存數據的必要的列和行爲,基本上,一個模型映射一個單個的數據庫表。python

更改Django數據庫配置

因爲原生的django使用的是sqlite3, 本人熟悉mysql 因此最後使用mysql。mysql

注:本文接着上一篇文章來的,若是沒有相應的項目請按照上一篇內容操做一下。[Python Django 學習 (一) 【Django 框架初探】]sql

  • 在 test_project項目中找到文件 test_project/test_project/settings.py 找到以下代碼
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
  • 將上述代碼註釋掉,添加以下代碼:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mysql',#數據庫名字
        'USER':'root',
        'PASSWORD':'*****',
        'HOST':'localhost',
        'PORT':'3306',
    }
}
  • 確保一件事情,你的python3 的版本安裝了 pymysql 、mysqlclient 使用pip 安裝
pip3.6 install pymysql
pip3.6 install mysqlclient 
# 我在安裝mysqlclient時出現了問題,到 https://www.lfd.uci.edu找的包本身安裝的

建立 test_app

在使用model時,官方文檔說,「當你定了模型以後,你須要告訴Django你將使用這些模型。經過編輯setting.py中 INSTALL_APPS,將包含你的模型的app的名字放到裏面」數據庫

  • 打開 CMD 鍵入 以下指令:
python36 manage.py startapp test_app
  • 將會在 test_project項目下 新建一個 test_app文件目錄django

  • 做用說明json

文件名 做用
migrations 將模型的更改,造成可執行的PY文件,使用指令遷移到數據庫中
_init_.py 標識當前文件路徑是一個python包
admin.py 能夠在其中添加當前model,而後使用界面對數據庫進行操做
apps.py 當前app 配置
models.py 存放當前app存在的模型,與數據庫一一對應
tests.py 存放當前app的測試
views.py 存在當前app的頁面模板
  • 將 test_app 添加到 test_project/test_project/settings.py文件中,以下:
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # new add 
    'test_app',
]

添加 testmodel 到 test_app中、遷移到數據庫

  • 打開 文件 test_project/test_app/modes.py 更改代碼以下:
from django.db import models
# Create your models here.
class TestModel(models.Model):
    # django 有一個機制 在沒有設置自增主鍵的時候會自動建立一個主鍵,
    test_name = models.CharField(max_length=100, default='no_name') # 字符類型的字段 設置最大長度與默認值
    test_content = models.CharField(max_length=50,default='male') # 字符類型的字段 設置最大長度與默認值
    # 若是不指定表名,django默認代表是 'appname_classname'
    class Meta:
        '''
        使用以下語句定義表名
        db_table = 'test_model'
        '''
    def __unicode__(self):
        return '%d: %s' % (self.pk, self.test_name)
  • 打開 CMD 鍵入 以下命令:
python36 manage.py makemigrations #不指定app將遷移所有數據
python36 manage.py makemigrations test_app # 能夠選擇單個app進行數據遷移
#以上兩個均可以,在app多的時候,建議使用下面的單個遷移
#該命令只是生成遷移文件,並無真正的操做數據庫
#######################################################################################
#返回以下結果
Migrations for 'test_app':
  test_app\migrations\0001_initial.py
    - Create model TestModel
  • 下面我查看文件夾 test_project\test_app\migrations 增長了文件 0001_initial.py,第一次遷移文件名應該都是這個,以後會不一樣。查看 文件 0001_initial.py 內容以下:
# Generated by Django 2.0 on 2018-11-15 03:00
from django.db import migrations, models
class Migration(migrations.Migration):
    initial = True
    dependencies = [
    ]
    operations = [
        migrations.CreateModel(
            name='TestModel',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('test_name', models.CharField(default='no_name', max_length=100)),
                ('test_content', models.CharField(default='male', max_length=50)),
            ],
        ),
    ]
# 咱們能夠看到,錢 Migration類中,定義了新的 模型 TestModel,而且有三個字段 id、test_name、test_content
  • 我每次遷移的時候都會查看,生成的遷移文件,確保都是我想要的數據庫改動。打開CMD 鍵入指令:
python36 manage.py migrate
#該指令將,真正將建表操做到mysql數據庫中
#######################################################################################
#會看到以下提示
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, test_app
Running migrations:
  Applying test_app.0001_initial... OK
#能夠發現執行了 剛纔的 0001_initial.py 文件中的內容
  • 咱們打開mysql 數據庫查看,是否存在表
mysql> show create table test_app_testmodel
    -> ;
+--------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table              | Create Table                                                                                                                                                                                                                              |
+--------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| test_app_testmodel | CREATE TABLE `test_app_testmodel` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `test_name` varchar(100) NOT NULL,
  `test_content` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+--------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)
  • 至此,模型與數據庫已經實現了同步。

使用 django admin管理數據庫數據

  • 以前說過 test_app下的文件 admin.py 添加以下內容:
from django.contrib import admin

from .models import TestModel
# Register your models here.

@admin.register(TestModel)
class TestModelAdmin(admin.ModelAdmin):
    list_display = ('pk', 'test_name')    #在後臺列表下顯示的字段
  • 進入 django admin頁面 輸入超級用戶用戶名、密碼api

  • 經過 admin 管理 test model,點擊上面的 Test models 能夠經過頁面進行增、刪、改、查的操做數組

介紹一下Django提供的字段類型

  • 基本類型
AutoField #自增列,若是不存在的話會添加一個自增的ID列
BigAutoField # 64位的,比上面自增列大
BigIntegerField #64 位的整型
BinaryField #原生的二進制列
BooleanField#布爾
CharField#字符串,注意該字段必須指定 max_length
DateField#日期,能夠指定auto_now 與 auto_now_add能夠自動填充當前列爲當前時間
DateTimeField# datetime
DecimalField# 小數點
DurationField# 與python的timedelta對應
EmailField
FileField
FileField and FieldFile
FilePathField
FloatField
ImageField
IntegerField
GenericIPAddressField
NullBooleanField
PositiveIntegerField
PositiveSmallIntegerField
SlugField
SmallIntegerField
TextField
TimeField
URLField
UUIDField
# 不是全部的 field 都用過,有興趣請自行嘗試
  • ArrayField

最近使用 Postgresql 開發,發現它支持,array類型。在Django,中一樣支持,代碼以下:

class TestModel(models.Model):
    test_array = ArrayField(models.CharField(max_length=96, null=False, default=''), default="{}", size="99")
    # 意思爲增長一個 test_array數組字段,而且數組元素都是char ,能夠更換成其餘類型
    #此處default {}是由於 postgresql在檢測的時候強制插入數據爲 '{a,b,c,d}',default空的話會報錯
    class Meta:
        db_table = 'test_model'
    def __str__(self):
        return self.node

代碼中的增刪改查

  • 分別在如下文件中添加以下代碼,路由具體說明將會從新寫一篇文章
# test_project/test_project/urls.py
from django.conf.urls import url
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    path('', include('test_app.urls')),#包括test_app的url
]
#建立 test_project/test_app/urls.py
from django.conf.urls import url
from test_app import views
urlpatterns = [
    url('test_app/test_model', views.test_model),
]
# 須要定義一個查詢的api
# test_project/test_app/views.py
from django.shortcuts import render
from django.http import HttpResponse
from . import models
import json as json
from django.core import serializers
def test_model(request):
    data  = models.TestModel.objects.all()
    data_json = json.loads(serializers.serialize('json', data))#將queryset變成json輸出
    print(str(data_json))
    return HttpResponse(data_json); 
#啓動Django服務後,在瀏覽器中輸入 localhost:8000/test_app/test_model
#打印結果將在cmd顯示
# 更換不一樣的查詢方式,打印輸出結果
# 數據庫中插入了兩條數據
models.TestModel.objects.all() #獲取全部的數據 返回queryset
models.TestModel.objects.all().values('test_name') #只取test_name列 返回queryset
models.TestModel.objects.get("id=1") #只要id=1 返回object
models.TestModel.objects.all().filter("id=2") #只要id=2 返回queryset
models.TestModel.objects.all().exclude("id=2") #排除id=2 返回queryset
#打印結果
*******
[{'model': 'test_app.testmodel', 'pk': 1, 'fields': {'test_name': 'name1', 'test_content': 'content1'}}, {'model': 'test_app.testmodel', 'pk': 2, 'fields': {'test_name': 'test2', 'test_content': 'content2'}}]
*******
<QuerySet [{'test_name': 'name1'}, {'test_name': 'test2'}]>
*******
TestModel object (1)
*******
[{'model': 'test_app.testmodel', 'pk': 2, 'fields': {'test_name': 'test2', 'test_content': 'content2'}}]
*******
<QuerySet [<TestModel: TestModel object (1)>]>
*******
#更細節的查詢,官網查看吧
https://docs.djangoproject.com/en/2.0/topics/db/queries/
#更改 test_project/test_app/urls.py,添加對於增長數據的url配置
from django.conf.urls import url
from test_app import views
urlpatterns = [
    url('test_app/test_model', views.test_model),
    # new add
    url('test_app/test_addto_model', views.add_test_model),
]
#更改 test_project/test_app/views.py 新增以下函數代碼
def add_test_model(request):
    models.TestModel.objects.create(
                   test_name="name_add_by_code",test_content="content_add")
    new_data = models.TestModel.objects.all()
    new_data_json = json.loads(serializers.serialize('json', new_data))
    return HttpResponse(new_data_json);
#啓動 django 服務後,訪問連接 localhost:8000/test_app/test_addto_model
頁面輸入結果:
{'model': 'test_app.testmodel', 'pk': 1, 'fields': {'test_name': 'name1', 'test_content': 'content1'}}{'model': 'test_app.testmodel', 'pk': 2, 'fields': {'test_name': 'test2', 'test_content': 'content2'}}{'model': 'test_app.testmodel', 'pk': 3, 'fields': {'test_name': 'name_add_by_code', 'test_content': 'content_add'}}
數據庫查詢結果
mysql> select * from test_app_testmodel;
+----+------------------+--------------+
| id | test_name        | test_content |
+----+------------------+--------------+
|  1 | name1            | content1     |
|  2 | test2            | content2     |
|  3 | name_add_by_code | content_add  |
+----+------------------+--------------+
3 rows in set (0.00 sec)
增長成功
# 因爲考慮到數據完整行,簡單介紹一下 Django 的 【事物】
from django.db import transaction
with transaction.atomic():
    #數據庫操做
#上面是最簡單的方法,過程當中報錯將不會操做數據庫
#詳情參加官網:https://docs.djangoproject.com/en/2.0/topics/db/transactions/
#不作演示了,直接上代碼
models.UserInfo.objects.filter(test_name='nam1').update(test_content='content1_update')
#刪除的時候必定要filter一下呦
models.UserInfo.objects.filter(test_name='test2').delete()

數據庫結構的導入到代碼

  1. 下載了項目代碼,可是本地數據庫中沒有項目表結構
  2. 數據庫在後臺改動了,要同步到代碼中
python36 manage.py inspectdb

注:在使用makemigrations 與 migrate時,每一次的 makemigrations 是基於上一個makemigrations進行比較的,若是某一次的makemigrations後,migrate失敗,切記到 app下 migrations文件夾下刪除,最新的makemigrations文件,而後修改model代碼,從新makemigrations,不然將會報錯一直遷移不到數據庫中。被這個坑了很久。

相關文章
相關標籤/搜索