Недавно я начал изучать фреймворк Django, и у меня возникли проблемы с проверкой переменных. Когда я пытаюсь вывести переменную field.errors в html-файле, вывода нет, хотя, когда я передаю переменную ошибки из метода создания, он выводит список «ошибок» (т.е. метод clean_number должен работать), и когда я их исправляю, список получает меньше (т.е. метод clean_number не работает). Пожалуйста, скажите мне, что я делаю неправильно. Заранее спасибо.
Файл create.html
<!doctype html>
<html lang = "ru">
<head>
<meta charset = "UTF-8">
<meta name = "viewport>
content = "width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv = "X-UA-Compatible" content = "ie=edge">
<title>Adding a train to the list</title>
<link href = "https://getbootstrap.com/docs/5.3/dist/css/bootstrap.min.css" rel = "stylesheet" integrity = "sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin = "anonymous">
<style>
.sidenav {
height: 100%;
width: 267px;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #f2f2f2;
overflow-x: hidden;
padding-top: 50px;
}
.container {
max-width: 900px;
}
</style>
</head>
<body>
<body class = "bg-light">
<header class = "navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<a class = "navbar-brand col-md-3 col-lg-2 me-0 px-3 fs-6" href = "/">Home page</a>
<button class = "navbar-toggler position-absolute d-md-none collapsed" type = "button" data-bs-toggle = "collapse" data-bs-target = "#sidebarMenu" aria-controls = "sidebarMenu" aria-expanded = "false" aria-label = "Toggle navigation">
<span class = "navbar-toggler-icon"></span>
</button>
<input class = "form-control form-control-dark w-100 rounded-0 border-0" type = "text" placeholder = "Search" aria-label = "Search">
<div class = "navbar-nav">
<div class = "nav-item text-nowrap">
<a class = "nav-link px-3"></a>
</div>
</div>
</header>
<div class = "container">
<main>
<div class = "row g-5">
<div class = "py-5 text-center">
<h2>Add a train</h2>
<p class = "lead">On this page, you need to fill in all the fields and follow the instructions.</p>
<form method = "post">
<div class = "row g-3">
{% csrf_token %}
{% for field in form %}
{{ field }}
<div class = "alert alert-danger">
{{ field.errors }}
{% if !field.errors %}
{{ error }}
{% endif %}
</div>
{% endfor %}
<hr class = "my-4">
<button class = "w-100 btn btn-primary btn-lg" type = "submit">Save changes</button>
</div>
</form>
</div>
</div>
</main>
</div>
</body>
</body>
</html>
Файл Forms.py
from .models import Train
from django.forms import ModelForm, NumberInput
from django.core.exceptions import ValidationError
class TrainForm(ModelForm):
class Meta:
model = Train
fields = ["number", "amount_stops"]
widgets = {
"number": NumberInput(attrs = {
'class': 'form-control',
'placeholder': 'Enter the train number',
}),
"amount_stops": NumberInput(attrs = {
'class': 'form-control',
'placeholder': 'Enter the number of stops'
})
}
def clean_number(self):
number = self.cleaned_data['number']
if number > 100:
raise ValidationError('The number is over 100!')
return number
def clean_amount_stops(self):
amount_stops = self.cleaned_data['amount_stops']
if amount_stops > 100:
raise ValidationError('The amount of stops is over 100!')
return amount_stops
Файл views.py
from django.shortcuts import render, redirect
from .forms import TrainForm
def create(request):
error = ''
if request.method == 'POST':
form = TrainForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
else:
error = form.errors
form = TrainForm()
context = {
'form': form,
'error': error
}
return render(request, 'main/create.html', context)
Сменил шаблон, но все равно ничего не изменилось.
<!doctype html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<meta name = "viewport"
content = "width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv = "X-UA-Compatible" content = "ie=edge">
<title>Document</title>
</head>
<body>
<form method = "post">
{% csrf_token %}
{% for field in form %}
{{ field }}<p>
{{ field.errors }}<p>
{% endfor %}
<button type = "submit">Save</button>
</form>
</body>
</html>
============================
02.10.23: Пробовал пересоздать проект без использования PyCharm IDE, просто с помощью Windows PowerShell, но ничего не изменилось, так как не отображается и не показывает(. Создание моего проекта:
-> cd D:\AppDjango\ - Navigate to Project
-> PS D:\AppDjango> python -m venv virenv
-> PS D:\AppDjango> virenv\Scripts\Activate.ps1
-> (virenv) PS D:\AppDjango> python -m pip install Django
-> (virenv) PS D:\AppDjango> django-admin startproject AppDjango
-> (virenv) PS D:\AppDjango> cd AppDjango
-> (virenv) PS D:\AppDjango\AppDjango> python manage.py runserver
-> (virenv) PS D:\AppDjango\AppDjango> ^C (Ctrl + C) - Finish process
-> (virenv) PS D:\AppDjango\AppDjango> python manage.py startapp MainApp
-> (virenv) PS D:\AppDjango\AppDjango> python manage.py migrate
import os <- Only added
...
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'MainApp' <- Only added
]
...
TEMPLATES = [
{
...
'DIRS': [os.path.join(BASE_DIR,'templates'),], <- Only changed
...
},
]
from django.db import models
class Train(models.Model):
number = models.IntegerField()
amount_stops = models.IntegerField()
def __str__(self):
return str(self.number)
from .models import Train
from django.forms import ModelForm, NumberInput
from django.core.exceptions import ValidationError
class TrainForm(ModelForm):
class Meta:
model = Train
fields = ["number", "amount_stops"]
widgets = {
"number": NumberInput(attrs = {
'class': 'form-control',
'placeholder': 'Enter the train number',
}),
"amount_stops": NumberInput(attrs = {
'class': 'form-control',
'placeholder': 'Enter the number of stops'
})
}
def clean_number(self):
number = self.cleaned_data['number']
if number > 100:
raise ValidationError('The number is over 100!')
return number
def clean_amount_stops(self):
amount_stops = self.cleaned_data['amount_stops']
if amount_stops > 100:
raise ValidationError('The amount of stops is over 100!')
return amount_stops
from django.shortcuts import render, redirect
from .forms import TrainForm
def create(request):
errors_Main = ''
if request.method == 'POST':
form = TrainForm(request.POST)
if form.is_valid():
form.save()
else:
errors_Main = form.errors
form = TrainForm()
context = {
'form': form,
'errors_Main': errors_Main
}
return render(request, 'MainApp/create.html', context)
from django.urls import path
from . import views
urlpatterns = [
path('', views.create, name='create')
]
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('MainApp.urls'))
]
<!doctype html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<meta name = "viewport"
content = "width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv = "X-UA-Compatible" content = "ie=edge">
<title>Document</title>
</head>
<body>
<form method = "post">
{% csrf_token %}
{% for field in form %}
{{ field }}<p>
{% for error in field.errors %} <- added
{{ error }}
{% endfor %}
{% endfor %}
<button type = "submit">Save</button>
</form>
</body>
</html>
-> (virenv) PS D:\AppDjango\AppDjango> python manage.py makemigrations
Migrations for 'MainApp':
MainApp\migrations\0001_initial.py
- Create model Train
-> (virenv) PS D:\AppDjango\AppDjango> python manage.py migrate
Operations to perform:
Apply all migrations: MainApp, admin, auth, contenttypes, sessions
Running migrations:
Applying MainApp.0001_initial... OK
-> (virenv) PS D:\AppDjango\AppDjango> python manage.py runserver
Результат: по-прежнему не отображает ошибки. Подскажите, пожалуйста, на каком этапе я накосячил?
🤔 А знаете ли вы, что...
Python подходит для начинающих программистов благодаря своей простоте и читаемости кода.
Попробуйте использовать циклический синтаксис для отображения ошибок, поэтому вместо только {{field.errors}}
используйте его следующим образом:
{% for error in field.errors %}
{{ error }}
{% endfor %}
Спасибо @Sunderam Dubey за помощь. Я нашел ответ на свой вопрос. Проблема была в методе create, я его переписал немного по другому (код ниже) и смог вывести текст ошибки:
def create(request):
form = TrainForm()
if request.method == "POST":
form = TrainForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
return render(request, "main/create.html", {"form": form})