Django项目——简单笔记本V1

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chengqiuming/article/details/84721851

一 代码结构

二 项目配置

1 learning_log/settings.py

# -*- coding: utf-8 -*-

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

SECRET_KEY = 'make_your_own_secret_key'

DEBUG = True

ALLOWED_HOSTS = []

'''
这是一个元组,告诉 Django 项目是由哪些应用程序组成的。
'''
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 通过将应用程序编组,在项目不断增大,包含更多的应用程序时,有助于对应用程序进行跟踪。
    # 这里新建了一个名为 My apps 的片段,当前它只包含应用程序 learning_logs 。
    # 我的应用程序
    'learning_logs',
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
)

ROOT_URLCONF = 'learning_log.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'learning_log.wsgi.application'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

# 中文
LANGUAGE_CODE = 'zh_Hans'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

STATIC_URL = '/static/'

2 learning_log/urls.py

# -*- coding: utf-8 -*-
# 导入了为项目和管理网站管理 URL 的函数和模块
from django.conf.urls import include, url
from django.contrib import admin
# 这个文件的主体定义了变量 urlpatterns
# 变量 urlpatterns 包含项目中的应用程序的 URL
urlpatterns = [
    # 包含模块 admin.site.urls ,该模块定义了可在管理网站中请求的所有 URL 。
    url(r'^admin/', include(admin.site.urls)),
    # 我们添加了一行代码来包含模块 learning_logs.urls 。
    # 这行代码包含实参 namespace ,让我们能够将 learning_logs 的 URL 同项目中的其他 URL 区分开来,
    # 这在项目开始扩展时很有帮助。
    url(r'', include('learning_logs.urls', namespace='learning_logs')),
]

三 后端代码 

1 模型(learning_logs/models.py)

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models

'''
模型就是一个类,包含属性和方法。
'''
'''
用户学习的主题
Model:Django 中一个定义了模型基本功能的类。
属性 text 是一个 CharField,由字符或文本组成的数据.需要存储少量的文本,如名称、标题或城市时,可使用 CharField 。
属性 date_added 是一个 DateTimeField,记录日期和时间的数据
传递了实参 auto_add_now=True ,每当用户创建新主题时,这都让 Django 将这个属性自动设置成当前日期和时间。
字段参考: https://docs.djangoproject.com/en/1.8/ref/models/fields/
'''
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)
    # 默认应使用哪个属性来显示有关主题的信息。
    # 如果你使用的是 Python 2.7 ,应调用方法 __unicode__() ,而不是 __str__()
    def __unicode__(self):
        """Return a string representation of the model."""
        return self.text

"""
学到的有关某个主题的具体知识
"""
class Entry(models.Model):
    '''
    第一个属性 topic 是一个 ForeignKey 实例
    外键是一个数据库术语,它引用了数据库中的另一条记录;这些代码将每个条目关联到特定的主题。
    每个主题创建时,都给它分配了一个键(或 ID )。
    需要在两项数据之间建立联系时, Django 使用与每项信息相关联的键。
    根据这些联系获取与特定主题相关联的所有条目。
    '''
    topic = models.ForeignKey(Topic)
    # 这种字段不需要长度限制,因为我们不限制条目的长度。
    text = models.TextField()
    # 属性 date_added 让我们能够按创建顺序呈现条目,并在每个条目旁边放置时间戳。
    date_added = models.DateTimeField(auto_now_add=True)
    '''
    在 Entry 类中嵌套了 Meta 类。
    Meta 存储用于管理模型的额外信息
    它让我们能够设置一个特殊属性,让 Django 在需要时使用 Entries 来表示多个条目。
    如果没有这个类, Django 将使用 Entrys 来表示多个条目。
    '''
    class Meta:
        verbose_name_plural = 'entries'

    '''
    由于条目包含的文本可能很长,我们让 Django 只显示 text 的前 50 个字符
    我们还添加了一个省略号,指出显示的并非整个条目。
    '''
    def __unicode__(self):
        """ 返回模型的字符串表示 """
        return self.text[:50] + "..."

2 视图(learning_logs/views.py)

# -*- coding: utf-8 -*-
'''
视图函数接受请求中的信息,准备好生成网页所需的数据,再将这些数据发送给浏览器
'''
from django.shortcuts import render
# 导入了与所需数据相关联的模型
from .models import Topic

def index(request):
    """ 学习笔记的主页
    URL 请求与我们刚才定义的模式匹配时, Django 将在文件 views.py 中查找函数 index() ,再将请求对象传递给这个视图函数。
    在这里,我们不需要处理任何数据,因此这个函数只包含调用 render() 的代码。
    这里向函数 render() 提供了两个实参:原始请求对象以及一个可用于创建网页的模板。
    """
    return render(request, 'learning_logs/index.html')

