如何使用Python中的Django构建自己的网站

如何使用Python中的Django构建自己的网站

Django是一个基于Python的开源Web框架,它的设计理念是DRY(Don’t Repeat Yourself),即避免重复劳动。Django提供了从URL路由、模板解析到SQL数据库ORM操作等一系列功能,让Web开发变得更加简单、快捷、高效。接下来,我们将一步步介绍如何使用Django来构建自己的网站。

更多Python文章,请阅读:Python 教程

安装Django

首先,我们需要先安装Django。打开终端,输入以下命令:

pip3 install Django

这里我们使用pip3工具来安装Django库,如果你的电脑上还没有安装pip3,可以使用以下命令安装:

sudo apt-get install python3-pip

安装完成后,我们可以验证一下Django是否已经成功安装。打开终端,输入以下命令:

python3 -m django --version

如果返回Django的版本号,说明Django安装成功。

创建一个Django项目

接下来,我们就可以开始使用Django来构建我们的网站了。我们可以使用以下命令来创建一个Django项目:

django-admin startproject mysite

这里我们创建一个名为mysite的项目。执行完该命令后,将会生成如下的目录结构:

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

其中,manage.py是Django的管理脚本,mysite是我们创建的Django项目。

运行Django开发服务器

使用以下命令可以启动Django开发服务器:

python3 manage.py runserver

执行完该命令后,在浏览器中输入 http://127.0.0.1:8000/,将会看到一个Django的欢迎页面。

创建一个Django应用

接下来,我们将创建一个Django应用。在Django中,应用是指一个特定功能的模块。我们可以使用以下命令来创建一个Django应用:

python3 manage.py startapp polls

这里我们创建一个名为polls的应用。执行完该命令后,将会生成如下的目录结构:

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

其中,models.py是用来定义数据模型的地方,views.py是用来处理请求的地方。

编写一个简单的视图

polls/views.py 中,我们可以定义视图函数来处理请求。下面是一个简单的视图函数例子:

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")

配置URL映射

polls/urls.py 文件中,可以定义URL映射关系,将请求路由到相应的视图函数上。例如,我们可以定义一个名为 urls.py 的文件,用于指定 polls 应用的URL模式:

from django.urls import path

from . import views

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

这里我们定义了一个URL模式,将空路由映射到 index 视图函数上。

接着,在 mysite/urls.py 文件中,可以将我们定义的 polls 应用的URL路由到Django的URL解析系统:

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

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

这里我们将 polls 应用的URL路由到了 http://127.0.0.1:8000/polls/ 上。

现在我们可以重新启动Django开发服务器,并尝试访问 http://127.0.0.1:8000/polls/,将会看到我们定义的视图函数的输出。

设计数据模型

polls/models.py 文件中,我们可以定义 PollChoice 数据模型:

from django.db import models

