天天看點

Python Web開發-Django2.0學習03

三、資料庫

1、建立資料庫

Django為多種資料庫背景提供了統一的調用API。根據需求不同,Django可以選擇不同的資料庫背景,有:PostgreSQL、SQLite3、MySQL、Oracle。預設情況下,配置使用SQLite3,SQLite3包含在Python中,是以不需要安裝任何東西來支援你的資料庫。但是,當開始你的第一個真正項目時,你可能想要使用一個更可擴充的資料庫,我們這裡以Django連接配接MySQL資料庫為例。

在cmd中輸入:

mysql -uroot -p
           

輸入密碼後,在MySQL中建立項目的資料庫polls:

mysql> CREATE DATABASE polls DEFAULT CHARSET=utf8;
           

這裡使用utf8作為預設字元集,以便支援中文。

在MySQL中為Django項目創立使用者,并授予相關權限:

mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, REFERENCES ON polls.* TO 'admin'@'localhost' IDENTIFIED BY 'admin123456.';

//grant all privileges on 想授權的資料庫.* to 'user1'@'%';
//flush privileges;
           

在settings.py中,将DATABASES對象更改為:

DATABASES = {
    'default': {
        # 'ENGINE': 'django.db.backends.sqlite3',
        # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'polls',
        'USER': 'admin',
        'PASSWORD': 'admin123456.',
        'HOST': 'localhost',
        'PORT': '3306', # 預設
    }
}
           

設定完之後要檢查是否已安裝MySQLdb子產品,否則伺服器無法啟動。在Python shell中輸入:

import MySQLdb
           

若上報ImportError: No module named MySQLdb,則未安裝MySQLdb子產品。

對于不同的系統和程式有如下的解決方法:

easy_install mysql-python (mix os)
pip install mysql-python (mix os)
apt-get install python-mysqldb (Linux Ubuntu)
cd/usr/ports/databases/py-MySQLdb && make install clean (FreeBSD)
yum install MySQL-python (linux Fedora, CentOS)
pip install mysqlclient (Windows)親測可用
           

**PS:**Mysql相關資料:

  • MySQL下載下傳安裝、配置與使用(win7x64)
  • Navicat for MySQL下載下傳、安裝與破解
  • Navicat for MySQL 11.2.15 中文免費版
  • mysql資料庫管理工具navicat for mysql怎麼用
  • Windows下Mysql5.7忘記root密碼的解決方法

2、建立模型

模型,實質上就是您的資料庫布局,并附加中繼資料。在Django中,每個模型都由一個繼承自django.db.models.Model的子類來表示,每個模型都有許多類變量,每個變量表示模型中的資料庫字段。

MySQL是關系型資料庫,但在Django的幫助下,我們不用直接編寫SQL語句。Django将關系型的表(table)轉換成為一個類(class),每個記錄(record)是該類下的一個對象(object),表的每一列(column)是該類的一個屬性(field)。這樣,我們就可以使用基于對象的方法,來操縱關系型的MySQL資料庫。

在polls/models.py中輸入:

from django.db import models

# Create your models here.
class Question(models.Model):
    question_text = models.CharField(max_length = 200)
    pub_date = models.DateTimeField('釋出日期')
    def __str__(self):
        return self.question_text

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete = models.CASCADE)
    choice_text = models.CharField(max_length = 200)
    votes = models.IntegerField(default = 0)
    def __str__(self):
        return self.choice_text
           

接着需要同步資料庫,在cmd中分别輸入:

# 1. 建立更改的檔案
python manage.py makemigrations#後面可加上要同步的對應app名稱
# 2. 将生成的py檔案應用到資料庫
python manage.py migrate##後面可加上要同步的對應app名稱
           

成功後,會建立polls/migrations/0001_initial.py檔案。打開檔案可發現,Django會自動增加一個id列,作為記錄的主鍵(Primary Key)。

