1. 程式人生 > >使用Django建立“學習筆記”①

使用Django建立“學習筆記”①

規範:編寫一個名為“學習筆記”的Web應用程式,讓使用者能夠記錄感興趣的主題,並在學習每個主題的過程中新增日誌條目。“學習筆記”的主頁對這個網站進行描述,並邀請使用者註冊或登入。使用者登入後,就可建立新的主題、新增新條目以及閱讀既有條目。

1.1 安裝virtualenv

pip install virtualenv

1.2 搭建虛擬環境

F:\xiangmu>virtualenv env11

1.3 啟用虛擬環境

env11\Scripts\activate

1.4 安裝Django

pip install Django

1.5 建立專案

(env11) F:\xiangmu>django-admin startproject studylog .#不要忘記末尾的空格句點 該句點讓新專案使用合適的目錄結構

在這過程中遇到了不少麻煩,最終解決方法:設定預設py檔案啟動方式為python.exe;命令列輸入pip install django(並非之前在虛擬環境);去掉django-admin字尾.py

1.6 建立資料庫

python manage.py migrate

1.7 檢視核實django專案

(env11) F:\xiangmu>python manage.py runserver#執行
Performing system checks...

System check identified no issues (0 silenced).#檢查確認建立正確專案
September 19, 2018 - 07:22:23
Django version 2.1.1, using settings 'studylog.settings'
Starting development server at http://127.0.0.1:8000/#指出了專案的url
Quit the server with CTRL-BREAK.

2.1 定義模型

(env11) F:\xiangmu>python manage.py startapp studylogs #不同於studylog,新檔案,用於建立app所需的基本設施

(env11) F:\xiangmu>dir
 驅動器 F 中的卷是 新加捲
 卷的序列號是 66ED-CACB

 F:\xiangmu 的目錄

2018/09/19 週三  07:36    <DIR>          .
2018/09/19 週三  07:36    <DIR>          ..
2018/09/19 週三  07:15           131,072 db.sqlite3
2018/09/19 週三  05:28    <DIR>          env11
2018/09/19 週三  07:06               555 manage.py #定義管理的資料
2018/09/19 週三  07:15    <DIR>          studylog
2018/09/19 週三  07:36    <DIR>          studylogs
# coding=utf-8
from django.db import models
#在這裡建立模型,模型即是一個類
class Topic(models.Model):
    '''使用者學習的主題'''
    text = models.CharField(max_length=200)#儲存少量文字,200個字元的預留空間
    date_added = models.DateTimeField(auto_now_add=True)#記錄日期和時間的資料,並自動設定成當前日期和時間

    def __str__(self):
        '''返回模型的字串表示'''
        return self.text

2.2 啟用模型

開啟位於studylog中的settings.py檔案,修改其部分,將之前的應用程式tian新增其中

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'studylogs'#剛才修改的models.py所在的資料夾
]

需要讓django修改資料庫,使其能夠儲存與模型相關的資訊

(env11) F:\xiangmu>python manage.py makemigrations studylogs#
Migrations for 'studylogs':
  studylogs\migrations\0001_initial.py
    - Create model Topic

(env11) F:\xiangmu>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, studylogs
Running migrations:
  Applying studylogs.0001_initial... OK

(env11) F:\xiangmu>

每次需要修改管理的資料時,都有三個步驟:1.修改models.py 2.對studylogs呼叫makemigrations 3.讓Django遷移專案

2.3 Django管理網站

①建立超級使用者(管理員)

(env11) F:\xiangmu>python manage.py createsuperuser
Username (leave blank to use 'administrator'): admin
Email address: [email protected]
Password:
Password (again):
This password is too short. It must contain at least 8 characters.
This password is entirely numeric.
Bypass password validation and create user anyway? [y/N]: N
Password:
Password (again):
Superuser created successfully.

②向管理網站註冊模型

開啟studylogs下的admin.py,修改其資料

from django.contrib import admin

# Register your models here.
from studylogs.models import Topic#匯入要註冊的Topic類
admin.site.register(Topic)#讓Django通過管理網站管理模型

③新增主題

2.4 定義模型Entry

需要為使用者可在學習筆記中新增的條目定義模型,每個條目都與特定主題相關聯,即多對一的關係。

class Entry(models.Model):
    '''學到的有關某個主題的特定知識'''
    topic = models.ForeignKey(Topic,on_delete=models.CASCADE)#foreignkey外來鍵,引用資料庫的另一條記錄
    text = models.TextField()
    date_added = models.DateTimeField(auto_now_add=True)#按建立順序顯示條目,並顯示時間戳

    class Meta:
        verbose_name_plural = 'entries'

    def __str__(self):
        return self.text[:50] + '...'

2.5 遷移模型Entry

(env11) F:\xiangmu>python manage.py makemigrations studylogs
Migrations for 'studylogs':
  studylogs\migrations\0002_entry.py
    - Create model Entry

(env11) F:\xiangmu>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, studylogs
Running migrations:
  Applying studylogs.0002_entry... OK

