Django入门

Django入门

建立项目

先建立项目规范(先要立好规矩),再建立虚拟环境,以便在其中创建项目。

制定规范

只把这个项目的一些明确目标列出来,突出开发重点。

规范如下:

开始编写一个名为“学习笔记”的Web应用程序,让用户能够记录感兴趣的主题,并在学习每个主题的过程中添加日志条目。“学习笔记”的主页对这个网站进行描述,并邀请用户注册或登录。用户登录后,就可以创建主题、添加新条目以及阅读既有的条目。

学习新的主题时,记录学到的知识可以帮助跟踪和复习这些知识。优秀的应用程序让这个记录的过程简单易行。

参考资料

《Python从入门到实践》

Django新版本(2.x)踩坑记录

Python练习Django项目——学习笔记

Python编程从入门到实践:Web应用程序 - Django入门

HTML 教程

Django 官网文档 The Django template language

Django模板文档

建立虚拟环境并激活

虚拟环境是系统的一个位置,把它隔离出来,这是必须的返校隔离措施,之后我们还要把它公之于众——部署到服务器上。

刚刚开始问题就出现了,Windows要怎么终端切换到目录来着?之前外星人入侵的项目明明用过,给忘了。之前就是只看了一眼,没有动手去做,所以才拖了这么久,这次让我一鼓作气搞定。

C:\Users\ASUS>d:

D:\>cd learning_log

D:\learning_log>

原来切换目录这么简单,我只是还不会用(心虚,这我都不记得了,原因还是以前都没怎么认真用过电脑)

还有一个很蠢的问题也解决了,之前下载的是Anaconda 3,用的也一直是Anaconda 的Prompt,我这次直接cmd能有用才怪。不过好在总算是可以继续了。

现在我们为项目新建了一个目录, 将其命名为learning_log,使用如下命令成功创建名为ll_env的虚拟环境:

python -m venv ll_env

建立虚拟环境后, (Windows系统下)成功使用下面的命令激活它:

ll_env\Scripts\activate

要停止的话,使用终止命令deactivate

安装Django

出问题了就重新来过,建立虚拟环境然后激活,然后再安装Django包:

(ll_env) (base) D:\learning_log> pip install Django
Collecting Django

下载可能有点慢,要等一会。

记住,Django仅在虚拟环境处于活动状态才可用。

嘛,就知道没有这么简单,下载失败了,这次又是哪里出了问题呢?更新了一下pip的版本重新下载。

(ll_env) (base) D:\learning_log>pip install Django
Collecting Django
  Downloading https://files.pythonhosted.org/packages/01/a5/fb3dad18422fcd4241d18460a1fe17542bfdeadcf74e3861d1a2dfc9e459/Django-3.1.1-py3-none-any.whl (7.8MB)
     |████████████████████████████████| 7.8MB 12kB/s
Collecting pytz (from Django)
  Downloading https://files.pythonhosted.org/packages/4f/a4/879454d49688e2fad93e59d7d4efda580b783c745fd2ec2a3adf87b0808d/pytz-2020.1-py2.py3-none-any.whl (510kB)
     |████████████████████████████████| 512kB 9.5kB/s
Collecting asgiref~=3.2.10 (from Django)
  Downloading https://files.pythonhosted.org/packages/d5/eb/64725b25f991010307fd18a9e0c1f0e6dff2f03622fc4bcbcdb2244f60d6/asgiref-3.2.10-py3-none-any.whl
Collecting sqlparse>=0.2.2 (from Django)
  Downloading https://files.pythonhosted.org/packages/85/ee/6e821932f413a5c4b76be9c5936e313e4fc626b33f16e027866e1d60f588/sqlparse-0.3.1-py2.py3-none-any.whl (40kB)
     |████████████████████████████████| 40kB 7.8kB/s
Installing collected packages: pytz, asgiref, sqlparse, Django
Successfully installed Django-3.1.1 asgiref-3.2.10 pytz-2020.1 sqlparse-0.3.1
WARNING: You are using pip version 19.2.3, however version 20.2.3 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.

原来是pip命令需要更新了,按照提示更新版本就成功了。

创建项目以及数据库

django-admin.py startproject learning_log .

新建一个名为learning_log的项目,不知道又出什么问题,先到这吧,睡了睡了。

1 问题

在prompt命令窗口执行上面的命令,会打开 django-admin.py 源代码

2 原因

*.py 的默认打开方式为 pycharm。所以自然直接打开,我没有安装pycharm,所以是用vscode打开的。

3 解决

修改一下命令

django-admin startproject [项目名] .

执行成功后,输入ls命令(Windows对应dir)就会发现 Django 新建好了需要的文件

文件名 说明
settings.py 指定Django如何与你的系统交互以及如何管理项目,修改其中一些设置, 并添加一些设置
urls.py 告诉Django应创建哪些网页来响应浏览器请求
wsgi.py 帮助Django提供它创建的文件, 这个文件名是web server gateway interface(Web服务器网关接口 ) 的首字母缩写。