想看到同步資料庫過程中運作的SQL語句,可在cmd中輸入:

python manage.py sqlmigrate polls 0001
           

檢查同步過程中的問題,可在cmd中輸入:

python manage.py check
           

3、使用資料庫API

Django提供了豐富的資料庫API,我們可以進入該項目的Python shell中使用它,使用以下指令調用Python shell:

python manage.py shell
           

在Python shell中使用資料庫API,代碼如下:

>>> from polls.models import Question, Choice   # Import the model classes we just wrote.

# No questions are in the system yet.
>>> Question.objects.all()
<QuerySet []>

# Create a new Question.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())

# Save the object into the database. You have to call save() explicitly.
>>> q.save()

# Now it has an ID.
>>> q.id
1

# Access model field values via Python attributes.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

# Change values by changing the attributes, then calling save().
>>> q.question_text = "What's up?"
>>> q.save()

# objects.all() displays all the questions in the database.
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
           

使用自定義方法,進一步探索資料庫API,先在polls/models.py中增加如下代碼:

import datetime

from django.db import models
from django.utils import timezone


class Question(models.Model):
    # ...
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
           

關于Python的标準datetime子產品和Django的timezone子產品,可參考文檔time zone support docs。

在Python shell中使用資料庫API,代碼如下:

>>> from polls.models import Question, Choice

# Make sure our __str__() addition worked.
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>

# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>

# Get the question that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>

# Request an ID that doesn't exist, this will raise an exception.
>>> Question.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Question matching query does not exist.

# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Question.objects.get(id=1).
>>> Question.objects.get(pk=1)
<Question: What's up?>

# Make sure our custom method worked.
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True

# Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a question's choice) which can be accessed via the API.
>>> q = Question.objects.get(pk=1)

# Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
<QuerySet []>

# Create three choices.
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)

# Choice objects have API access to their related Question objects.
>>> c.question
<Question: What's up?>

# And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3

# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

# Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()
           

想了解更多有關模型關系的資訊,可參考Accessing related objects。了解更多有關如何使用雙下劃線查找字段的資訊,可參考Field lookups。資料庫API的完整詳細資訊,請查閱Database API reference。

4、在網頁顯示資料

在polls/views.py中,定義視圖函數survey,并從資料庫中讀取記錄,代碼如下:

from django.shortcuts import render
from django.http import HttpResponse

from polls.models import Question, Choice

# Create your views here.
def index(request):
    return HttpResponse('Hello, world! You\'re at the polls index. ')

def survey(request):
    q1 = Question.objects.get(id=1)
    q1_str = str(q1)
    choice_list = q1.choice_set.all()
    choice_str = map(str, choice_list)
    return HttpResponse("<p>" + q1_str +':'+ ' '.join(choice_str) + "</p>")
           

在polls/urls.py中,進行URL配置(前面已在mysite/urls.py中設定polls.urls通路對象),代碼如下:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name = 'index'),
    path('survey/', views.survey, name = 'survey'),
]
           

運作伺服器,在浏覽器中輸入URL:127.0.0.1:8001/polls/survey檢視效果。

5、背景管理admin

admin界面通常在mysite/urls.py中已經設定好,位于path(‘admin/’, admin.site.urls),使用如下。

首先,需要建立一個可以登入管理網站的賬号,在cmd中輸入:

python manage.py createsuperuser
           

填寫使用者名、郵箱和密碼,這裡我們建立了一個admin賬号。

接着需要将資料模型注冊到admin中,修改polls/admin.py檔案(如果沒有建立一個),代碼如下:

from django.contrib import admin
from .models import Question, Choice

# Register your models here.
admin.site.register(Question)
admin.site.register(Choice)
           

運作伺服器,在浏覽器中輸入URL:127.0.0.1:8001/admin,填寫前面建立的使用者名和密碼,就可以檢視效果。

參考資料

  • Django官方文檔
  • 自強學堂
  • 被解放的姜戈
  • The Django Book