# 函数 topics() 包含一个形参: Django 从服务器那里收到的 request 对象
def topics(request):
    """显示所有主题"""
    # 我们查询数据库 —— 请求提供 Topic 对象,并按属性 date_added 对它们进行排序。
    # 我们将返回的查询集存储在 topics 中。
    topics = Topic.objects.order_by('date_added')
    # 我们定义了一个将要发送给模板的上下文。
    # 上下文是一个字典,其中的键是我们将在模板中用来访问数据的名称,而值是我们要发送给模板的数据。
    # 在这里,只有一个键 — 值对,它包含我们将在网页中显示的一组主题。
    context = {'topics': topics}
    # 创建使用数据的网页时,除对象 request 和模板的路径外,我们还将变量 context 传递给 render()
    return render(request, 'learning_logs/topics.html', context)

'''
这是第一个除 request 对象外还包含另一个形参的视图函数。
这个函数接受正则表达式 (?P<topic_id>\d+) 捕获的值,并将其存储到 topic_id 中。
我们使用 get() 来获取指定的主题
我们获取与该主题相关联的条目,并将它们按 date_added 排序:
date_added 前面的减号指定按降序排列,即先显示最近的条目。
我们将主题和条目都存储在字典 context 中,再将这个字典发送给模板 topic.html。
在自己的项目中编写查询时,先在 Django shell 中进行尝试大有裨益。
相比于编写视图和模板,再在浏览器中检查结果,在 shell 中执行代码可更快地获得反馈。
'''
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, 'learning_logs/topic.html', context)

3 url配置(learning_logs/urls.py)

# -*- coding: utf-8 -*-
"""
定义 learning_logs 的 URL 模式
导入了函数 url ,因为我们需要使用它来将 URL 映射到视图
"""
from django.conf.urls import url
# 句点让 Python 从当前的 urls.py 模块所在的文件夹中导入视图。
from . import views
# 这个文件的主体定义了变量 urlpatterns
# 变量 urlpatterns 是一个列表,包含可在应用程序 learning_logs 中请求的网页
'''
实际的 URL 模式是一个对函数 url() 的调用,这个函数接受三个实参。
第一个是一个正则表达式。 Django 在 urlpatterns 中查找与请求的 URL 字符串匹配的正则表达式,因此正则表达式定义了 Django 可查找的模式。
我们来看看正则表达式 r'^$' 。其中的 r 让 Python 将接下来的字符串视为原始字符串,而引号告诉 Python 正则表达式始于和终于何处。
脱字符( ^ )让 Python 查看字符串的开头,而美元符号让 Python 查看字符串的末尾。
总体而言,这个正则表达式让 Python 查找开头和末尾之间没有任何东西的 URL 。
Python 忽略项目的基础 URL ( http://localhost:8000/ ),因此这个正则表达式与基础 URL 匹配。
其他 URL 都与这个正则表达式不匹配。如果请求的 URL 不与任何 URL 模式匹配, Django 将返回一个错误页面。
url() 的第二个实参指定了要调用的视图函数。请求的 URL 与前述正则表达式匹配时, Django 将调用 views.index.
第三个实参将这个 URL 模式的名称指定为 index ,让我们能够在代码的其他地方引用它。
每当需要提供到这个主页的链接时,我们都将使用这个名称,而不编写 URL 。
'''
urlpatterns = [
    # 主页.
    url(r'^$', views.index, name='index'),
    
    # 显示所有主题.
    url(r'^topics/$', views.topics, name='topics'),
    
    # 特定主题详细页面
    # r 让 Django 将这个字符串视为原始字符串,并指出正则表达式包含在引号内。
    # 这个表达式的第二部分( /(?P<topic_id>\d+)/ )与包含在两个斜杠内的整数匹配,并将这个整数存储在一个名为 topic_id 的实参中。
    # 这部分表达式两边的括号捕获 URL 中的值; ?P<topic_id> 将匹配的值存储到 topic_id 中;
    # 而表达式 \d+ 与包含在两个斜杆内的任何数字都匹配,不管这个数字为多少位。
    #  URL 与这个模式匹配时, Django 将调用视图函数 topic() ,并将存储在 topic_id 中的值作为实参传递给它。
    # 在这个函数中,我们将使用 topic_id 的值来获取相应的主题。
    url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),
]

4 管理(learning_logs/admin.py)

# -*- coding: utf-8 -*-
from django.contrib import admin
# 导入我们要注册的模型
from learning_logs.models import Topic, Entry

# 让 Django 通过管理网站管理我们的模型
admin.site.register(Topic)
admin.site.register(Entry)

四 前端代码

1 learning_logs/templates/learning_logs/base.html

<!--
创建网站时,几乎都有一些所有网页都将包含的元素。
在这种情况下,可编写一个包含通用元素的父模板,并让每个网页都继承这个模板,而不必在每个网页中重复定义这些通用元素。
这种方法能让你专注于开发每个网页的独特方面,还能让修改项目的整体外观容易得多。
这个文件包含所有页面都有的元素;其他的模板都继承 base.html 。
当前,所有页面都包含的元素只有顶端的标题。我们将在每个页面中包含这个模板,因此我们将这个标题设置为到主页的链接:
这个文件的第一部分创建一个包含项目名的段落,该段落也是一个到主页的链接。
为创建链接,我们使用了一个 模板标签 ,它是用大括号和百分号表示的。
模板标签是一小段代码,生成要在网页中显示的信息。
在这个实例中,模板标签 {% url 'learning_logs:index' %} 生成一个 URL ,该 URL 与 learning_logs/urls.py 中定义的名
为 index 的 URL 模式匹配。
在这个示例中, learning_logs 是一个 命名空间 ,而 index 是该命名空间中一个名称独特的 URL 模式。
-->
<p>
  <a href="{% url 'learning_logs:index' %}">学习笔记</a> -
  <a href="{% url 'learning_logs:topics' %}">主题</a>