一大早起来直接查命令哪里出了问题,一下就解决了。接下来建立一个数据库。在这里更新了一下Django的版本。然后dir查看一下,确认后启动一个服务器,查看系统中的项目,按照响应操作打开生成的页面。

python manage.py migrate
python manage.py runserver

生成页面

至此,这个项目成功建立了,耶!

创建应用程序

打开另一个终端,切换到manage.py所在目录,激活虚拟环境,执行命令startapp。

定义模型并激活

模型告诉Django如何处理应用程序中存储的数据。 在代码层面, 模型就是一个类, 包含属性和方法。

models.py

from django.db import models

# Create your models here.
# 创建了一个名为Topic 的类, 它继承了Model ——Django中一个定义了模型基本功能的类。 Topic 类只有两个属性: text 和date_added 。
class Topic(models.Model):
    ''' 用户学习的主题'''
    text = models.CharField(max_length = 200) # 属性text是一个CharField——由字符或文本组成的数据
    # https://docs.djangoproject.com/en/1.8/ref/models/fields
    # Django Model Field Reference 用于熟悉模型中可使用的各种字段,自己开发时可能会用到
    date_added = models.DateTimeField(auto_now_add=True) # 实参auto_add_now=True 让Django将这个属性自动设置成当前日期和时间。
    def __str__(self):
        """返回模型的字符串表示"""
        return self.text

每当需要修改“学习笔记”管理的数据时, 都采取如下三个步骤: 修改models.py; 对learning_logs 调用makemigrations ; migrate让Django迁移项目。

python manage.py makemigrations learning_logs
# 让Django修改数据库, 使其能够存储与模型Topic 相关的信息
# 命令makemigrations 让Django确定该如何修改数据库, 使其能够存储与定义的新模型相关联的数据。
python manage.py migrate
# 应用这种迁移, 让Django替我们修改数据库

Django 管理网站

为应用程序定义模型时,Django提供的管理网站(admin site)让你能够轻松地处理模型。网站的管理员可使用管理网站,但普通用户不能使用。

创建超级用户

(ll_env)learning_log>python manage.py createsuperuser
❶ Username (leave blank to use 'ehmatthes'): ll_admin
❷ Email address:
❸ Password:
  Password (again):
  Superuser created successfully.

向管理网站注册模型

Django自动在管理网站中添加了一些模型,如User 和Group ,但对于我们创建的模型,必须手工进行注册。我们创建应用程序learning_logs 时,Django在models.py所在的目录中创建了一个名为admin.py的文件。

添加主题

在网站上测试添加主题“Chess”和“Rock Climbing”

定义并迁移模型Entry

要记录学到的国际象棋和攀岩知识,需要为用户可在学习笔记中添加的条目定义模型。每个条目都与特定主题相关联,这种关系被称为多对一关系,即多个条目可关联到同一个主题。

from django.db import models

# Model是Django中一个定义了模型基本功能的类
class Topic(models.Model):
        --snip--

class Entry(models.Model):
    """学到的有关某个主题的具体知识"""
    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 self.text[:50]+"..."

属性topic 是一个ForeignKey 实例,外键是一个数据库术语,引用了数据库中的另一条记录;

这些代码将每个条目关联到特定的主题。每个主题创建时,都给它分配了一个键(或ID)。 需要在两项数据之间建立联系时,Django使用与每项信息相关联的键。Django2.0版本外键要求添加on_delete参数。

在Entry 类中嵌套了Meta 类。Meta 存储用于管理模型的额外信息,设置一个特殊属性,让Django需要时使用Entries表示多个条目,没有这个类将使用Entrys来表示多个条目。

没有看明白这些想说明什么,往后看应该就会知道了。接下来迁移数据库。生成新的迁移文件。

添加一个模型,就迁移一次数据库。过程:修改models.py,执行命令python manage.py makemigrations app_name ,再执行命令python manage.py migrate 。

向管理网站注册Entry

修改admin.py

from django.contrib import admin
from learning_logs.models import Topic, Entry
admin.site.register(Topic)
admin.site.register(Entry)

Django shell

python manage.py shell

Cr+Z,回车退出

用于测试和排除故障的理想之地

更多关于如何查询数据的文档

创建网页:学习笔记主页

定义URL、编写视图和编写模板。

urls -> views -> html 添加网页步骤。

映射URL

在WWW上,每一信息资源都有统一的且在网上唯一的地址,该地址就叫URL(Uniform Resource Locator,统一资源定位器),它是WWW的统一资源定位标志,就是指网络地址。

实际的URL模式是一个对函数url的调用,这个函数接受三个实参。

urlpatterns = [
    #主页
    #第一个是正则表达式,r让Python将接下来的字符串视为原始字符串,引号正则表达式始于和终于何处
    #第二个实参指定了要调用的视图函数
    #第三个实参将这个URL模式的名称指定为index
    path(r'',views.index,name='index'),
    ]

正则表达式(regex),这是个什么鬼东西?相信后面还会有很多见面的机会……

请求的URL与正则表达式匹配时调用视图函数

