使用Django开发网络应用程序

Git存储库

我已经将制作的内容上传到Github上,请参考。

https://github.com/sigma7641/nutrient_calculator.git

制作物

我将创建一个能够计算已注册物品的营养成分的Web应用程序。基本上,该应用程序具备以下功能。

    • ユーザーが栄養価を計算したい食品の情報(名称、カロリー、タンパク質、脂質、炭水化物など)を入力するフォームを提供する。

 

    • ユーザーがフォームに情報を入力して「登録」ボタンを押すと、その情報がデータベースに保存される。

 

    • ユーザーが保存した食品情報を一覧表示するページを提供する。

 

    ユーザーが一覧ページから個別の食品情報を選択すると、その食品の栄養価を表示するページを提供する。

以上是基本功能。在实施中,我们将正确使用Django的各种功能(包括表单、视图、模板、模型、数据库等)来实现这些功能。

操作步骤

    1. 创建Django项目

 

    1. 创建应用程序

 

    1. 创建数据模型

 

    1. 连接到数据库

 

    1. 数据库迁移

 

    1. 创建表单

 

    1. 创建视图

 

    1. 设置URL模式

 

    1. 创建模板文件

 

    1. 安装应用程序

 

    1. 配置模板文件

 

    1. 配置CSS样式

 

    1. 设置数据库

 

    进行功能测试

我使用相同的步骤进行设置,但可能存在一些低效或错误的部分。
如果感到不自然,建议参考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>&copy; 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访问。此外,服务器还可以通过同一网络上的其他计算机访问。

广告
将在 10 秒后关闭
bannerAds