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: {{ item.category.title }}
{% 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>
Читать дальше...
</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 %}
Все
{% 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 %}
For displaying custom error messages, you have to disable the default behavior of html5 of required field, you can use novalidate in the form.
You can also show particular field error messages in loop.
Try this code:
add_news.html
<div class="col-md-12">
<h1>Add new</h1>
<form method="POST" novalidate>
{% csrf_token %}
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
{{error|striptags}}
{% endfor %}
{% endif %}
{% for field in form %}
<div class="form-group">
{{ field.label_tag }}
{{field}}
<div class="invalid-feedback">
{% for error in field.errors %}
{{error}}
{% endfor %}
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary btn-block">Add new</button>
</form>
</div>
I have set up my blog so that when a user clicks on the displayed name, it will go to that user's blogs (filtered that so only that person's blogs will show up). I used {{ view.kwargs.username }} to show the person's username, but I'd rather show the first name. What can I change to accomplish this?
blog/templates/blog/user_post.html:
{% extends 'blog/base.html' %}
{% block content %}
<h1 class="mb-3">Posts by {{ view.kwargs.username }} ({{ page_obj.paginator.count }})</h1>
{% for post in posts %}
<article class="media content-section">
<img class="rounded article-img mt-2" src="{{ post.author.profile.image.url }}" alt="">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-posts' post.author.username %}">{{ post.author.profile.user.first_name }} {{ post.author.profile.user.last_name }}</a>
<small class="text-muted">{{ post.date_posted|date:"F d, Y" }}</small>
</div>
<h2><a class="article-title" href="{% url 'post-detail' post.id %}">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content }}</p>
</div>
</article>
{% endfor %}
{% if is_paginated %}
{% if page_obj.has_previous %}
<a class="btn btn-outline-info mb-4" href="?page=1">First</a>
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.previous_page_number }}">Previous</a>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<a class="btn btn-info mb-4" href="?page={{ num }}">{{ num }}</a>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<a class="btn btn-outline-info mb-4" href="?page={{ num }}">{{ num }}</a>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.next_page_number }}">Next</a>
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.paginator.num_pages }}">Last</a>
{% endif %}
{% endif %}
{% endblock content %}
blog/urls.py:
path('user/<str:username>/', UserPostListview.as_view(), name='user-posts'),
blog/views.py:
class UserPostListview(ListView):
model = Post
template_name = 'blog/user_posts.html'
context_object_name = 'posts'
# ordering = ['-date_posted']
paginate_by = 10
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Post.objects.filter(author=user).order_by('-date_posted')
You can use a django templatetags:
In your app, create a directory called templatetags and create a file
myapp/templatetags/mytemplates.py
from django import template
def extractFirstName( username ):
return username.split()[0] # or whatever to return the first name
register = template.Library()
register.filter( 'extractFirstName', extractFirstName )
Then in your html
{% extends 'blog/base.html' %}
{% load mytemplates %}
{% block content %}
<h1 class="mb-3">Posts by {{ view.kwargs.username | extractFirstName }} ...>
<!-- all your other stuff -->
{% endblock %}
I have a ListView page that is working well with pagination. I also have Django filter added to that page for filtering. The problem is pagination is working well but with Django filter it stops working. When the page loads paginate_by is not working. When the pagination is clicked the next page not working.
What am I doing wrong?
views.py
class JobsListView(ListView, FilterView):
# model = JobPost
queryset = JobPost.objects.all()
template_name = 'jobpost_list.html'
paginate_by = 3
# page_kwargs = 'page'
filterset_class = JobPostFilter
def get_queryset(self, *args, **kwargs):
if self.kwargs:
return JobPost.objects.filter(position=self.kwargs['position']).order_by('-created_at')
else:
query = JobPost.objects.all().order_by('-created_at')
return query
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['todays'] = date.today()
context['filter'] = JobPostFilter(self.request.GET, queryset=self.get_queryset())
return context
template
{% extends 'base.html' %}
{% load bootstrap4 %}
{% load fontawesome %}
{% block content %}
{% if messages %}
<div class="alert alert-success alert-dismissible fade show">
{% for m in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ m }}</li>
<button type="button" class="close" data-dismiss="alert" aria-
label="Close">
<span aria-hidden="true">×</span>
</button>
{% endfor %}
</div>
{% endif %}
<div class="col-12">
<h1 class="text-center">Vacancies</h1>
</div>
<div class="row">
<div class="col-4">
<form method="get">
{% bootstrap_form filter.form %}
{% buttons %}
<button class="btn btn-primary" type="submit">Search {% fontawesome_icon
'search' %}</button>
{% endbuttons %}
</form>
</div>
<div class="col-8">
{% for job in filter.qs %}
<div class="joblists">
<h3><a href='{% url "jobpost_detail" job.slug %}'>{{ job.position }} </a> <a
href="{% url 'jobpost_update_form' job.slug %}">{% fontawesome_icon 'edit' %}
</a></h3>
<p>{{ job.description|safe|truncatewords:30 }}</p>
{% if job.location != '' %}
<p>{% fontawesome_icon 'location-arrow' %} <strong>{{ job.location }}
</strong>
</p>
{% endif %}
<p>{{ job.job_type }}</p>
{% if job.deadline != NULL and job.deadline > todays %}
<p>{% fontawesome_icon 'calendar' %} {{ job.deadline|timeuntil }} <small>to
deadline</small></p>
{% endif %}
{% if job.deadline > todays %}
<p>{% fontawesome_icon 'check-circle' color='green' %} Open</p>
{% elif job.deadline < todays %}
<p>{% fontawesome_icon 'times-circle' color='red' %} Closed</p>
{% endif %}
</div>
{% endfor %}
</div>
<div class="pagination">
{% if is_paginated %}
<hr>
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-center pagination-sm">
{% if page_obj.has_previous %}
{% if not search %}
<li class="page-item">
<a class="page-link" href="{% url 'jobpost_list' %}?page={{
page_obj.previous_page_number }}" tabindex="-1">Previous</a>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="{% url 'jobpost_list' %}?{{search}}&page=
{{ page_obj.previous_page_number }}" tabindex="-1">Previous</a>
</li>
{% endif %}
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1">Previous</a>
</li>
{% endif %}
{% for object in page_obj.paginator.page_range %}
<li class="page-item"><a class="page-link" href="{% url 'jobpost_list'
%}?page={{ forloop.counter }}">{{ forloop.counter }}</a></li>
{% endfor %}
{% if page_obj.has_next %}
{% if not search %}
<li class="page-item">
<a class="page-link" href="{% url 'jobpost_list' %}?page={{
page_obj.next_page_number }}">Next</a>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="{% url 'jobpost_list' %}?{{search}}&page=
{{ page_obj.next_page_number }}">Next</a>
</li>
{% endif %}
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#">Next</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
</div>
{% endblock %}
in {% for job in filter.qs %} if you replace filter.qs with 'object_list' it pagination and filtering will work. BUT This won't have any records when the page loads initially without any filter params set in the url.
I am trying to figure out what can be done. Searching....
I am working on library website in which I want to display data from database which is Book name and description. But I'm not able to do that. Here is my code
views.py
from django.shortcuts import render
from .models import *
def index(request):
book_list = Book.objects.all()
return render(request,template_name='index.html', context={'book_list':book_list})
index.html
{% extends "base_generic.html" %}
{% block new_books %}
{% for b in book_list %}
<div class="card">
<img class="card-img-top" src=".." alt="Image">
<div class="card-body">
<h5 class="card-title">{{ book_list }} </h5>
<p class="card-text">Hello this is card text</p>
<a class="btn btn-primary">View this book</a>
</div>
</div>
{% endfor %}
{% endblock %}
You should work with b variable instead of book_list inside of for loop.
If your Book model contains title field, your code might look like this:
{% extends "base_generic.html" %}
{% block new_books %}
{% for b in book_list %}
<div class="card">
<img class="card-img-top" src=".." alt="Image">
<div class="card-body">
<h5 class="card-title">{{ b.title }} </h5>
<p class="card-text">Hello this is card text</p>
<a class="btn btn-primary">View this book</a>
</div>
</div>
{% endfor %}
{% endblock %}
I am trying to make a layout for a bookstore app... I have installed bootstrap through command line and I am trying to load simplex theme.
I am getting this error
TemplateSyntaxError at /store/
'bootstrap_styles' received some positional argument(s) after some keyword argument(s)
Also, when I delete that line of code and try to execute it I get error of {% endblock %}
this..
TemplateSyntaxError at /store/
Invalid block tag: 'endblock'
Here is my base.html
{% extends 'bootstrap3/bootstrap3.html' %}
{% load staticfiles %}
{% load bootstrap3 %}
{% load bootstrap_themes %}
{% bootstrap_styles theme='simplex' type ='min.css' %}
{% block bootstrap3_extra_head %}
<link href = "http://fonts.googleapis.com/css?family=Open+Sans:400,300,700" rel = "stylesheet" type="text/css"/>
<link href = "{% static 'base/css/style.css' %}" rel = "stylesheet" type="text/css"/>
{% endblock %}
{% block bootstrap3_title %}
{%block title %}
Welcome to Pick A Book !!
{%endblock %}
{% endblock %}
{ block bootstrap3_content %}
<nav class = "navbar navbar-inverse navbar-fixed-top">
<div class = "container">
<div class = "navbar-header">
<button type="button" class ="navbar-toggle" data-toggle="collapse" data-target = "#navbar">
<span class = "icon-bar"> </span>
<span class = "icon-bar"> </span>
<span class = "icon-bar"> </span>
</button>
Pick A Book
</div>
<div id = "navbar" class ="collapse navbar-collapse">
<ul class ="nav navbar-nav">
<li class = "hvr=curl-top-right">Home </li>
<li class = "hvr=curl-top-right"> About </li>
<li class = "hvr=curl-top-right">Contact </li>
</ul>
<div class = "navbar-form pull-right">
{% if request.user.is_authenticated %}
Welcome {% if request.user.first_name %}
{{ request.user.first_name }}
{% else %}
{{ request.user.username }}
{% endif %}! Log Out
{% else %}
Welcome, Log In or <a href="{% url 'registration_register' %}" > Register</a>
{% endif %}
</div>
</div>
</div>
</nav>
<div class = "container-fluid">
<img src = "{% static 'base/img/header_full.jpg' %}" class ="bg">
<div class = "parallax">
<div class ="row">
{ % block body %}
<div class = "col-md-8 col-md-offset-2 col-sm-12 maincontent">
Welcome to our Store.
</div>
{%endblock%}
</div>
</div>
</div>
<div class = "row text-center navbar footer">
<div class = "col-md-12">
<p> 2017 Pick A Book. Developed by Kshitij Rangari </p>
</div>
</div>
{%endblock%}
There is a few syntax errors
{% block bootstrap3_title %}
{%block title %} #<<<<<<<<<<<<<<< {% block title %}
Welcome to Pick A Book !!
{%endblock %} #<<<<<<<<<<<<<<<< {% endblock %}
{% endblock %}
{ block bootstrap3_content %} #<<<<<<<<<<<<<<<< missing % after {