编写视图和模板

默认的urls.py包含在文件夹learning_log中, 现在需要在文件夹learning_logs中创建另一个urls.py文件:(注意关于 Django版本更新,书上的代码需做相应修改)

打开项目主文件夹learning_log中的文件urls.py, 修改为
learning_log/urls.py

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

urlpatterns = [
    path('admin/', admin.site.urls),# 该模块定义了可在管理网站中请求的所有URL
    path('', include('learning_logs.urls', namespace='learning_logs')), 
    # 代码包含实参namespace , 让我们能够将learning_logs 的URL同项目中的其他URL区分开来
]
'''
Django版本更新,书上的代码需做相应修改

书中源代码:
from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'', include('learning_logs.urls', namespace='learning_logs')),
]
应改为:
from django.contrib import admin
from django.urls import path, include

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

'''

默认的urls.py包含在文件夹learning_log中, 现在需要在文件夹learning_logs中创建另一个urls.py文件:(注意关于 Django版本更新,书上的代码需做相应修改)
learning_logs/urls.py

"""定义learning_logs的URL模式"""
from django.urls import path,re_path
from . import views

app_name='learning_logs' # 不能少 ,否则runserver的时候就会出错

# https://docs.djangoproject.com/en/2.2/ref/urls/#module-django.urls.conf
urlpatterns = [
    # 主页
    path('', views.index, name='index'),
    # Django将在文件views.py中查找函数index()
]

# urls -> views -> html  添加网页步骤

'''
Django版本更新,书上的代码需做相应修改

书中源代码:
from django.conf.urls import url
from . import views
urlpatterns = [
     # Home page.
    url(r'^$', views.index, name='index'),

    # Show all topics.
    url(r'^topics/$', views.topics, name='topics'),

    # Detail page for a single topic.
    url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),
]

应改为:
from django.urls import path
from . import views

app_name='learning_logs'
urlpatterns = [
    # 主页
    path('', views.index, name='index'),

    # 显示所有的主题
    path('topics/', views.topics, name='topics'),

    # 特定主题的详细页面
    path("topics/(?P<topic_id>\d+)/", views.topic, name='topic'),
]

'''

创建其他网页

确定创建网页的流程后,可以扩充“学习笔记”项目了。

接下来要创建两个显示数据的页面。

所以先创建一个父模板,其他模板都将继承它。

模板继承

父模板

这个文件包含所有页面都有的元素; 其他的模板都继承base.html。 当前, 所有页面都包含的元素只有顶端的标题。 将在每个页面中包含这个模板, 因此将这个标题设置为到主页的链接:

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

{% block content %}{% endblock content %}
{% endraw %}

模板标签用({ % % })表示,生成一个URL。

在简单的HTML页面中,用锚标签定义链接:

 <a href="link_url">link text</a>

要修改项目中的URL,只需要修改urls.py中的URL模式。

子模板

重新编写index.html,使其继承base.html。

显示所有主题的页面

urls -> views -> html 添加网页步骤

下面来写一个显示全部主题的页面和一个显示特定主题中条目的页面。

name 'request' is not defined

views.py

def topics(request) 写错成 def topics(reqest)了

显示特定主题的页面

Reverse for 'topic' with arguments '('',)' not found. 1 pattern(s) tried: ['topics/(?P<topic_id>\\d+)/$']

return render(request, ‘learning_logs/topic.html’,context)

写成了

return render(request, ‘learning_logs/topics.html’,context)

  # 特定主题的详细页面
  # 错误
  # path("topics/(?P<topic_id>\d+)/", views.topic, name='topic'),

  # 正确
  re_path(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),
  # ?P<topic_id> 将匹配的值存储到topic_id 中; 而表达式\d+ 与包含在两个斜杆内的任何数字都匹配, 不管这个数字为多少位。

小结

今天首先学习了如何使用Django框架来创建Web程序应用,相信其他语言或者框架都是大同小异。

然后制定了项目规范,列出参考资料,最后在项目完成后需要鸣谢。

在虚拟环境中安装Django,创建一个项目,并且核实已经成功立项。

学习如何创建应用程序,以及如何定义表示应用程序数据的模型。

学习了数据库,以及在修改模型后让Django来迁移数据库。

创建了可管理网站的超级用户,并使用管理网站输入了一些数据。

探索Django Shell,它能够让我在终端对话处理项目数据,排除障碍。

学习了如何定义URL、创建网络视图以及编写网页的模板。最后还使用了模板继承,让各个模板简化,使修改网站变得更加容易。

遇上了劲敌“正则表达式”和“URL模式”,而且由于Django版本更新,url()和path()等函数更是变得乱七八糟,最后还是靠着上网看别人写的博客才K.O了它们。


下一次,我们将创建对用户友好而直观的网页,让用户无需管理网站就可以使用“学习笔记”。

我们还将添加一个用户注册系统,让用户能够注册和创建自己的学习笔记。

“让任意数量的用户都能与之交互,是Web应用程序的核心所在。”


   转载规则


《Django入门》 Henry-Avery 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录