第一个 Django 应用

在本教程中,我们将逐步创建你的第一个 Django 应用。通过这个过程,你将学习到 Django 的基本概念和如何使用 Django 框架来构建一个简单的 Web 应用。我们将从环境设置开始,逐步深入到模型、视图和模板的使用。

1. Django 简介和特性

Django 是一个高级 Python Web 框架,它鼓励快速开发和干净、实用的设计。Django 遵循 MVT(Model-View-Template)架构,提供了许多内置功能,如用户认证、管理界面、表单处理等。

主要特性:

  • 快速开发:Django 提供了许多内置功能,减少了开发时间。
  • 安全:Django 内置了防止常见的 Web 攻击(如 CSRF、XSS 等)的功能。
  • 可扩展:Django 支持多种数据库,并且可以轻松扩展。
  • 丰富的文档:Django 有详细的官方文档和活跃的社区支持。

2. 安装和环境设置

在开始之前,你需要确保你的系统上已经安装了 Python 和 pip。然后,你可以使用 pip 来安装 Django。

pip install django

安装完成后,你可以通过以下命令验证 Django 是否安装成功:

django-admin --version

3. 项目结构和管理命令

创建项目

使用 django-admin 命令来创建一个新的 Django 项目:

django-admin startproject myfirstproject

这将在当前目录下创建一个名为 myfirstproject 的文件夹,包含以下文件和目录:

myfirstproject/
    manage.py
    myfirstproject/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py

项目结构说明

  • manage.py:一个命令行实用程序,用于与 Django 项目进行交互。
  • myfirstproject/:项目的配置目录。
    • settings.py:项目的配置文件。
    • urls.py:URL 配置文件。
    • asgi.py 和 wsgi.py:用于部署项目的 ASGI 和 WSGI 接口。

运行开发服务器

进入项目目录并运行开发服务器:

cd myfirstproject
python manage.py runserver

打开浏览器并访问 http://127.0.0.1:8000/,你应该会看到 Django 的欢迎页面。

4. MVT (Model-View-Template) 架构

Django 遵循 MVT 架构,这是一种设计模式,用于分离应用程序的不同部分:

  • Model:负责数据存储和业务逻辑。
  • View:处理用户请求并返回响应。
  • Template:负责显示数据。

5. 第一个 Django 应用

创建应用

在 Django 中,项目可以包含多个应用。每个应用负责一个特定的功能。我们可以使用以下命令创建一个新的应用:

python manage.py startapp myfirstapp

这将在项目目录下创建一个名为 myfirstapp 的文件夹,包含以下文件和目录:

myfirstapp/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

注册应用

在 myfirstproject/settings.py 文件中,找到 INSTALLED_APPS 列表,并添加你的应用:

INSTALLED_APPS = [
    ...
    'myfirstapp',
]

定义视图

在 myfirstapp/views.py 文件中,定义一个简单的视图:

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, Django!")

配置 URL

在 myfirstapp 目录下创建一个 urls.py 文件,并添加以下内容:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
]

然后在项目的 urls.py 文件中包含这个应用的 URL 配置:

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

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

运行应用

现在,你可以重新启动开发服务器并访问 http://127.0.0.1:8000/,你应该会看到 "Hello, Django!" 的页面。

6. 模型定义和字段类型

定义模型

在 myfirstapp/models.py 文件中,定义一个简单的模型:

from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.title

创建和应用迁移

在终端中运行以下命令来创建数据库迁移:

python manage.py makemigrations

然后应用迁移:

python manage.py migrate

注册模型到管理界面

在 myfirstapp/admin.py 文件中注册模型:

from django.contrib import admin
from .models import Article

admin.site.register(Article)

创建超级用户

运行以下命令创建一个超级用户:

python manage.py createsuperuser

按照提示输入用户名、邮箱和密码。

访问管理界面

启动开发服务器并访问 http://127.0.0.1:8000/admin/,使用你创建的超级用户登录,你应该能够看到并管理 Article 模型。

7. 数据库迁移

数据库迁移是 Django 管理数据库模式变化的方式。每次你对模型进行更改时,都需要创建并应用迁移。

创建迁移

python manage.py makemigrations

应用迁移

python manage.py migrate

8. 查询集和管理器

查询集

查询集是 Django 从数据库中获取数据的方式。你可以在视图中使用查询集来获取数据。

from .models import Article

def article_list(request):
    articles = Article.objects.all()
    return HttpResponse(articles)

管理器

管理器是 Django 模型用于数据库查询的接口。默认情况下,每个模型都有一个 objects 管理器。

9. 模型关系 (一对多、多对多)

一对多关系

在 models.py 中定义一对多关系:

class Author(models.Model):
    name = models.CharField(max_length=100)

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    pub_date = models.DateTimeField('date published')
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

多对多关系

在 models.py 中定义多对多关系:

class Tag(models.Model):
    name = models.CharField(max_length=50)

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    pub_date = models.DateTimeField('date published')
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    tags = models.ManyToManyField(Tag)

10. 自定义模型方法

你可以在模型中定义自定义方法来封装业务逻辑。例如:

class Article(models.Model):
    ...

    def is_recent(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=7)

11. 函数视图和类视图

函数视图

函数视图是 Django 中最简单的视图形式。例如:

