I recently started learning Django and can’t solve one problem. I created my validator for the form, but instead of showing an error window, it just resets the form.
Here is the code models.py:
from django.db import models
from django.urls import reverse_lazy
from django.core.exceptions import ValidationError
class News(models.Model):
title = models.CharField(max_length=150, verbose_name="Title")
content = models.TextField(blank=True, verbose_name="Content")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Date of publication")
updated_at = models.DateTimeField(auto_now=True, verbose_name="Update")
photo = models.ImageField(upload_to='photos/%Y%m/%d/', verbose_name="Photo", blank=True)
is_published = models.BooleanField(default=True, verbose_name="Is_published ")
category = models.ForeignKey('Category', on_delete=models.PROTECT, null=True, verbose_name="Category")
def get_absolute_url(self):
return reverse_lazy('read', kwargs={'news_id' : self.pk})
def __str__(self):
return self.title
class Meta:
verbose_name="new"
verbose_name_plural="news"
ordering = ['-created_at', 'title']
class Category(models.Model):
title = models.CharField(max_length=150, db_index=True, verbose_name="Title of category")
def get_absolute_url(self):
return reverse_lazy('category', kwargs={'pk' : self.pk})
def __str__(self):
return self.title
class Meta:
verbose_name="category"
verbose_name_plural="categories"
ordering = ['-title']
This is the code forms.py:
from django import forms
from .models import News, Category
from django.core.exceptions import ValidationError
import re
class NewsForm(forms.Form):
title = forms.CharField(max_length=150, min_length=1, label="Title", widget=forms.TextInput(attrs={'class' : 'form-control'}))
content = forms.CharField(label="Text", required=False, widget=forms.Textarea(attrs={'class' : 'form-control', 'rows' : 15}))
# photo = forms.ImageField(upload_to='photos/%Y%m/%d/')
is_published = forms.BooleanField(label="To publish", initial=True)
category = forms.ModelChoiceField(label="Category", queryset=Category.objects.all(), empty_label="Select a category", widget=forms.Select(attrs={'class' : 'form-control'}))
def clean_title(self):
raise ValidationError('Error!')
# class NewsForm(forms.ModelForm):
# class Meta:
# model = News
# fields = ['title', 'content', 'is_published', 'category']
# widgets = {
# 'title' : forms.TextInput(attrs={'class' : 'form-control'}),
# 'content' : forms.Textarea(attrs={'class' : 'form-control', 'rows' : 15}),
# 'category' : forms.Select(attrs={'class' : 'form-control'})
# }
And here is the code views.py:
from django.shortcuts import render, get_object_or_404, redirect
from .models import News, Category
from .forms import NewsForm
def news(request):
news = News.objects.all()
return render(request, 'news/news.html', {'news': news, 'title': 'List of news:'})
def get_category(request, pk):
news = News.objects.filter(category_id=pk)
return render(request, 'news/category.html',
{'news': news, 'title': f'List of news in the {str(Category.objects.get(pk=pk))} category :'})
def view_news(request, news_id):
back = request.GET.get('back')
new = get_object_or_404(News, pk=news_id)
return render(request, 'news/read_news.html', {'new' : new, 'back' : back})
def add_news(request):
if request.method == 'POST':
form = NewsForm(request.POST)
if form.is_valid():
new = News.objects.create(**form.cleaned_data)
# new = form.save()
return redirect(str(new.get_absolute_url())+'?back=False')
return render(request, 'news/add_news.html', {'form' : NewsForm() })
Here is the code urls.py:
from django.urls import path
from .views import *
urlpatterns = [
path('news/', news, name="news_all"),
path('news/category/<int:pk>/', get_category, name="category"),
path('news/read/<int:news_id>/', view_news, name="read"),
path('news/add-news/', add_news, name="add"),
]
Code news_tags.py:
from django import template
from ..models import Category
register = template.Library()
@register.simple_tag(name="g_cat")
def get_categories():
return Category.objects.all()
@register.inclusion_tag('news/tags/news_tag.html', name="news_tag")
def news_tag(news, link=False):
return {'news' : news, 'link' : link}
Code news_tag.html:
<div class="col-md-9">
{% for item in news %}
<div class="card mb-3">
<div class="card-header">
{% if link %}
Category: <a href="{{ item.category.get_absolute_url }}">{{ item.category.title }}</a>
{% else %}
Category: {{ item.category.title }}
{% endif %}
</div>
<div class="card-body">
<div>
{% if item.photo %}
<img src="{{ item.photo.url }}" alt="" class="news-media-photo">
{% endif %}
<div class="media-body">
<h5 class="card-title" style="color: {% cycle 'red' 'green' %}">{{ forloop.revcounter }}. {{ item.title }}</h5>
<p class="card-text">{{ item.content|linebreaks|truncatewords:50 }}</p>
<a href="{{ item.get_absolute_url }}" class="btn btn-primary">Читать дальше...</a>
</div>
</div>
</div>
<div class="card-footer text-muted">
{{ item.created_at|timesince }} назад...
</div>
</div>
{% empty %}
<h2>Ooops...</h2>
{% endfor %}
</div>
Here is the code base.html:
<!doctype html>
{% load static %}
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'css/style.css' %}">
<title>{% block title %}News:{% endblock %}</title>
</head>
<body>
{% block navbar %}
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="/">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item"><a class="nav-link" href="{% url 'news_all' %}">Главная</a></li>
<li class="nav-item"><a class="nav-link" href="{% url 'add' %}">Add new</a></li>
</ul>
</div>
</nav>
{% endblock %}
<div class="container mt-3">
<h2>{% block list_title %}News:{% endblock %}</h2>
<div class="row">
{% block sidebar %}
<div class="col-md-3">
{% load news_tags %}
<div class="list-group">
{% g_cat as g_cat %}
<a href="{% url 'news_all' %}" class="list-group-item list-group-item-action">Все</a>
{% for i in g_cat %}
<a href="{{ i.get_absolute_url }}" class="list-group-item list-group-item-action">
{{ i.title }}
</a>
{% endfor %}
</div>
</div>
{% endblock %}
{% block content %}
{% endblock %}
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.6/dist/umd/popper.min.js"
integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut"
crossorigin="anonymous"></script>
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</body>
</html>
Here is the code add_news.html:
{% extends 'base.html' %}
{% block title %}Add new{% endblock %}
{% block list_title %}
<p align="center">{{ new.title }}</p>
{% endblock %}
{% block navbar %}
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="/">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item"><a class="nav-link" href="{% url 'news_all' %}">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#" onclick="history.back();return false;">Cancel</a></li>
</ul>
</div>
</nav>
{% endblock %}
{% block sidebar %}{% endblock %}
{% block content %}
<div class="col-md-12">
<h1>Add new</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
{% comment %}
{{ form.non_field.errors }}
{% for i in form %}
<div class="form-group">
{{ i.label_tag }}
{{ i }}
<div class="invalid-feedback">
{{ i.errors }}
</div>
</div>
{% endfor %}
{{ form.non_field.errors }}
<div class="form-group">
<label for="{{ form.title.id_for_label }}">Title</label>
{{ form.title }}
<div class="invalid-feedback">
{{ form.title.errors }}
</div>
</div>
<div class="form-group">
<label for="{{ form.content.id_for_label }}">Text</label>
{{ form.content }}
<div class="invalid-feedback">
{{ form.content.errors }}
</div>
</div>
<div class="form-group">
<label for="{{ form.is_published.id_for_label }}">To publish</label>
{{ form.is_published }}
<div class="invalid-feedback">
{{ form.is_published.errors }}
</div>
</div>
<div class="form-group">
<label for="{{ form.category.id_for_label }}">Category</label>
{{ form.category }}
<div class="invalid-feedback">
{{ form.category.errors }}
</div>
</div>
{% endcomment %}
<button type="submit" class="btn btn-primary btn-block">Add new</button>
</form>
</div>
{% endblock %}
Code read_news.html:
{% extends 'base.html' %}
{% block title %}Новость - {{ new.title }}{% endblock %}
{% block list_title %}
<p align="center">{{ new.title }}</p>
{% endblock %}
{% block navbar %}
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="/">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item"><a class="nav-link" href="{% url 'news_all' %}">Главная</a></li>
{%if back is None %}
<li class="nav-item"><a class="nav-link" href="#" onclick="history.back();return false;">Back</a></li>
{% elif back == False %}
<li class="nav-item"><a class="nav-link" href="/news/news/">Back</a></li>
{% endif %}
</ul>
</div>
</nav>
{% endblock %}
{% block sidebar %}{% endblock %}
{% block content %}
<div class="col-md-12">
<div class="card mb-3">
<div class="card-header">
Category: {{ new.category.title }}
</div>
<div class="card-body">
<div>
{% if new.photo %}
<img src="{{ new.photo.url }}" alt="" height="250" class="news-media-photo">
{% endif %}
<div class="media-body">
<p class="card-text">{{ new.content|linebreaks }}</p>
</div>
</div>
</div>
<div class="card-footer text-muted">
{{ new.created_at|timesince }} ago...
</div>
</div>
</div>
{% endblock %}
Here is the code news.html:
{% extends 'base.html' %}
{% block title %}{{ title }}{% endblock %}
{% block list_title %}
{{ title }}
{% endblock %}
{% block content %}
{% load news_tags %}
{% news_tag news True %}
{% endblock %}
Here is the code category.html:
{% extends 'base.html' %}
{% block title %}
{{ title }}
{% endblock %}
{% block list_title %}
{{ title }}
{% endblock %}
{% block content %}
{% load news_tags %}
{% news_tag news %}
{% endblock %}