《python编程从入门到实践》读书实践笔记(三) - Dangjo项目

本文是《python编程从入门到实践》读书实践笔记18~20章的内容,主要是一个基于Django框架的示例demo

18 Django入门

18.1.2 建立虚拟环境

书中是直接用python建立虚拟环境,笔者用的是anaconda,尝试使用anaconda增加虚拟环境。

conda create -n my_django  # 名字可以自己取
# 经过一段时间的新建
conda activate my_django  # 激活新建的环境

当然也可以通过anaconda的UI界面进行操作

18.1.4 安装django

pip install django

18.1.5 新建django项目

先通过命令行新建项目,然后可以看通过VS进行管理

django-admin startproject learning_log .

会在 . 下创建manage.py
会在 . 下创建与项目名learning_log同名的文件夹,文件夹内有:

  • __init__.py:告诉python这个文件夹是一个python包
  • asgi.py:
  • settings.py: Django如何与系统交互以及管理项目,以修改和添加设置
  • urls.py:应创建哪些页面来响应浏览器请求
  • wsgi.py: Web服务器网关接口,帮助Django提供它创建的文件

18.1.6 创建数据库

# 在.下
python manage.py migrate

然后会在.下自动创建一个db.sqlite3文件,用于管理数据库

18.1.7 查看项目

python manage.py runserver

Performing system checks...
System check identified no issues (0 silenced).
December 24, 2021 - 11:07:34
Django version 4.0, using settings 'learning_log.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

会输出类似的结果
此时,可以在网页 访问 http://127.0.0.1:8000/ 来观察初始页面

通过pycharm管理项目

在pycharm中打开刚才的文件夹,文件夹下有一个manage.py和一个learning_log子文件夹

在settings/Interpreter配置好python环境。

此时,可以在pycharm的terminal中,运行

python manage.py runserver

效果和在命令行下运行是一样的。

18.2 创建应用程序

python manage.py startapp demo_app

创建一个demo_app
此时会新建一个同名文件夹,内部有:

  • 子文件夹:migrations
  • 文件:__init__.py admin.py apps.py models.py tests.py views.py

18.2.1 定义模型

在models.py中,可以定义自己的类、方法
目前先沿用书中的代码:

from django.db import models
# Create your models here.
class Topic(models.Model):
    """用户学习的主题"""
    text = models.CharField(max_length=200)
    date_added = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        """返回模型的字符串标示"""
        return self.text

特别的,后续需要阅读以下Django Model field Reference

18.2.2 激活模型

激活模型分3步:

  1. 在settings.py中,添加 'demo_app' 到 INSTALLED_APPS 列表中:
INSTALLED_APPS = [
    # 私人的应用程序
    'demo_app',
    # 系统默认添加的应用程序
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
  1. 通过python manage.py makemigrations demo_app命令,让数据库能存储新模型相关的数据。这个命令会在demo_app的migrations下自动建立py文件
  2. 通过python manage.py migrate命令,更新数据库主文件db.sqlite3

18.2.3 Django管理网站

管理网站是指,新建超级用户,让他可以使用模型来管理网站。

  1. 创建超级用户(管理员)
    超级用户:具备所有权限
    注册用户:阅读网站的公开信息和自己的私有数据
    访客:只允许阅读网站的公开信息
    输入以下命令
python manage.py createsuperuser

之后会有一些管理员信息需要输入

Username (leave blank to use '******'): admin
Email address:
Password:
Password (again):
The password is too similar to the username.
This password is too short. It must contain at least 8 characters.
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.
  1. 向管理网站注册模型
    Django自动在管理网站中添加了一些模型,但是私人创建的模型,需要手工进行注册
    在刚才新建的demo_app文件夹下的admin.py中,增加如下代码
from django.contrib import admin
# Register your models here.
# 以下为新增代码
from .models import Topic  # Topic是之前在models.py中新建的类(即模型)
admin.site.register(Topic)
  1. 添加主题
    通过登录http://127.0.0.1:8000/admin/
    输入账号密码,可以在demo_app标签下,增加标签(之所以可以增加标签,是因为我们在Topic类下定义了text)
  2. 定义模型entry
    本项目是要实现一个学习笔记记录的功能,刚才的Topic下的内容,是每个话题。现在要实现在学习笔记中添加条目,并与Topic中的主题关联。这是一种多对一关系,即多个笔记可以关联同一个Topic。
    尝试在models.py中增加代码:
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 f"{self.text[:50]}..."

然后重复之前的数据库更新操作:

  1. python manage.py makemigrations demo_app命令,让数据库能存储新模型相关的数据。这个命令会在demo_app的migrations下自动建立py文件
  2. python manage.py migrate命令,更新数据库主文件db.sqlite3

并向管理网站注册Entry

from .models import Topic, Entry  # Topic是之前在models.py中新建的类(即模型)
admin.site.register(Topic)
admin.site.register(Entry)

18.2.6 添加一些Entry

可以添加3条Entry并关联topic, 以便后续试验用。

18.2.7 Django Shell

在命令行输入 python manage.py shell 可以进入交互式shell会话
这会话可以在后续编写交互代码时,用来快速验证。
这个shell下有特殊的Django语法,用来访问数据库中的数据,比如:

from demo_app.models import *
topics = Topic.objects.all()
for topic in topics:
    # 打印已存储数据中topic的所有ID和内容
    print(topic.id, topic)    

编写用户可请求的页面时,将使用Django语法。在确认代码能获取所需的数据时,shell很有帮助。如果代码在shell中的行为符合预期,那么它们在项目文件中也符合预期。在shell中排除故障要比在生成页面的文件中排除故障容易得多。虽然不会太多地使用shell,但是可以用它来熟悉对存储在项目中的数据进行方法的Django语法。

18.3 创建页面:学习笔记主页

Django创建页面分为三个阶段:

  1. 定义URL模式
  2. 编写视图
  3. 编写模板

URL模式视图模板的关系:URL模式描述了RUL是如何设计的,让Django系统知道如何将浏览器请求和网站URL匹配,以确定返回哪个页面。每个URL都被映射到特定的视图——视图函数获取并处理页面所需的数据。视图函数通常使用模板来渲染。

18.3.1 映射URL

受限,先在demo_app下简历一个urls.py,用来管理这个app的所有urls。
新建一个urls.py,写入:

from django.urls import path
from . import views

app_name = 'demo_app'
urlpatterns = [
    # path接收3个实参。
    # 第一个是字符串,它用于匹配请求和返回的页面,空值代表基础URL
    # 第二个参数指向要调用view.py中的某个函数(即视图函数,这个index函数还没有编写)
    # 第三个参数将这个URL模式名称命名为index,后续可以用这个名字来调用
    path('', views.index, name='index'),  
    
]

然后,在主工程的urls.py 中添加一行来引用模块demo_app的urls

from django.contrib import admin
from django.urls import path, include  # 新import一个inlcude方法

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('demo_app.urls'))  # 引用demo_app的urls
]

