Django是一个web框架。可用来构建交互式网站。

设置项目

首先需要写项目说明书(spec)。
然后需要创建虚拟环境(virtual environment)。
虚拟环境是一个隔离的环境,可以单独virtual environment)。
虚拟环境是一个隔离的环境,可以单独为应用安装package,而非整个系统可见

首先创建虚拟环境,并在其中安装Django模块:

# 为显示美观,需设置提示符
$ export PS1='$ '
$ mkdir learning_log
$ cd learning_log
# 注意使用python3而非python, venv是虚拟环境模块,ll_env是虚拟环境的名字
$ python3 -m venv ll_env
# 激活虚拟环境,停用虚拟环境输入deactivate
$ source ll_env/bin/activate
(ll_env) $
# 升级pip,本步骤可选
(ll_env) $ pip install --upgrade pip
# 在虚拟环境下安装django,此package只在此环境下可见。也就是说,每个虚拟环境下都需要安装一次。
(ll_env) $ pip install django

然后创建Django项目learning_log:

# 创建项目,learning_log为项目名
(ll_env) $ django-admin startproject learning_log .
# 查看当前目录,和操作系统下的显示是一致的
(ll_env) $ ls
learning_log  ll_env  manage.py
# 查看learning_log目录
(ll_env) $ ls learning_log
asgi.py  __init__.py  settings.py  urls.py  wsgi.py
# 查看ll_env目录,似乎操作系统下的命令也可以在虚拟环境中执行
(ll_env) $ ls ll_env
bin  include  lib  lib64  pip-selfcheck.json  pyvenv.cfg
(ll_env) $ du -sk ll_env
49544   ll_env

以上的几个文件说明以下,详细说明见这里:

  • manage.py,此项目的主程序,接受参数并传递给Django执行
  • learning_log/settings.py, 项目配置文件
  • learning_log/urls.py,针对浏览器请求,构建什么页面
  • learning_log/wsgi.py,web server gateway interface配置文件
  • learning_log/asgi.py,Asynchronous Server Gateway Interface配置文件

接下来创建数据库,因Django需要用其存放数据:

# migrate命令会确保数据库与项目的当前状态匹配,第一次执行时会创建数据库
# 数据库使用的是SQLite,数据库名为db.sqlite3,生成在当前目录下
# 另外,在虚拟环境下,直接用python而非python3,因其会自动匹配python版本
(ll_env) $ python manage.py migrate
Operations to perform:Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:Applying contenttypes.0001_initial... OKApplying auth.0001_initial... OKApplying admin.0001_initial... OKApplying admin.0002_logentry_remove_auto_add... OKApplying admin.0003_logentry_add_action_flag_choices... OKApplying contenttypes.0002_remove_content_type_name... OKApplying auth.0002_alter_permission_name_max_length... OKApplying auth.0003_alter_user_email_max_length... OKApplying auth.0004_alter_user_username_opts... OKApplying auth.0005_alter_user_last_login_null... OKApplying auth.0006_require_contenttypes_0002... OKApplying auth.0007_alter_validators_add_error_messages... OKApplying auth.0008_alter_user_username_max_length... OKApplying auth.0009_alter_user_last_name_max_length... OKApplying auth.0010_alter_group_name_max_length... OKApplying auth.0011_update_proxy_permissions... OKApplying sessions.0001_initial... OK

如果你在运行以上migrate命令时,报错说SQLite版本过低,则需要升级SQLite,参照此文。
大略过程如下,请用root执行:

# cd ~
# wget https://www.sqlite.org/2019/sqlite-autoconf-3270200.tar.gz
# tar -zxvf sqlite-autoconf-3270200.tar.gz
# cd sqlite-autoconf-3270200
# ./configure --prefix=/usr/local
# make && make install
# mv /usr/bin/sqlite3  /usr/bin/sqlite3_old
# ln -s /usr/local/bin/sqlite3   /usr/bin/sqlite3
# OS中查看版本
# sqlite3 --version
3.27.2 2019-02-25 16:06:06 bd49a8271d650fa89e446b42e513b595a717b9212c91dd384aab871fc1d0f6d7
# 下面的环境变量设置非常重要,请写在用户启动文件中,如.bash_profile
# export LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:/usr/local/lib
# Python中查看版本,这里显示对了才是真起作用。如果不设置LD_LIBRARY_PATH则仍显示老版本
# python3
Python 3.6.8 (default, Aug  7 2019, 08:02:28)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39.0.1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlite3
>>> sqlite3.sqlite_version
'3.27.2'