class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    poll = models.ForeignKey(Poll, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

这里我们定义了两个模型,Poll 用来表示投票问题,Choice 用来表示选项。 Choicepoll 属性是一个外键,表示该选项属于哪个投票问题。

同步数据库

在我们定义了数据模型之后,我们需要用Django来同步数据库。我们可以使用以下命令来创建数据库表:

python3 manage.py makemigrations polls

执行完该命令后,我们需要再执行以下命令来应用数据库变更:

python3 manage.py migrate

创建超级用户

接下来,我们需要创建一个超级用户,以便我们可以登录到Django的管理后台。使用以下命令来创建一个超级用户:

python3 manage.py createsuperuser

按照提示输入用户名、电子邮件和密码,超级用户将被创建。

添加管理后台

接下来,我们需要为我们的数据模型添加一个管理员后台。在 polls/admin.py 文件中,我们可以注册 PollChoice 模型:

from django.contrib import admin

from .models import Choice, Poll

admin.site.register(Poll)
admin.site.register(Choice)

现在我们可以重新启动Django开发服务器,然后访问 http://127.0.0.1:8000/admin/,用我们刚才创建的超级用户进行登录。我们就可以在管理员后台中看到我们刚才定义的数据模型。

编写模板

接下来,我们需要编写模板来渲染视图。模板使用Django的模板语言来编写,可以将动态数据渲染到HTML页面中。在 polls/views.py 文件中,我们可以定义视图函数来渲染模板:

from django.shortcuts import render

from .models import Poll

def index(request):
    latest_poll_list = Poll.objects.order_by('-pub_date')[:5]
    context = {'latest_poll_list': latest_poll_list}
    return render(request, 'polls/index.html', context)

polls/templates/polls/ 目录下,我们可以创建一个名为 index.html 的模板,用于显示投票问题列表:

{% if latest_poll_list %}
    <ul>
    {% for poll in latest_poll_list %}
        <li><a href="{% url 'polls:detail' poll.id %}">{{ poll.question }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

这里我们使用Django模板语言来渲染动态数据。 latest_poll_list 是我们从数据库中查询到的最新投票问题数据,我们将其传递给模板中,使用 for 循环语句来遍历数据并显示到HTML页面上。

添加URL参数

我们还可以向URL中添加参数,用于详细显示选定的投票问题。在 polls/urls.py 文件中,我们可以定义一个名为 detail 的URL模式:

from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
    path('<int:pk>/', views.detail, name='detail'),
    # ...
]

这里我们向URL中添加了一个参数 pk,表示要显示的投票问题的ID。

渲染详细页面

polls/views.py 文件中,我们可以定义视图函数来渲染详细页面:

from django.shortcuts import get_object_or_404, render

from .models import Choice, Poll

def detail(request, poll_id):
    poll = get_object_or_404(Poll, pk=poll_id)
    return render(request, 'polls/detail.html', {'poll': poll})

这里我们使用 get_object_or_404() 函数来获取我们要显示的投票问题对象 Poll。如果该对象不存在,则返回404错误。

polls/templates/polls/ 目录下,我们可以创建一个名为 detail.html 的模板,用于详细显示选定的投票问题及其选项:

<h1>{{ poll.question }}</h1>

<ul>
{% for choice in poll.choice_set.all %}
    <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>

<a href="{% url 'polls:index' %}">Back to index</a>

这里我们使用Django模板语言来渲染详细页面。我们首先使用 {{ poll.question }} 来显示投票问题的标题,然后使用 for 循环语句来遍历该投票问题的选项,并将其显示在HTML页面上。

处理表单数据

在Django中,我们可以使用表单来收集用户输入的数据。在 polls/templates/polls/ 目录下,我们可以创建一个名为 vote.html 的模板,用于显示投票表单:

<h1>{{ poll.question }}</h1>

{% if error_message %}
    <p><strong>{{ error_message }}</strong></p>
{% endif %}

<form action="{% url 'polls:vote' poll.id %}" method="post">
{% csrf_token %}
{% for choice in poll.choice_set.all %}
    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" {% if forloop.first %}checked{% endif %}>
    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
<input type="submit" value="Vote">
</form>

这里我们使用Django模板语言来渲染投票表单。我们使用 for 循环语句遍历该投票问题的选项,并将其显示为一组单选框,供用户选择。

polls/views.py 文件中,我们可以定义视图函数来处理用户提交的投票数据:

from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse

from .models import Choice, Poll

def vote(request, poll_id):
    poll = get_object_or_404(Poll, pk=poll_id)
    try:
        selected_choice = poll.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        return render(request, 'polls/detail.html', {
            'poll': poll,
            'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        return HttpResponseRedirect(reverse('polls:results', args=(poll.id,)))

这里我们首先使用 tryexcept 语句来判断用户是否选择了一个选项,如果没有,则返回错误消息并显示投票详细页面。如果用户选择了一个选项,我们则更新该选项的计数器并保存到数据库中,然后将用户重定向到投票结果页面。

显示投票结果

polls/views.py 文件中,我们可以定义视图函数来显示投票结果:

from django.shortcuts import get_object_or_404, render

from .models import Poll

def results(request, poll_id):
    poll = get_object_or_404(Poll, pk=poll_id)
    return render(request, 'polls/results.html', {'poll': poll})

polls/templates/polls/ 目录下,我们可以创建一个名为 results.html 的模板,用于显示投票结果:

<h1>{{ poll.question }}</h1>

<ul>
{% for choice in poll.choice_set.all %}
    <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>

<a href="{% url 'polls:index' %}">Back to index</a>

这里我们使用Django模板语言来渲染投票结果页面。我们首先使用 {{ poll.question }} 来显示投票问题的标题,然后使用 for 循环语句来遍历该投票问题的选项及其投票数,并将其显示在HTML页面上。

测试视图函数

最后,我们需要编写一些测试来测试我们的视图函数。在 polls/tests.py 文件中,我们可以编写以下测试用例:

“`python
import datetime

from django.test import TestCase
from django.utils import timezone
from django.urls import reverse

from .models import Poll

class PollModelTests(TestCase):

def test_was_published_recently_with_future_poll(self):
    """
    was_published_recently() returns False for polls whose pub_date
    is in the future.
    """
    time = timezone.now() + datetime.timedelta(days=30)
    future_poll = Poll(pub_date=time)
    self.assertIs(future_poll.was_published_recently(), False)

def test_was_published_recently_with_old_poll(self):
    """
    was_published_recently() returns False for polls whose pub_date
    is older than 1 day.
    """
    time = timezone.now() - datetime.timedelta(days=1, seconds=1)
    old_poll = Poll(pub_date=time)
    self.assertIs(old_poll.was_published_recently(), False)

def test_was_published_recently_with_recent_poll(self):
    """
    was_published_recently() returns True for polls whose pub_date
    is within the last day.
    """
    time = timezone.now() - datetime.timedelta(hours=23, minutes=59, seconds=59)
    recent_poll = Poll(pub_date=time)
    self.assertIs(recent_poll.was_published_recently(), True)

def create_poll(question, days):
“””
Create a poll with the given question and published the given
number of days offset to now (negative for polls published
in the past, positive for polls that have yet to be published).
“””
time = timezone.now() + datetime.timedelta(days=days)
return Poll.objects.create(question=question, pub_date=time)

class PollIndexViewTests(TestCase):
def test_no_polls(self):
“””
If no polls exist, an appropriate message is displayed.
“””
response = self.client.get(reverse(‘polls:index’))
self.assertEqual(response.status_code, 200)
self.assertContains(response, “No polls are available.”)
self.assertQuerysetEqual(response.context[‘latest_poll_list’], [])

def test_past_polls(self):
    """
    Polls with a pub_date in the past are displayed on the
    index page.
    """
    create_poll(question="Past poll.", days=-30)
    response = self.client.get(reverse('polls:index'))
    self.assertQuerysetEqual(
        response.context['latest_poll_list'],
        ['<Poll: Past poll.>']
    )

def test_future_poll(self):
    """
    Polls with a pub_date in the future aren't displayed on
    the index page.
    """
    create_poll(question="Future poll.", days=30)
    response = self.client.get(reverse('polls:index'))
    self.assertContains(response, "No polls are available.")
    self.assertQuerysetEqual(response.context['latest_poll_list'], [])

def test_future_poll_and_past_poll(self):
    """
    Even if both past and future polls exist, only past polls
    are displayed on the index page.
    """
    create_poll(question="Past poll.", days=-30)
    create_poll(question="Future poll.", days=30)
    response = self.client.get(reverse('polls:index'))
    self.assertQuerysetEqual(
        response.context['latest_poll_list'],
        ['<Poll: Past poll.>']
    )

def test_two_past_polls(self):
    """
    The polls index page may display multiple polls.
    """
    create_poll(question="Past poll 1.", days=-30)
    create_poll(question="Past poll 2.", days=-5)
    response = self.client.get(reverse('polls:index'))
    self.assertQuerysetEqual(
        response.context['latest_poll_list'],
        ['<Poll: Past poll 2.>', '<Poll: Past poll 1.>']
    )

class PollDetailViewTests(TestCase):
def test_future_poll(self):
“””
The detail view of a poll with a pub_date in the future
returns a 404 not found.
“””
future_poll = create_poll(question=’Future poll.’, days=5)
url

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程