18.3.2 编写视图

视图函数接收请求中的信息系,准备好生成页面所需的数据,再将这些数据发送给浏览器。

在demo_app的views.py中添加代码

# Create your views here.
def index(request):
    """学习笔记的主页"""
    return render(request, 'demo_app/index.html')  # 这个index.html即模板

18.3.3 编写模板

在demo_app 下 新建深层文件夹templates\demo_app
并在demo_app\templates\demo_app下新建index.html

<p>learning log</p>
<p>learning log helps you keep track of your learning.</p>

这个文件夹很深,但是django就是这么规定的- -!
重启服务: python manage.py runserver
这时访问http://127.0.0.1:8000/ 会链接到新写的index.html

小结
在demo_app的urls.py中,指向了视图函数(views.py中的index)。 视图函数(views.py中的index)指向了某个模板(demo_app/index.html)。
把urls.py的内容添加到主工程的urls.py后,即实现了页面的链接。
为什么要这么做

将URL、视图和模板分离,能让我们分别考虑项目的不同方面,在项目很大时,可以让各个参与者专注于最擅长的方面。例如,数据库专家专注于模型、程序员你专注于视图代码,而Web设计人员专注于模板。

18.4 创建其他页面

本节创建两个显示数据的页面,一个列出所有主题,另一个显示特定的主题。每个页面都要制定URL模式、视图函数和模板。

18.4.1 模板继承

父模板
在index.html同级目录下,新建base.html (看不懂,先试试看)

<p>
<a href="{% url 'demo_app:index' %}"> go to: index /a>
</p>

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

子模板
重新index.html,使其集成base.html

{% extends "demo_app/base.html"%}

{% block content %}
<p>learning log helps you keep track of your learning.</p>
{% endblock content %}

18.4.2 显示所有主题的页面

1. URL模式: 修改demo_app/urls.py

app_name = 'demo_app'
urlpatterns = [
    # 主页
    path('', views.index, name='index'),
    # 显示所有的主题
    path('topics/', views.topics, name='topics')
]

2. 视图: 修改demo_app/views.py

from django.shortcuts import render
from .models import Topic

# Create your views here.
def index(request):
    """学习笔记的主页"""
    return render(request, 'demo_app/index.html')

def topics(request):
    """显示所有主题"""
    topics = Topic.objects.order_by('date_added')
    context = {'topics': topics}
    return render(request, 'demo_app/topics.html', context)

3. 模板:新建topics.html

{% extends "demo_app/base.html"%}

{% block content %}
<p>Topics</p>
<ul>
  {% for topic in topics%}
  <li>{{topic}}</li>
  {% empty %}
  <li>No topics have benn added yet.</li>
  {% endfor %}
</ul>
{% endblock content %}

并修改base.html以增加超链接

<p>
<a href="{% url 'demo_app:index' %}"> go to: index</a>
<a href="{% url 'demo_app:topics' %}"> go to: Topics</a>
</p>

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

18.4.3 显示特定主题的页面

1. URL模式: 修改demo_app/urls.py
在原基础上继续修改

urlpatterns = [
    # 主页
    path('', views.index, name='index'),
    # 显示所有的主题
    path('topics/', views.topics, name='topics'),
    # 特定主题的详细页面
    path('topics/<int:topic_id>', views.topic, name='topic')
]

2. 视图: 修改demo_app/views.py
在原基础上继续修改

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, 'demo_app/topics.html', context)

3. 模板:新建topic.html

{% extends "demo_app/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>No entry for this topic yet.</li>
  {% endfor %}
</ul>
{% endblock content %}

4 修改topics.html以增加超链接

{% extends "demo_app/base.html"%}

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

至此,完成了一系列链接。

19 用户账户

这部分暂时忽略,目前的工作不涉及多用户交互

20 设置应用程序的式样并部署

这部分暂时忽略,目前的工作不涉及多用户交互

posted @ 2022-01-06 10:26  坦先生的AI资料室  阅读(154)  评论(0编辑  收藏  举报