查看项目:

# 以前台方式运行server,默认监听端口是8000,在runserver后面可以直接指定其它端口号
(ll_env) $ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...System check identified no issues (0 silenced).
January 18, 2020 - 08:00:19
Django version 3.0.2, using settings 'learning_log.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C. <- 就停在这了

这时在其它终端可以测试server是否正常:

$ netstat -an|grep 8000
tcp        0      0 127.0.0.1:8000          0.0.0.0:*               LISTEN$ curl http://127.0.0.1:8000/

如果用浏览器看,就是下面这个样子:

启动应用

Django项目由多个应用组成,我们先启动一个应用。以下命令需另启一终端执行:

$ source ll_env/bin/activate
# 应用名称为learning_logs,比项目名称learning_log多一个s
(ll_env) $ python manage.py startapp learning_logs
(ll_env) $ ls
db.sqlite3  learning_log  learning_logs  ll_env  manage.py
(ll_env) $ ls learning_logs
admin.py  apps.py  __init__.py  migrations  models.py  __pycache__  tests.py  views.py

接下来定义Model,也就是业务模型,代码层面就是Class。
用户可创建多个topic,每个topic可有多个entry。entry为文本类型,同时需要记录时间。因此,在应用目录下编辑文件models.py如下:

from django.db import models# Create your models here.
class Topic(models.Model):"""A topic the user is learning about."""text = models.CharField(max_length=200)date_added = models.DateTimeField(auto_now_add=True)def __str__(self):"""Return a string representation of the model."""return self.textclass Entry(models.Model):"""Something specific learned about a topic."""topic = models.ForeignKey(Topic, on_delete=models.CASCADE)text = models.TextField()date_added = models.DateTimeField(auto_now_add=True)class Meta:verbose_name_plural = 'entries'def __str__(self):"""Return a string representation of the model."""return f"{self.text[:50]}..."

然后需要激活模型,在项目的settings.py文件中先添加应用,放在最前,余下的是系统应用:

INSTALLED_APPS = ['learning_logs',
...'django.contrib.messages','django.contrib.staticfiles',
]

因为发生了修改,因此就需要应用这些修改,步骤如下。。

(ll_env) $ python manage.py makemigrations learning_logs
Migrations for 'learning_logs':learning_logs/migrations/0001_initial.py- Create model Topic(ll_env) $ python manage.py migrate
Operations to perform:Apply all migrations: admin, auth, contenttypes, learning_logs, sessions
Running migrations:Applying learning_logs.0001_initial... OK

以后每次发生修改都需要这么做,例如第二次应用变更时的输出如下:

(ll_env) $ python manage.py makemigrations learning_logs
Migrations for 'learning_logs':learning_logs/migrations/0002_entry.py- Create model Entry
(ll_env) $ python manage.py migrate
Operations to perform:Apply all migrations: admin, auth, contenttypes, learning_logs, sessions
Running migrations:Applying learning_logs.0002_entry... OK

一些操作可通过Django管理站点(Admin Site)来做,例如添加Topic,添加Entry。不过首先需要创建管理用户:

(ll_env) $ python manage.py createsuperuser
Username (leave blank to use 'vagrant'): ll_admin
Email address:
Password: Welcome1
Password (again): Welcome1
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.

创建完用户后,然后将model加入到应用的admin.py文件中:

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

然后就可以访问管理站点http://localhost:8000/admin/了。
在管理站点添加ChessRock Climbing两个Topic。为Chess创建1个entry,Rock Climbing创建2个entry:

在本节最后,我们介绍Django Shell,是一个交互式终端,主要用于调试和故障排除。