2.6 向管理網站註冊Entry

from django.contrib import admin

# Register your models here.
from studylogs.models import Topic,Entry
admin.site.register(Topic)
admin.site.register(Entry)

修改admin.py檔案

2.7 django shell

django shell:通過互動式終端會話以程式設計方式檢視資料,是測試專案和排除故障的理想之地。例如

(env11) F:\xiangmu>python manage.py shell
Python 3.6.5 |Anaconda, Inc.| (default, Mar 29 2018, 13:32:41) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from studylogs.models import Topic#這裡匯入模組studylogs中的模型topic
>>> Topic.objects.all()#返回一個列表,查詢集
<QuerySet [<Topic: Chess>, <Topic: Game>]>
#可以進行遍歷,查詢id,通過id檢視其屬性
>>> topics = Topic.objects.all()
>>> for topic in topics:
...   print(topic.id,topic)
...
1 Chess
2 Game
>>> t = Topic.objetcs.get(id=2)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: type object 'Topic' has no attribute 'objetcs'
>>>  t = Topic.objects.get(id=2)
  File "<console>", line 1
    t = Topic.objects.get(id=2)
    ^
IndentationError: unexpected indent
>>> t = Topic.objects.get(id=2)
>>> t.text
'Game'
>>> t.date_added
datetime.datetime(2018, 9, 19, 0, 33, 9, 870659, tzinfo=<UTC>)

ctrl+z退出shell

3.1 對映URL

開啟studylog中的url.py:

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('studylogs.urls',namespace='studylogs')),
]

需要在studylogs中建立另一個urls.py檔案:(難)

# coding=utf-8
'''定義studylogs的url模式'''
from django.urls import path
from . import views
app_name='studylogs'
urlpatterns = [
    path('',views.index,name='index'),
]#URL模式三個實參 正則表示式 呼叫的檢視函式將其命名為index

最後網站無法開啟排查原因,出現在了這裡,django2與django1在url上語法不同,1→2:urls→path,取消了之前的正則表示式url模式

3.2 編寫檢視

開啟views.py

from django.shortcuts import render

# Create your views here.
def index(request)#主頁
    return render(request,'studylogs/index.html')

3.3 編寫模板

在studylogs下新建一個templates(模板)資料夾,再在其中建立studylogs資料夾,在最新的studylogs資料夾中新建一個index.html的檔案,並且修改:

<p>study log</p>
<p>i will remember the day i did this</p>

4.1 模板繼承

建立父模板base.html

<p>
    <a href="{% url 'studylogs:index' %}">studylog</a>
</p>
{% block content %}{% endblock content %}

修改子模板index.html

{% extends "studylogs/base.html"%}
{% block content %}
<p>i will remember the day i did this</p>
{% endblock content %}

4.2 url模式

修改studylogs下的urls.py

from django.urls import path
from . import views

app_name = 'studylogs'
urlpatterns = [
    path('', views.index, name='index'),
    path('topics/', views.topics, name='topics'),
]

修改views.py

from django.shortcuts import render
from .models import Topic

# Create your views here.
def index(request):
    return render(request,'studylogs/index.html')

def topics(request):
    topics = Topic.objects.order_by('date_added')#查詢資料庫,並按屬性date排序,儲存在topics中
    context = {'topics':topics}#定義一個字典,將要傳送給字典的上下文
    return render(request,'studylogs/topics.html',context)

建立一個顯示所有主題的模板,接受字典context

{% extends "studylogs/base.html"%}
{% block content %}
  <p>Topics</p>

  <ul>
      {% for topic in topics %}
        <li>{{ topic }}</li>
      {% empty %}
        <li>No topics have been added yet.</li>
      {% endfor %}
  </ul>

{% endblock content %}

修改父模板,使其包含到顯示所有主題的頁面的連結

<p>
    <a href="{% url 'studylogs:index' %}">studylog</a> -
    <a href="{% url 'studylogs:topics' %}">Topics</a>
</p>
{% block content %}{% endblock content %}

4.3 顯示特定主題的頁面

urls.py

# coding=utf-8
'''定義studylogs的url模式'''
from django.urls import path,re_path
from . import views

app_name = 'studylogs'
urlpatterns = [
    path('', views.index, name='index'),
    re_path(r'^topics(?P<topic_id>\d+)/$', views.topics, name='topics'),
]

views.py

from django.shortcuts import render
from .models import Topic

# Create your views here.
def index(request):
    return render(request,'studylogs/index.html')

def topics(request):
    topics = Topic.objects.order_by('date_added')#查詢資料庫,並按屬性date排序,儲存在topics中
    context = {'topics':topics}#定義一個字典,將要傳送給字典的上下文
    return render(request,'studylogs/topics.html',context)

def topic(request,topic_id):
    topic = Topic.objects.get(id=topic_id)
    entries = topic.entry_set.order_by('date_added')
    context = {'topic':topic,'entries':entries}
    return render(request,'studylogs/topic.html',context)