</p>
<!--
我们插入了一对块标签。这个块名为 content ,是一个占位符,其中包含的信息将由子模板指定。
子模板并非必须定义父模板中的每个块,因此在父模板中,可使用任意多个块来预留空间,而子模板可根据需要定义相应数量的块。
-->
{% block content %}{% endblock %}
<!--
在大型项目中,通常有一个用于整个网站的父模板 ——base.html ,且网站的每个主要部分都有一个父模板。
每个部分的父模板都继承 base.html ,而网站的每个网页都继承相应部分的父模板。
这让你能够轻松地修改整个网站的外观、网站任何一部分的外观以及任何一个网页的外观。
这种配置提供了一种效率极高的工作方式,让你乐意不断地去改进网站。
-->

2 learning_logs/templates/learning_logs/index.html

<!--
可发现我们将标题 Learning Log 替换成了从父模板那里继承的代码。
子模板的第一行必须包含标签extends  ,让Django 知道它继承了哪个父模板。
文件 base.html 位于文件夹 learning_logs 中,因此父模板路径中包含 learning_logs 。
这行代码导入模板 base.html 的所有内容,让 index.html 能够指定要在 content 块预留的空间中添加的内容。
-->
{% extends "learning_logs/base.html" %}
<!--
模板定义了网页的结构。模板指定了网页是什么样的,而每当网页被请求时, Django 将填入相关的数据。模板让你能够访问视图提供的任何数据。
我们的主页视图没有提供任何数据,因此相应的模板非常简单。
创建网页的过程看起来可能很复杂,但将 URL 、视图和模板分离的效果实际上很好。
这让我们能够分别考虑项目的不同方面,且在项目很大时,让各个参与者可专注于其最擅长的方面。
例如,数据库专家可专注于模型,程序员可专注于视图代码,而 Web 设计人员可专注于模板。
们插入了一个名为 content 的 block 标签,以定义 content 块。
不是从父模板继承的内容都包含在 content 块中,在这里是一个描述项目 “ 学习笔记 ” 的段落。
我们使用标签 endblock 指出了内容定义的结束位置。
-->
{% block content %}
  <p>学习笔记,记录你的学习过程!</p>
{% endblock content %}

3 learning_logs/templates/learning_logs/topic.html

<!--
首先使用标签 extends 来继承 base.html
-->
{% extends 'learning_logs/base.html' %}

{% block content %}

  <p>Topic: {{ topic }}</p>

  <p>Entries:</p>
  <ul>
    <!--
    每个项目列表项都将列出两项信息:条目的时间戳和完整的文本。为列出时间戳,我们显示属性 date_added 的值。
    在 Django 模板中,竖线( | )表示模板过滤器 ——对模板变量的值进行修改的函数。
    过滤器 date: 'M d, Y H:i' 以这样的格式显示时间戳: January 1, 2015 23:00 。
    接下来的一行显示 text 的完整值,而不仅仅是 entry 的前50 个字符。
    过滤器 linebreaks 将包含换行符的长条目转换为浏览器能够理解的格式,以免显示为一个不间断的文本块。
    我们使用模板标签 empty 打印一条消息,告诉用户当前主题还没有条目。
    -->
  {% for entry in entries %}
    <li>
      <p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
      <p>{{ entry.text|linebreaks }}</p>
    </li>
  {% empty %}
    <li>
      没有针对该主题的条目。
    </li>
  {% endfor %}
  </ul>

{% endblock content %}

4 learning_logs/templates/learning_logs/topics.html

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

{% block content %}

  <p>主题</p>

  <ul>
    <!--在模板中,每个 for 循环都必须使用 endfor 标签来显式地指出其结束位置。
    我们使用模板标签 url 根据 learning_logs 中名为 topic 的 URL 模式来生成合适的链接。
    这个 URL 模式要求提供实参 topic_id ,因此我们在模板标签 url 中添加了属性 topic.id。
    现在,主题列表中的每个主题都是一个链接,链接到显示相应主题的页面,如 http://localhost:8000/topics/1/ 。
    -->
    {% for topic in topics %}
      <li>
        <a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
      </li>
    <!--模板标签  empty  ,它告诉 Django 在列表 topics 为空时该怎么办-->
    {% empty %}
      <li>还没有添加主题</li>
    {% endfor %}
  </ul>

{% endblock content %}

三 管理界面演示

四 测试演示

猜你喜欢

转载自blog.csdn.net/chengqiuming/article/details/84721851