## 进入Shell
(ll_env) $ python manage.py shell
Python 3.6.8 (default, Aug  7 2019, 08:02:28)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39.0.1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from learning_logs.models import Topic
>>> Topic.objects.all()
<QuerySet [<Topic: Chess>, <Topic: Rock Climbing>]>
>>> topics = Topic.objects.all()
>>> for topic in topics:
...     print(topic.id, topic)
...
1 Chess
2 Rock Climbing
>>> t = Topic.objects.get(id=1)
>>> t.text
'Chess'
>>> t.date_added
datetime.datetime(2020, 1, 19, 4, 5, 27, 998766, tzinfo=<UTC>)
>>> t.entry_set.all()
<QuerySet [<Entry: The opening is the first part of the game, roughly...>, <Entry: In the opening phase of the game, it’s important t...>]>
# 退出Shell
>>> <Ctrl+D>
now exiting InteractiveConsole...

构建主页

Django中制作页面包括3步:

  1. 定义URL
  2. 写view,每一个URL对应一个view
  3. 写template,view使用template做渲染,template决定了页面的模样。

首先在项目目录下定义URL,编辑urls.py文件如下:

from django.contrib import admin
from django.urls import path, includeurlpatterns = [path('admin/', admin.site.urls), # 这个是已有的管理主页path('', include('learning_logs.urls')), # 这个是新增的主页]

在以上文件中,path('admin/', admin.site.urls)是已有的行,表示路径admin/下的页面由模块admin.site.urls定义。
然后我们进入应用目录learning_log,编辑urls.py文件如下:

"""Defines URL patterns for learning_logs."""from django.urls import pathfrom . import viewsapp_name = 'learning_logs'
urlpatterns = [# Home page# 第一个参数表示URL的模式,''表示主页,也就是http://localhost:8000/;# 第二个参数表示当URL匹配时,调用的函数,这里就是views.py中的index()函数。# 第三个参数是URL的快捷名称,方便引用。path('', views.index, name='index'),
]

至此,URL定义完毕,开始写view。
在应用目录下编辑文件views.py如下,可以看到请求被转向了learning_logs/index.html

from django.shortcuts import render# Create your views here.
def index(request):"""The home page for Learning Log."""return render(request, 'learning_logs/index.html')

接下来需要写template,在应用目录下创建templates目录,然后再创建目录learning_logs
在最里一层目录编辑文件index.html如下:

<p>Learning Log</p><p>Learning Log helps you keep track of your learning, for any topic you're
learning about.</p>

好了,此时如访问页面http://localhost:8000/,显示如下:

如果遇到ModuleNotFoundError: No module named 'learning_logs.urls'的错误,<Ctrl+C>退出服务,然后重新启动服务即可:

python manage.py runserver

理解这个页面的运转流程非常重要,虽然看似复杂,但将URL,view和template分开的架构不就是MVC架构吗,架构人员,编程人员,Web设计人员可以专注于自己的领域。

构建其它页面

制作两个页面,分别显示所有的topic和特定topic下的所有view。
如果一些元素在每个页面中都需要,就可以定义基础模板,然后其它模板全部继承此基础模板。
index.html同一目录下编辑文件base.html如下:

<p><a href="{% url 'learning_logs:index' %}">Learning Log</a>
</p>{% block content %}{% endblock content %}

包含在% %之间的称为template tag,可以理解为占位符。最后一行{% block content %}{% endblock content %}是需要各子目标实现的部分。

然后重写index.html以继承基础模板:

{% extends "learning_logs/base.html" %}{% block content %}<p>Learning Log helps you keep track of your learning, for any topic you'relearning about.</p>
{% endblock content %}

接下来定义topic页面。在应用目录修改urls.py如下:

"""Defines URL patterns for learning_logs."""from django.urls import pathfrom . import viewsapp_name = 'learning_logs'
urlpatterns = [# Home pagepath('', views.index, name='index'),path('topics/', views.topics, name='topics'),
]

然后为topic页面写view。在应用目录下修改views.py如下:

from django.shortcuts import render
from .models import Topic# Create your views here.
def index(request):"""The home page for Learning Log."""return render(request, 'learning_logs/index.html')def topics(request):"""Show all topics."""topics = Topic.objects.order_by('date_added')context = {'topics': topics}return render(request, 'learning_logs/topics.html', context)

在以上文件中,context是需要传递给template的数据。在本例中就是字典。

然后为topic定义template。在index.html同一目录下编辑文件topics.html如下:

{% extends "learning_logs/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 %}

然后修改基础模板添加指向topics.html的链接。修改base.html如下:

<p><a href="{% url 'learning_logs:index' %}">Learning Log</a><a href="{% url 'learning_logs:topics' %}">Topics</a>
</p>{% block content %}{% endblock content %}

此时测试页面http://localhost:8000/topics/,显示如下:

接下来需要为每一个topic设计页面,我们准备用topic ID来区分,例如http://localhost:8000/topics/1/
因此我们修改urls.py如下:

"""Defines URL patterns for learning_logs."""from django.urls import pathfrom . import viewsapp_name = 'learning_logs'
urlpatterns = [# Home pagepath('', views.index, name='index'),path('topics/', views.topics, name='topics'),path('topics/<int:topic_id>/', views.topic, name='topic'),
]

然后为topic(注意是topic不是topics)定义view。修改view文件views.py如下:

from django.shortcuts import render
from .models import Topic# Create your views here.
def index(request):"""The home page for Learning Log."""return render(request, 'learning_logs/index.html')def topics(request):"""Show all topics."""topics = Topic.objects.order_by('date_added')context = {'topics': topics}return render(request, 'learning_logs/topics.html', context)def topic(request, topic_id):"""Show a single topic and all its entries."""topic = Topic.objects.get(id=topic_id)entries = topic.entry_set.order_by('-date_added')context = {'topic': topic, 'entries': entries}return render(request, 'learning_logs/topic.html', context)

然后为topic定义view。创建topic.html文件如下:

{% extends 'learning_logs/base.html' %}{% block content %}<p>Topic: {{ topic }}</p><p>Entries:</p><ul>{% for entry in entries %}<li><p>{{ entry.date_added|date:'M d, Y H:i' }}</p><p>{{ entry.text|linebreaks }}</p></li>{% empty %}<li>There are no entries for this topic yet.</li>{% endfor %}</ul>{% endblock content %}

最后,在topics.html页面中添加指向各topic的链接。修改topics.html如下:

{% extends "learning_logs/base.html" %}{% block content %}<p>Topics</p><ul>{% for topic in topics %}<a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a> {% empty %}<li>No topics have been added yet.</li>{% endfor %}</ul>{% endblock content %}

测试效果如下:

最后,我们回顾一下目录结构:

$ ls -1
db.sqlite3 # SQLite数据库
learning_log
learning_logs # 应用目录
ll_env # 虚拟环境
manage.py # Django主程序# 查看应用目录
$ tree learning_logs
learning_logs
├── admin.py
├── apps.py
├── __init__.py
├── migrations
│   ├── 0001_initial.py
│   ├── 0002_entry.py
│   ├── __init__.py
│   └── __pycache__
│       ├── 0001_initial.cpython-36.pyc
│       ├── 0002_entry.cpython-36.pyc
│       └── __init__.cpython-36.pyc
├── models.py
├── __pycache__
│   ├── admin.cpython-36.pyc
│   ├── __init__.cpython-36.pyc
│   ├── models.cpython-36.pyc
│   ├── urls.cpython-36.pyc
│   └── views.cpython-36.pyc
├── templates
│   └── learning_logs
│       ├── base.html
│       ├── index.html
│       ├── topic.html
│       └── topics.html
├── tests.py
├── urls.py
└── views.py5 directories, 22 files

Python Crash Course读书笔记 - 第18章:GETTING STARTED WITH DJANGO相关推荐

  1. Python Crash Course读书笔记 - 第19章:USER ACCOUNTS

    允许用户输入数据 目前用户数据Topic和Entry都是通过管理站点输入的,我们希望用户可以新增和编辑数据. 允许用户输入和提交数据的Web页面称为form,在Django中可使用ModelForm. ...

  2. Python Crash Course读书笔记 - 第2章:Variables and Simple Data Types

    变量 文件hello_world.py中, .py是python文件的后缀,因此会用Python interpreter解析. $ cat hello_world.py print("Hel ...

  3. Python Crash Course读书笔记 - 第16章:DOWNLOADING DATA

    本章首先探索在线公开数据源.然后介绍CSV和JSON格式数据的处理,并分别用Matplotlib和Plotly做可视化. CSV文件格式 CSV(comma-separated values)格式,正 ...

  4. Python Crash Course读书笔记 - 第15章:GENERATING DATA

    数据可视化是指通过可视化的手段探索数据,和数据分析紧密关联.通过代码来探索数据集的模式. 和显示酷炫的图片无关,而是让用户之前并不知道的数据含义和模式. Python被广泛应用于遗传学,气候研究,政治 ...

  5. python第三章上机实践_《机器学习Python实践》读书笔记-第三章

    <机器学习Python实践>,第三章,第一个机器学习项目 以往目录:橘猫吃不胖:<机器学习Python实践>读书笔记-第一章​zhuanlan.zhihu.com 书中介绍了一 ...

  6. 开始读Python Crash Course读书笔记

    2020年1月13日晚开始读Python Crash Cours第二版.Crash Course是速成班的意思. 简要信息如下: Python Crash Course, 2nd Edition A ...

  7. python基础教程读书笔记——第三章 字符串

    第三章 字符串 摘要: %s , $x , find()  , join() , split() , lower() , title() , strip() 1.字符串格式化 format = &qu ...

  8. 《TCP/IP具体解释》读书笔记(18章)-TCP连接的建立与中止

    TCP是一个面向连接的协议.不管哪一方向还有一方发送数据之前.都必须在两方之间建立一条连接.这样的两端间连接的建立与无连接协议UDP不同.UDP向还有一端发送数据报时,无需不论什么预告的握手. 1.建 ...

  9. 《TCP/IP详解》读书笔记(18章)-TCP连接的建立与中止

    TCP是一个面向连接的协议.无论哪一方向另一方发送数据之前,都必须在双方之间建立一条连接.这种两端间连接的建立与无连接协议UDP不同,UDP向另一端发送数据报时,无需任何预告的握手. 1.建立连接的协 ...

最新文章

  1. C#Dictionary源码
  2. 316. Remove Duplicate Letters 去除重复字母
  3. pandas输出列名_pandas中的DataFrame按指定顺序输出所有列的方法
  4. python 程序运行计时 动态,在python中运行计时器几分钟
  5. ubuntu 安装java_Hadoop3.1.3安装教程_单机/伪分布式配置
  6. jquert ajax文件 mvc,jquery ajax file upload NET MVC 无刷新文件上传
  7. daily scrum 12.2
  8. memcpy和strcpy的区别
  9. 数据库的数据进行改动,Cognos报表展示未及时更新
  10. Indesign CS6怎么添加框线_InDesign用插件快速给文本文字添加拼音的方法
  11. 专业的电脑版录音软件哪个最好用
  12. PC浏览器播放HLS协议的视频
  13. 膜拜 丹尼斯·里奇(纪念 C 语言之父离世 6 周年) 我们欠他的不止是张电影票
  14. 球体弹性碰撞位置和速度计算算法
  15. mysql给一张表做快照_MySQL之快照读
  16. 在fpga中用Cordic算法来产生正弦函数
  17. 判断手机设备是否支持5G无线频段
  18. 高斯混合模型(GMM)实现和可视化
  19. Axon Framework架构概述
  20. 8021什么意思_ox004a8021 指令引用的 0x01ac1100内存 是什么意思?

热门文章

  1. 解决:Connections could not be acquired from the unde
  2. 科技新品 | 富士胶片研发出全球最大容量数据流磁带;iGame发布内存新品“古德白”...
  3. ajax hover,jQuery / 使用hover()和toggle()切换事件 - 汇智网
  4. 如何进行微信登录授权测试?
  5. 杭州公司java开发工程师常见面试问题
  6. Spring注解开发配置
  7. 外贸须知:和各国客户做生意需要注意的点
  8. 基于微信小程序云开发(校园许愿墙app)2.0稳定版,以发布上线
  9. Gartner:新兴技术成熟度曲线2018(中文—历年)
  10. EAUML日拱一卒--序列图(Sequence Diagram)::交互和交互使用