使用Django开发网络应用程序
Git存储库
我已经将制作的内容上传到Github上,请参考。
https://github.com/sigma7641/nutrient_calculator.git
制作物
我将创建一个能够计算已注册物品的营养成分的Web应用程序。基本上,该应用程序具备以下功能。
-
- ユーザーが栄養価を計算したい食品の情報(名称、カロリー、タンパク質、脂質、炭水化物など)を入力するフォームを提供する。
-
- ユーザーがフォームに情報を入力して「登録」ボタンを押すと、その情報がデータベースに保存される。
-
- ユーザーが保存した食品情報を一覧表示するページを提供する。
- ユーザーが一覧ページから個別の食品情報を選択すると、その食品の栄養価を表示するページを提供する。
以上是基本功能。在实施中,我们将正确使用Django的各种功能(包括表单、视图、模板、模型、数据库等)来实现这些功能。
操作步骤
-
- 创建Django项目
-
- 创建应用程序
-
- 创建数据模型
-
- 连接到数据库
-
- 数据库迁移
-
- 创建表单
-
- 创建视图
-
- 设置URL模式
-
- 创建模板文件
-
- 安装应用程序
-
- 配置模板文件
-
- 配置CSS样式
-
- 设置数据库
- 进行功能测试
我使用相同的步骤进行设置,但可能存在一些低效或错误的部分。
如果感到不自然,建议参考Django官方文档和教程等教材。
同时,如果您能在评论中提出修正意见,我会很高兴。
创建Django项目
首先,创建Django项目。
django-admin startproject nutrient_calculator
在Django中,项目是用于管理多个应用程序的根目录,用于开发Django应用程序。项目提供了Django应用程序的配置、URL路由、数据库连接和静态文件管理等功能。
通常情况下,一个项目由多个应用组成。例如,构建一个网站时,会有博客、论坛、用户认证等功能提供的各个应用程序。这些应用程序被包含在项目中并独立开发,同时共享公共配置。
此外,Django项目还可以作为Web服务器来托管Django应用程序。Django支持WSGI(Web服务器网关接口),通过将项目部署到Web服务器上,可以处理请求并返回响应。
创建应用程序
对于已创建的项目,将创建一个用于计算营养成分的应用程序。
cd nutrient_calculator
python manage.py startapp nutrition
Django中的应用程序是Django应用程序的组成部分,包含Web应用程序的功能和组件。这些应用程序用于将功能在Web应用程序中进行分组,并设计为可以单独开发、测试和维护每个应用程序的功能。
Django的应用程序通常包含视图、模型、模板、静态文件等多种组件,用于执行Web应用程序中的一个功能。应用程序应该根据功能进行分割,并且必须是可独立重用的。
此外,Django应用程序可以具有自己的配置、模板、静态文件、数据库迁移、URL模式等。应用程序可以在Django项目中创建多个应用程序,以构建整个Web应用程序。
创建数据模型
我們將創建一個用於儲存營養素數據的數據模型。該模型能夠儲存營養素的類型、卡路里、蛋白質、脂肪和碳水化合物值。
from django.db import models
class Nutrient(models.Model):
name = models.CharField(max_length=255)
calories = models.IntegerField()
protein = models.IntegerField()
fat = models.IntegerField()
carbohydrate = models.IntegerField()
def __str__(self):
return self.name
class Meta:
app_label = 'nutrition'
在Django中,可以通过Python类来定义数据库表,这被称为“模型”。
模型通过继承Django的models.Model类进行定义。通过定义字段作为属性,并指定字段的数据类型。它被表示为保存在数据库中的表的列。
通过创建模型,可以在数据库中创建表。而且,可以通过模型与数据库进行交互。
连接到数据库
需要进行与DB的连接设置。这次假设DB已准备好。
DATABASES = {
'default': {
'ENGINE': '【自分の設定を入れてください】',
'NAME': '【自分の設定を入れてください】',
'USER': '【自分の設定を入れてください】',
'PASSWORD': '【自分の設定を入れてください】',
'HOST': '【自分の設定を入れてください】',
'PORT': '【自分の設定を入れてください】'
}
}
数据库迁移
需要将创建的数据模型反映到数据库中。这需要在nutrient_calculator目录(包含manage.py文件的目录)中进行操作。
python manage.py makemigrations
python manage.py migrate
在Django中,数据库迁移是指为了修改数据库结构而采取的步骤。例如,当进行模型的添加、删除或字段的修改等操作时,为了将这些变更内容反映到数据库中,就需要进行数据库迁移。
要进行迁移,首先需要生成迁移文件。该文件描述了要进行的更改。生成迁移文件后,可以通过执行迁移将更改应用到数据库中。
可以使用Django的命令行工具生成和执行迁移文件。具体步骤如下:
# マイグレーションファイルの生成
python manage.py makemigrations アプリ名
# マイグレーションの実行
python manage.py migrate アプリ名
如果您省略应用程序名称,将对所有应用程序执行迁移,因此我们这次使用了这个选项。
创建表单
创建一个输入营养素的表单。在表单中放置文本框用于输入每种营养素,并通过点击提交按钮显示计算结果。同时,将卡路里从输入的值中计算出来。
from django import forms
from .models import Nutrient
class NutrientForm(forms.ModelForm):
name = forms.CharField(label='食品名', max_length=255, required=True)
calories = forms.IntegerField(label='カロリー', widget=forms.HiddenInput, required=False)
protein = forms.IntegerField(label='タンパク質', required=True)
fat = forms.IntegerField(label='脂質', required=True)
carbohydrate = forms.IntegerField(label='炭水化物', required=True)
class Meta:
model = Nutrient
fields = ['name', 'calories', 'protein', 'fat', 'carbohydrate']
def clean(self):
cleaned_data = super().clean()
protein = cleaned_data.get('protein')
fat = cleaned_data.get('fat')
carbohydrate = cleaned_data.get('carbohydrate')
if protein is None or fat is None or carbohydrate is None:
raise forms.ValidationError('タンパク質、脂質、炭水化物は必須です。')
else:
calories = protein * 4 + fat * 9 + carbohydrate * 4
cleaned_data['calories'] = calories
return cleaned_data
在Django中,表单是用于接收用户在Web应用程序中输入的信息的工具。表单具有显示表单、验证表单、保存表单等功能。
要创建表单,请在forms.py文件中编写表单的定义。表单的定义使用Django提供的forms模块。
在定义表单时,需要继承ModelForm类,并在Meta类中指定模型和字段。
此外,为了在模板中显示表单,需要在views.py文件中生成表单并传递给模板。
创建视图
我們將創建一個視圖來接收從表單提交的營養素值。
from django.shortcuts import render, get_object_or_404, redirect
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from .models import Nutrient
from .forms import NutrientForm
def index(request):
nutrients = Nutrient.objects.all()
return render(request, 'nutrition/index.html', {'nutrients': nutrients})
def create(request):
if request.method == 'POST':
form = NutrientForm(request.POST or None)
if form.is_valid():
nutrient = Nutrient(
name=form.cleaned_data['name'],
calories=form.cleaned_data['calories'],
protein=form.cleaned_data['protein'],
fat=form.cleaned_data['fat'],
carbohydrate=form.cleaned_data['carbohydrate'],
)
nutrient.save()
return redirect(reverse('nutrition:index'))
else:
form = NutrientForm()
context = {
'form': form
}
return render(request, 'nutrition/form.html', {'form': form})
def detail(request, pk):
nutrient = get_object_or_404(Nutrient, pk=pk)
return render(request, 'nutrition/detail.html', {'nutrient': nutrient})
def update(request, pk):
nutrient = get_object_or_404(Nutrient, pk=pk)
form = NutrientForm(request.POST or None, instance=nutrient)
if form.is_valid():
form.save()
return redirect('nutrition:detail', pk=nutrient.pk)
return render(request, 'nutrition/form.html', {'form': form})
def delete(request, pk):
nutrient = get_object_or_404(Nutrient, pk=pk)
nutrient.delete()
return redirect('nutrition:index')
在Django中,视图是接收HTTP请求并返回相应的函数或方法。视图相当于MVC(模型-视图-控制器)中的视图部分。
使用NutrientForm来处理通过POST方式传送的数据,并创建一个新的Nutrient对象。最后,将重定向到新创建的Nutrient对象的详细页面。另外,如果收到GET请求,则显示一个空的表单。
在`redirect`函数的参数中,指定重定向到`nutrition:index`。这意味着当删除后立即重定向到营养素列表,因为`index`视图是一个列表视图。
在中国,您需要在urls.py文件中设置视图函数以匹配URL模式。
设置URL模式
在Django中,需要设置URL模式来接收URL请求并调用相应的视图函数。通常,我们会将nutrition/urls.py加载到nutrient_calculator/urls.py中,以实现按应用程序分割文件的目的。
from django.contrib import admin
from django.urls import path
from nutrition import views
app_name = 'nutrition'
urlpatterns = [
path('', views.index, name='index'),
path('create/', views.create, name='create'),
path('<int:pk>/', views.detail, name='detail'),
path('<int:pk>/update/', views.update, name='update'),
path('<int:pk>/delete/', views.delete, name='delete'),
]
from django.urls import include, path
urlpatterns = [
path('/', include('nutrition.urls', namespace='nutrition')),
]
创建模板文件
请创建一个用于存放模板文件的目录。请使用nutrient_calculator进行操作。
mkdir templates
基本页面.html
{% load static %}
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="{% static 'style.css' %}">
</head>
<body>
<header class="header">
<h1 class="header">Nutrient Calculator</h1>
<nav class="nav">
<ul>
<li><a href="{% url 'nutrition:index'%}">List</a></li>
<li><a href="{% url 'nutrition:create'%}">Create</a></li>
</ul>
</nav>
</header>
<div class="allWrapper">
<div class="container">
{% block content %}{% endblock %}
</div>
</div>
<footer>
<div class="container">
<p>© 2023 sigma7641. All Rights Reserved.</p>
</div>
<div class="container">
<p class="sentences">
サイト上のコンテンツの無断転載・複製を禁じます。
このサイトに掲載されている全ての文章・画像・音声などの著作物は、著作権法によって保護されています。
当サイトは、リンク先で起こったトラブルについて一切責任を負いません。
</p>
</div>
</footer>
</html>
基础营养.html .html)
我们还会为应用程序创建模板文件。在templates文件夹中实现。
mkdir nutrition
请执行此操作以创建用于营养的目录。
{% extends "base.html" %}
{% load static %}
{% block content %} {% endblock %}
主页.html
{% extends 'nutrition/base_nutrition.html' %}
{% block content %}
<h1>Nutrients</h1>
<table>
<thead>
<tr>
<th>食材名</th>
<th>カロリー</th>
<th>タンパク質</th>
<th>脂質</th>
<th>炭水化物</th>
<th>アクション</th>
</tr>
</thead>
<tbody>
{% for nutrient in nutrients %}
<tr>
<td>{{ nutrient.name }}</td>
<td>{{ nutrient.calories }}</td>
<td>{{ nutrient.protein }}</td>
<td>{{ nutrient.fat }}</td>
<td>{{ nutrient.carbohydrate }}</td>
<td>
<a href="{% url 'nutrition:detail' nutrient.pk %}">Detail</a>
<a href="{% url 'nutrition:update' nutrient.pk %}">Update</a>
<a href="{% url 'nutrition:delete' nutrient.pk %}">Delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
模板文件是包含HTML和CSS等文件的文件,用于渲染从视图中发送的数据并在浏览器中显示。在Django中,模板文件被放置在应用程序的模板目录中。
在这里,我们继承了base_nutrition.html,并用{% block %}标签定义了content区块。然后,我们使用{% for %}标签获取Nutrient模型对象,并在表格的每一行中进行展示。此外,作为每一行的操作,我们创建了到detail视图、update视图和delete视图的链接。{% url %}标签用于使用URL模式的名称创建链接。
创建.html
{% extends 'nutrition/base_nutrition.html' %}
{% block content %}
<h1>Create Nutrient</h1>
<table>
<form method="post">
{% csrf_token %}
{% for field in form %}
<tr>
<th>{{ field.label_tag }}</th>
<td>{{ field }}</td>
</tr>
{% endfor %}
<tr>
<td colspan="2"><button type="submit">Save</button></td>
</tr>
</form>
</table>
{% endblock %}
这是一个继承base_nutrition.html并在content区块中显示表单的模板。form.as_p是一个快速方式,用于以
元素包装并显示表单。另外,{% csrf_token %}用于启用Django的跨站请求伪造保护功能。
详情页面
{% extends 'nutrition/base_nutrition.html' %}
{% block content %}
<h1>Nutrient Detail</h1>
<table>
<tr>
<th>食材名:</th>
<td>{{ nutrient.name }}</td>
</tr>
<tr>
<th>カロリー:</th>
<td>{{ nutrient.calories }}</td>
</tr>
<tr>
<th>タンパク質:</th>
<td>{{ nutrient.protein }}</td>
</tr>
<tr>
<th>炭水化物:</th>
<td>{{ nutrient.carbohydrate }}</td>
</tr>
<tr>
<th>脂質:</th>
<td>{{ nutrient.fat }}</td>
</tr>
</table>
<p><a href="{% url 'nutrition:index' %}">Back to index</a></p>
<p><a href="{% url 'nutrition:update' pk=nutrient.pk %}">Update</a></p>
<form action="{% url 'nutrition:delete' pk=nutrient.pk %}" method="POST">
{% csrf_token %}
<input type="submit" value="Delete">
</form>
{% endblock %}
更新.html
{% extends 'nutrition/base_nutrition.html' %}
{% block content %}
<h1>Update Nutrient</h1>
<table>
<form method="post">
{% csrf_token %}
{% for field in form %}
<tr>
<th>{{ field.label_tag }}</th>
<td>{{ field }}</td>
</tr>
{% endfor %}
<tr>
<td colspan="2"><input type="submit" value="Update"></td>
</tr>
</form>
</table>
{% endblock %}
删除.html
{% extends 'nutrition/base_nutrition.html' %}
{% block content %}
<h2>Delete Nutrient</h2>
<p>Are you sure you want to delete "{{ nutrient.name }}"?</p>
<form method="post">
{% csrf_token %}
<input type="submit" value="Delete">
<a href="{% url 'nutrition:detail' nutrient.pk %}">Cancel</a>
</form>
{% endblock %}
表单.html .html)
{% extends 'nutrition/base_nutrition.html' %}
{% block content %}
<h1>Create Nutrient</h1>
<table class="excel-like">
<form method="post">
{% csrf_token %}
<tr>
<th><label for="{{ form.name.id_for_label }}">食材名</label></th>
<td>{{ form.name }}</td>
</tr>
<tr>
<th><label for="{{ form.protein.id_for_label }}">タンパク質</label></th>
<td>{{ form.protein }}</td>
</tr>
<tr>
<th><label for="{{ form.fat.id_for_label }}">脂質</label></th>
<td>{{ form.fat }}</td>
</tr>
<tr>
<th><label for="{{ form.carbohydrate.id_for_label }}">炭水化物</label></th>
<td>{{ form.carbohydrate }}</td>
</tr>
<tr>
<td colspan="2"><button type="submit" class="btn btn-primary">Save</button></td>
</tr>
</form>
</table>
{% endblock %}
应用程序的安装
将本次应用程序安装到settings.py中。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'nutrition', #この部分を追加
]
放置模板文件
在使用Django模板文件之前,您需要首先在Django项目的settings.py文件中指定保存模板的目录。请追加以下内容。
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Templete
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
os.path.join(BASE_DIR, 'templates', 'nutrition'),
],
'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',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
],
},
}
]
在项目的根目录下创建一个名为”templates”的文件夹,并将模板文件放置其中。
BASE_DIR指的是项目的根目录路径。
这段代码用于获取Python脚本所在目录的父目录。在这个例子中,__file__表示当前文件的路径,其中包含了脚本的文件名。通过将这个路径应用于os.path.abspath函数,将其转换为绝对路径。然后,通过连续应用两次os.path.dirname函数,获取父目录的路径。
CSS的设置
请简单地解决CSS文件的示例。请记录所需内容。
请在nutrition目录下创建static目录并放置。
mkdir static
body {
background-color: lightblue;
color: white;
}
在settings.py中添加以静态方式配置的CSS文件的读取选项。
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'nutrition', 'static'),
]
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
BASE_DIR用来重用template文件夹的变量配置。
STATIC_URL用来指定浏览器访问静态文件的URL。通常设定为/static/。
STATICFILES_DIRS用来指定每个应用程序的静态文件位置。在上述示例中,指定了存放在项目根目录static文件夹内的静态文件。
STATIC_ROOT用来指定静态文件收集目录的路径。通常在项目根目录内创建staticfiles文件夹,并指定该路径。该目录将在执行collectstatic命令时生成。
当设定该变量时,
python manage.py collectstatic
您可以使用命令将静态文件集中到一个位置。这些文件可以在Web服务器上进行提供。
确认行动
python manage.py runserver 0.0.0.0:8000
当您访问 http://localhost:8000/nutrition,您可以使用Web应用程序。
这是在开发服务器上启动Django项目的命令。
当执行此命令时,Django将启动一个监听HTTP请求的Web服务器。0.0.0.0表示服务器接受所有网络接口的连接。8000指定了Web服务器监听的端口号。
执行此命令后,默认情况下会启动Django的开发服务器,并且可以通过http://localhost:8000访问。此外,服务器还可以通过同一网络上的其他计算机访问。