def article_detail(request, article_id):
    article = get_object_or_404(Article, pk=article_id)
    return HttpResponse(article.content)

类视图

类视图提供了更多的灵活性和可重用性。例如:

from django.views import View

class ArticleDetailView(View):
    def get(self, request, article_id):
        article = get_object_or_404(Article, pk=article_id)
        return HttpResponse(article.content)

12. URL 模式和命名

URL 模式

在 urls.py 中定义 URL 模式:

urlpatterns = [
    path('articles/', views.article_list, name='article_list'),
    path('articles/<int:article_id>/', views.article_detail, name='article_detail'),
]

URL 命名

URL 命名允许你在模板和视图中引用 URL 而不用担心路径的变化。例如:

<a href="{% url 'article_detail' article.id %}">Read more</a>

13. 视图参数和请求处理

视图参数

视图可以接受 URL 中的参数。例如:

def article_detail(request, article_id):
    article = get_object_or_404(Article, pk=article_id)
    return HttpResponse(article.content)

请求处理

Django 的请求对象包含了所有关于当前请求的信息。你可以使用它来获取 GET 或 POST 参数。

def search(request):
    query = request.GET.get('q')
    results = Article.objects.filter(title__icontains=query)
    return HttpResponse(results)

14. 通用视图

Django 提供了一些通用视图,可以大大简化常见任务的实现。例如:

from django.views.generic import ListView, DetailView

class ArticleListView(ListView):
    model = Article
    template_name = 'article_list.html'

class ArticleDetailView(DetailView):
    model = Article
    template_name = 'article_detail.html'

15. 中间件

中间件是 Django 处理请求和响应的钩子。你可以在 settings.py 中配置中间件:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

16. 模板语法和标签

模板语法

Django 模板使用 {{ }} 来插入变量,使用 {% %} 来插入逻辑。例如:

<h1>{{ article.title }}</h1>
<p>{{ article.content }}</p>
<p>Published on: {{ article.pub_date }}</p>

模板标签

Django 提供了许多内置模板标签,例如 if、for 等。例如:

{% if article.is_recent %}
    <p>This article is recent.</p>
{% endif %}

17. 模板继承

模板继承允许你创建一个基础模板,并在其他模板中继承它。例如:

<!-- base.html -->
<html>
<head>
    <title>{% block title %}My Site{% endblock %}</title>
</head>
<body>
    <div id="content">
        {% block content %}{% endblock %}
    </div>
</body>
</html>
<!-- article_detail.html -->
{% extends "base.html" %}

{% block title %}{{ article.title }}{% endblock %}

{% block content %}
<h1>{{ article.title }}</h1>
<p>{{ article.content }}</p>
{% endblock %}

18. 上下文处理器

上下文处理器允许你在所有模板中添加变量。例如:

# context_processors.py
def site_info(request):
    return {'site_name': 'My Django Site'}

在 settings.py 中配置上下文处理器:

TEMPLATES = [
    {
        ...
        'OPTIONS': {
            'context_processors': [
                ...
                'myfirstapp.context_processors.site_info',
            ],
        },
    },
]

19. 自定义模板标签和过滤器

自定义模板标签

在 myfirstapp 目录下创建一个 templatetags 目录,并在其中创建一个 custom_tags.py 文件:

from django import template

register = template.Library()

@register.simple_tag
def current_time(format_string):
    return datetime.datetime.now().strftime(format_string)

在模板中使用自定义标签:

{% load custom_tags %}
<p>Current time: {% current_time "%Y-%m-%d %H:%M" %}</p>

自定义过滤器

在 custom_tags.py 中定义一个自定义过滤器:

@register.filter
def lower(value):
    return value.lower()

在模板中使用自定义过滤器:

<p>{{ article.title|lower }}</p>

20. 静态文件处理

配置静态文件

在 settings.py 中配置静态文件:

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

使用静态文件

在模板中使用静态文件:

{% load static %}
<img src="{% static 'images/logo.png' %}" alt="Logo">

21. Django Form 类

创建表单

在 myfirstapp 目录下创建一个 forms.py 文件:

from django import forms

class ArticleForm(forms.Form):
    title = forms.CharField(max_length=200)
    content = forms.CharField(widget=forms.Textarea)

在视图中使用表单

在视图中使用表单:

from django.shortcuts import render
from .forms import ArticleForm

def create_article(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            # 处理表单数据
            pass
    else:
        form = ArticleForm()
    return render(request, 'create_article.html', {'form': form})

在模板中渲染表单

在模板中渲染表单:

<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Submit</button>
</form>

22. 表单验证

Django 表单提供了内置的验证功能。例如:

class ArticleForm(forms.Form):
    title = forms.CharField(max_length=200)
    content = forms.CharField(widget=forms.Textarea)

    def clean_title(self):
        title = self.cleaned_data['title']
        if len(title) < 5:
            raise forms.ValidationError("Title must be at least 5 characters long.")
        return title

23. ModelForm

ModelForm 是 Django 提供的一个便捷类,用于直接从模型生成表单。例如:

from django.forms import ModelForm
from .models import Article

class ArticleForm(ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'content']

24. 表单集 (Formsets)

表单集允许你在一个页面上处理多个表单。例如:

from django.forms import formset_factory
from .forms import ArticleForm

ArticleFormSet = formset_factory(ArticleForm,