django create form with materialize modal - django

As far as I tried, I cannot get the form data or send it to the django view function through the materialize css modal. I'm just a novice in js, ajax and related.
The "CreateView" action for my form is running outside, but it is required to be inside a modal and still get the benefits of using django form validation, security, and so on. I'm using Django version 1.11.
The project has two applications: main that loads the main page, and library that performs actions on book objects. A book has only a title, and so there's a form defined like:
library/forms.py:
from django import forms
from .models import Book
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = [
'title',
]
the project urls definition, mysite/urls.py :
from django.conf.urls import url, include
from django.contrib import admin
from main import views as main_views
urlpatterns = [
url(r'^$', main_views.home, name='home'),
url(r'^books/', include('library.urls')),
url(r'^admin/', admin.site.urls),
]
Home view, main/views.py:
from django.shortcuts import render
def home(request):
return render(request, 'main/home.html')
main/templates/main/home.html:
<html>
<head>
<title>A library</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/css/materialize.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body>
{% block body %}
<div class="container">
<!--a class="waves-effect waves-light btn modal-trigger" href="#modal1">Create Book</a-->
<a class="waves-effect waves-light btn modal-trigger" data-target="add_book_modal" href="{% url 'books:create' %}">
Create Book
</a>
<div class="divider"></div>
<div class="section">
<h5>Section 1</h5>
<p>Stuff</p>
</div>
</div>
{% endblock %}
{% include 'library/book_form.html' %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
<script>
$( document ).ready(function() {
$('.modal').modal();
});
</script>
</body>
</html>
The library's urls, library/urls.py:
from django.conf.urls import url
from .views import BookCreateView
app_name='books'
urlpatterns = [
url(r'^create/$', BookCreateView.as_view(), name='create'),
]
library/views.py:
from django.shortcuts import render
from django.views.generic import CreateView
from django.urls import reverse_lazy
from .models import Book
from .forms import BookForm
class BookCreateView(CreateView):
form_class = BookForm
template_name = 'library/book_form.html'
success_url = reverse_lazy('home')
library/templates/library/book_form.html:
<div id="add_book_modal" class="modal">
<div class="modal-content">
{% block body %}
<main>
<h5>Add book information</h5>
{% if form.errors.non_field_errors %}
{{ form.errors.non_field_errors }}
{% endif %}
<form method="POST">
{% csrf_token %}
{{ form.non_field_errors }}
{{ form.source.errors }}
{{ form.source }}
<!--Form content-->
{{form.as_p}}
<!--Form button-->
<button class="btn waves-effect waves-light" type="submit" name="action">Submit
</button>
</form>
</main>
{% endblock %}
</div>
</div>
Any help will be appreciated.

Changing a href link and setting the place of html code where the content will be rendered
main/templates/main/home.html:
...
<a class="waves-effect waves-light btn modal-trigger" href="#modal1">Create Book</a>
...
<!-- Modal Structure -->
<div id="modal1" class="modal">
<div class="modal-content">
<!--Form content goes in here.-->
</div>
</div>
{% endblock %}
<!-- django include tag removed -->
Jquery to render the form in the modal through django's routes
main/templates/main/home.html:
<script>
$( document ).ready(function() {
$('.modal').modal();
$('.modal-content').load("{% url 'books:create' %}");
});
</script>
Finally, book form specifying the way back.
_library/templates/library/book_form.html_:
<h5>Add book information</h5>
{% if form.errors.non_field_errors %}
{{ form.errors.non_field_errors }}
{% endif %}
<form method="POST" action="{% url 'books:create' %}">
{% csrf_token %}
{{ form.non_field_errors }}
{{ form.source.errors }}
{{ form.source }}
<!--Form content-->
{{form.as_p}}
<!--Form button-->
<button class="btn waves-effect waves-light" type="submit" name="action">Submit form
</button>
</form>

Related

Django- Template not found

I can't seem to get my delete, edit and add review functionality working. The errors come as soon as I try to navigate to the urls I have set up. When I try and add a new review using my link on the reviews page I get the below message:
TemplateDoesNotExist at /reviews/add
I don't understand why because I have linked the url above to the template, which I have created.
The issue I have with my edit/delete views is that the url it searches for when I click the button is just /edit/ or /delete/ rather than reviews/edit/int:pk or reviews/delete/int:pk as per my urls.
I have pasted my code below, any help would be much appreciated! I have the feeling I am going to kick myself when I realise!
reviews.html:
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="container-fluid home-container">
<div class="row align-items-center">
<div class="col-sm-12 text-center mt-4">
<h2><strong>Reviews</strong></h2>
</div>
</div>
{% for review in reviews %}
<hr class="hr-1">
<div class="row featurette">
<div class="col-sm-12">
<h2 class="featurette-heading">{{ review.title }}</h2>
<p class="lead">{{ review.content }}</p>
<div class="row justify-content-between mx-1">
<p>By: {{ review.user }}</p>
<p>Created on: {{ review.created }}</p>
<p>Last Updated: {{ review.updated }}</p>
</div>
<!-- Add user authentication if -->
<div class="text-center">
<a href="edit/{{ review.id }}" class="mx-2">
<button class="positive-button mb-2">Edit</button></a>
<a href="delete/{{ review.id }}" class="mx-2 mb-2">
<button class="negative-button">Delete</button></a>
</div>
</div>
</div>
{% endfor %}
<div class="row">
<div class="col-sm-12 text-center py-4">
{% if user.is_authenticated %}
<a href="{% url 'home:add_review' %}">
<button class="positive-button-lg">Add a review</button>
</a>
{% else %}
<p>If you would like to add your own review, please login or sign up if you haven't already!</p>
{% endif %}
</div>
</div>
</div>
{% endblock %}
add_review.html:
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-auto text-center p-3">
<form method="post" style="margin-top: 1.3em;">
{{ review_form }}
{% csrf_token %}
<button type="submit" class="btn btn-primary btn-lg">Submit</button>
</form>
</div>
</div>
{% endblock %}
views.py:
from django.shortcuts import render
from django.views import View
from django.urls import reverse_lazy
from django.views.generic import UpdateView, DeleteView
from .models import Reviews
from .forms import ReviewForm
def home(request):
''' Returns the home page.'''
return render(request, 'home/index.html')
def reviews(request):
''' Returns the reviews page.'''
serialized_reviews = []
reviews = Reviews.objects.all()
for review in reviews:
serialized_reviews.append({
"title": review.title,
"content": review.content,
"user": review.user,
"created": review.created,
"updated": review.updated,
})
context = {
"reviews": serialized_reviews
}
print(serialized_reviews)
return render(request, 'home/reviews.html', context)
class AddReview(View):
'''View which allows the user to add a new review.'''
def get(self, request, *args, **kwargs):
review = Reviews
review_form = ReviewForm
context = {
'review': review,
'review_form': review_form,
'user': review.user,
'title': review.title,
'content': review.content,
}
return render(request, 'add_review.html', context)
def post(self, request, *args, **kwargs):
review_form = ReviewForm(data=request.POST)
if review_form.is_valid():
obj = review_form.save(commit=False)
obj.user = request.user
obj.save()
return redirect("home:reviews")
class DeleteReview(DeleteView):
'''View which allows the user to delete the selected review.'''
model = Reviews
template_name = 'delete_review.html'
success_url = reverse_lazy('reviews')
class EditReview(UpdateView):
'''View which allows the user to edit the selected review.'''
model = Reviews
template_name = 'edit_review.html'
fields = ['title', 'content']
urls.py:
from django.urls import path
from . import views
app_name = 'home'
urlpatterns = [
path('', views.home, name='home'),
path('reviews', views.reviews, name='reviews'),
path('reviews/add', views.AddReview.as_view(), name='add_review'),
path('reviews/delete/<int:pk>', views.DeleteReview.as_view(), name='delete_review'),
path('reviews/edit/<int:pk>', views.EditReview.as_view(), name='edit_review'),
]
The main difference is my app name, which is 'core'. Also, I forgot to add the content field to the model, but that is easily done, the form will just handle it as soon as you do the migration. (except on list.html)
models.py
from django.db import models
from django.contrib.auth import get_user_model
from django.utils import timezone
class Reviews(models.Model):
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
title = models.CharField(max_length=128)
created_at = models.DateTimeField(auto_now_add=timezone.now())
updated_at = models.DateTimeField(auto_now=timezone.now())
forms.py
from django import forms
from core.models import Reviews
class ReviewsForm(forms.ModelForm):
class Meta:
model = Reviews
fields = '__all__'
views.py
from core.models import Reviews
from core.forms import ReviewsForm
from django.shortcuts import render, redirect
def list_reviews(request):
reviews = Reviews.objects.all()
context = {
"reviews": reviews
}
return render(request, 'reviews/list.html', context)
def add_review(request):
if request.method == 'POST':
form = ReviewsForm(request.POST)
if form.is_valid():
form.save()
return redirect('/reviews/')
else:
form = ReviewsForm()
context = {
'form': form
}
return render(request, 'reviews/detail.html', context)
def edit_review(request, pk):
if request.method == 'POST':
form = ReviewsForm(request.POST)
if form.is_valid():
obj = Reviews.objects.get(id=pk)
obj.title = form.cleaned_data['title']
obj.user = form.cleaned_data['user']
obj.save()
return redirect('/reviews/')
else:
obj = Reviews.objects.get(id=pk)
form = ReviewsForm(instance=obj)
context = {
'form': form
}
return render(request, 'reviews/detail.html', context)
def delete_review(request, pk):
obj = Reviews.objects.get(id=pk)
obj.delete()
return redirect('/reviews/')
urls.py
from django.urls import path
import core.views as views
app_name = 'core'
urlpatterns = [
path('reviews/', views.list_reviews, name='list-reviews'),
path('reviews/add', views.add_review, name='add-review'),
path('reviews/edit/<int:pk>/', views.edit_review, name='edit-review'),
path('reviews/delete/<int:pk>/', views.delete_review, name='delete-review'),
]
list.html
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="container-fluid home-container">
<div class="row align-items-center">
<div class="col-sm-12 text-center mt-4">
<h2><strong>Reviews</strong></h2>
</div>
</div>
{% for review in reviews %}
<hr class="hr-1">
<div class="row featurette">
<div class="col-sm-12">
<h2 class="featurette-heading">{{ review.title }}</h2>
<p class="lead">{{ review.content }}</p>
<div class="row justify-content-between mx-1">
<p>By: {{ review.user }}</p>
<p>Created on: {{ review.created_at }}</p>
<p>Last Updated: {{ review.updated_at }}</p>
</div>
<!-- Add user authentication if -->
<div class="text-center">
<a href="{% url 'core:edit-review' pk=review.id %}" class="mx-2">
<button class="positive-button mb-2">Edit</button></a>
<a href="{% url 'core:delete-review' pk=review.id %}" class="mx-2 mb-2">
<button class="negative-button">Delete</button></a>
</div>
</div>
</div>
{% endfor %}
<div class="row">
<div class="col-sm-12 text-center py-4">
{% if user.is_authenticated %}
<a href="{% url 'core:add-review' %}">
<button class="positive-button-lg">Add a review</button>
</a>
{% else %}
<p>If you would like to add your own review, please login or sign up if you haven't already!</p>
{% endif %}
</div>
</div>
</div>
{% endblock %}
detail.html
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-auto text-center p-3">
<form method="post" style="margin-top: 1.3em;">
{% csrf_token %}
<table>
{{ form }}
</table>
<button type="submit" class="btn btn-primary btn-lg">Save</button>
</form>
</div>
</div>
{% endblock %}
According to your urls, It is a review/edit/<int:pk>.
So you must add same thing in href tag.
Change this:
<a href="edit/{{ review.id }}"
To this:
<a href="review/edit/{{ review.id }}"
That's why you are getting that error
I've fixed it, firstly the path in my add_review view was wrong, which I have amended and it now works (thanks Ivan).
I also was not actually bringing the ID through on my 'reviews' view in the first place, so when following the links on my edit and review buttons, it didn't know what I meant by 'id', as I hadn't specified what that was in the view context.
Thanks for the help all!
I think you're writing in your urls the wrong way, like this below your div text-center:
<a href="edit/{{ review.id }}" class="mx-2">
It should be:
<a href="{% url 'yourappname:edit' review.id %}">

NoReverseMatch: Reverse for 'about' not found. 'about' is not a valid view function or pattern name

I am building blog in django and stuck because of this error.
When I click on Readmore button to load full blog post. this error appears.
it should load the page which diplay blog post with detail it showed this error to me.
i tried different solutions which are available on internet but didn't get rid of this error.
Here is my code!
project url.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('Blog_App.urls')),
]
app urls
from django.urls import path
from . import views
urlpatterns = [
path('', views.PostList.as_view(), name= 'home'),
path('user/<str:username>/', views.UserPostList.as_view(), name= 'user-posts'),
path('<slug:slug>', views.PostDetail.as_view(), name= 'post_detail'),
path('register/', views.Register, name= 'Registration'),
path('login/', views.Login, name= 'Login'),
path('logout/', views.logout_view, name= 'Logout'),
]
views.py
from django.db import models
from .forms import NewUserForm
from django.shortcuts import get_object_or_404, redirect, render
from django.http import HttpResponse
from django.contrib.auth import login,logout, authenticate
from django.contrib import messages
from django.contrib.auth.forms import AuthenticationForm
from django.views import generic
from .models import STATUS, Post
from django.contrib.auth.models import User
class PostList(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'Blog_App/index.html'
class UserPostList(generic.ListView):
model = Post
template_name = 'Blog_App/user_posts.html'
context_object_name = 'posts'
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Post.objects.filter(author=user).order_by('-created_on')
class PostDetail(generic.DetailView):
model = Post
template_name = 'Blog_App/post_detail.html'
def Register(request):
if request.method == 'POST':
form = NewUserForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
messages.success(request, 'Registration succesfull')
return redirect('home')
messages.error(request, 'Invalid Information')
form = NewUserForm()
context = {'register_form': form}
return render(request, 'Blog_App/register.html', context )
def Login(request):
if request.method == 'POST':
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
messages.info(request, 'Congrats. You logged In! ')
return redirect('home')
else:
messages.error(request, 'Incorrect Credentials!')
else:
messages.error(request, 'Invalid Information')
form = AuthenticationForm()
return render(request, 'Blog_App/login.html', context={'login_form': form})
def logout_view(request):
logout(request)
messages.info(request, 'You are succesfully Logged out')
return redirect('home')
Base.html
<!DOCTYPE html>
<html lang="en">
{% load static %}
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Blog-App</title>
<link rel="stylesheet" href="{% static 'css/style.css' %}">
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
</head>
<body>
<div class="nav-container">
<nav class="test">
<div class="nav-wrapper">
<a href="#" data-target="mobile-demo" class="sidenav-trigger"><i class="material-
icons">menu</i></a>
<ul id="nav-mobile" class="hide-on-med-and-down">
<li>Home</li>
<li>About </li>
<li>Contact Us</li>
<ul id="nav-mobile" class="right hide-on-med-and-down">
{% if user.is_authenticated %}
<li>Logout</li>
<li>{{user.username}}</li>
{% else %}
<li>Login</li>
<li>Register</li>
{% endif %}
</ul>
<div>
</nav>
</div>
{% block content %}
{% endblock content %}
<footer class="page-footer" >
<div class="container">
<div class="row">
<div class="col l6 s12">
<h5 class="white-text">Footer Content</h5>
<p class="grey-text text-lighten-4">You can use rows and columns here to organize your
footer content.</p>
</div>
<div class="col l4 offset-l2 s12">
<h5 class="white-text">Links</h5>
<ul>
<li><a class="grey-text text-lighten-3" href="#!">Link 1</a></li>
<li><a class="grey-text text-lighten-3" href="#!">Link 2</a></li>
<li><a class="grey-text text-lighten-3" href="#!">Link 3</a></li>
<li><a class="grey-text text-lighten-3" href="#!">Link 4</a></li>
</ul>
</div>
</div>
</div>
<div class="footer-copyright">
<div class="container">
© 2014 Copyright Text
<a class="grey-text text-lighten-4 right" href="#!">More Links</a>
</div>
</div>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js">
</script>
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
{% if messages %}
{% for msg in messages %}
<script>
swal({
"text": "{{msg}}",
});
</script>
{% endfor %}
{% endif %}
</body>
</html>
index.html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="Blog-posts">
<div class="row">
<div class="div-1">
<div class="col s12 m6 ">
{% for post in post_list %}
<div class="card card-list blue-grey darken-1">
<div class="card-content white-text">
<div class="author">
<a href="{% url 'user-posts' post.author.username %}">
<h5 class="author-name"><img class="author-img" src="{% static
'images/profile.jpg' %}" alt="" height="40px" width="40px">
{{post.author}}</h5>
</a>
<small class="post-created_on">{{post.created_on}}</small>
</div>
<span class="card-title">{{post.title}}</span>
<p>{{post.content|slice:"200"}}</p>
</div>
<div class="Readmore-btn">
<a href="{% url 'post_detail' post.slug %}" class="waves-effect waves-
light btn-small">Read More</a></div>
</div>
{% endfor %}
</div>
</div>
<div class="div-2">
<div class="col m5">
<div class="card card-sidebar">
<div class="card-content black-text">
<span class="card-title">About Us</span>
<p>I am a very simple card. I am good at containing small bits of
information.
I am convenient because I require little markup to use effectively.</p>
</div>
<div class="card-action">
<div class="Readmore-btn_about"><a href="#" class="waves-effect waves-
light btn-small">Read More</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
If you are facing same kind of issue. so here how i get rid of this.
Django giving me error of some kind of {% url 'about' %} pattern in base.html.
But it actually exist in another html file which called as post_detail.html.
So if you are facing same kind of error check for other files as well you will find an error in other html file.
Thanks

Django messages not showing up on redirects, only render

For a couple days now, I've been trying to figure out why my messages don't show up on redirects. All of the dependencies are there in my settings.py file as you can see. I don't think that's the problem because I am getting two messages to show up on signup and login if the user's passwords don't match on signup or if the user enters the wrong password on login. I notice it only works on renders, but not on redirects. I'll post an image of my file structure and also the relevant files next.
File structure images:
settings.py
from django.contrib.messages import constants as messages
MESSAGE_TAGS = {
messages.DEBUG: 'alert-info',
messages.INFO: 'alert-info',
messages.SUCCESS: 'alert-success',
messages.WARNING: 'alert-warning',
messages.ERROR: 'alert-danger',
}
INSTALLED_APPS = [
...
'django.contrib.messages',
...
]
MIDDLEWARE = [
...
'django.contrib.sessions.middleware.SessionMiddleware',
...
'django.contrib.messages.middleware.MessageMiddleware',
...
]
TEMPLATES = [
...
'context_processors': [
...
'django.contrib.messages.context_processors.messages',
],
},
},
]
My urls.py in the main virtual_library folder
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from book.views import *
urlpatterns = [
path('admin/', admin.site.urls),
# Book paths
path('', include('book.urls')),
# Added Django authentication system after adding members app
path('members/', include('django.contrib.auth.urls')),
path('members/', include('members.urls')),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
My urls.py in the book folder
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from .views import *
from book import views
urlpatterns = [
# Default path
path('', views.home, name='home'),
# Book paths
path('create/', views.createbook, name='createbook'),
path('current/', views.currentbooks, name='currentbooks'),
path('wanttoread/', views.wanttoreadbooks, name='wanttoreadbooks'),
path('currentlyreading/', views.currentlyreading, name='currentlyreading'),
path('read/', views.read, name='read'),
path('book/<int:book_pk>', views.viewbook, name='viewbook'),
path('book/<int:book_pk>/editbook', views.editbook, name='editbook'),
path('book/<int:book_pk>/viewonly', views.viewonly, name='viewonly'),
path('book/<int:book_pk>/delete', views.deletebook, name='deletebook'),
# Genres
path('genre/', AddGenreView.as_view(), name='addgenre'),
]
My urls.py in the members folder
from django.contrib import admin
from django.urls import path
from django.conf import settings
from django.contrib.auth import views as auth_views
from django.conf.urls.static import static
from members import views
from . import views
from .views import UserEditView, CreateProfilePageView, ShowProfilePageView, EditProfilePageView, PasswordsChangeView
urlpatterns = [
# User auth
path('signupuser/', views.signupuser, name='signupuser'),
path('loginuser/', views.loginuser, name='loginuser'),
path('logoutuser/', views.logoutuser, name='logoutuser'),
# User settings
path('edit_settings/', UserEditView.as_view(), name='edit_settings'),
# path('password/', auth_views.PasswordChangeView.as_view(template_name='registration/change_password.html')),
path('password/', PasswordsChangeView.as_view(template_name='registration/change_password.html')),
path('password_success/', views.password_success, name="password_success"),
# User profile
path('create_profile_page/', CreateProfilePageView.as_view(), name='create_profile_page'),
path('<int:pk>/edit_profile_page/', EditProfilePageView.as_view(), name='edit_profile_page'),
path('<int:pk>/profile/', ShowProfilePageView.as_view(), name='show_profile_page'),
]
base.html in the book folder
<div class="container mt-5">
{% for message in messages %}
<div class="container-fluid p-0">
<div class="alert {{ message.tags }} alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button> {{ message }}
</div>
</div>
{% endfor %} {% block content %}{% endblock %}
</div>
my currentbooks.html template to view user's books in the book folder
{% extends "book/base.html" %} {% load static %} { % block title % } Your Books { % endblock % } {% block content %}
<div class="row justify-content-center mt-5">
<div class="col-md-10">
<h1>{% if book_list %} {{ book_list.count }} total book{{ book_list.count|pluralize }} in your Mibrary...</h1>
</div>
</div>
<div class="row justify-content-center mt-5">
<div class="col-md-10">
{% if page_obj %}
<div class="container mt-1">
{% for book in page_obj %}
<div class="card-body">
{% if book.book_img %}
<img src="{{ book.book_img.url }}" alt="{{ book.title }}" class="img-fluid" style="height:150px; width:100px"> {% else %}
<img src="{% static 'book/images/logo.png' %}" alt="{{ book.title }}" class="img-fluid" style="height:150px; width:100px"> {% endif %}
<blockquote class="blockquote mt-3">
<a href="{% url 'viewonly' book.id %}">
<strong><p class="mb-0">{{ book.title|capfirst }}</p></strong>
</a>
<p class="mb-0">{% if book.summary %}{{ book.summary|truncatechars:80|safe }}{% endif %}</p>
</blockquote>
<footer class="blockquote-footer">by <cite title="Source Title">{{ book.author }}</cite></footer>
<small><p class="mb-0"><em>{{ book.user }}</em></p></small>
</div>
<hr> {% endfor %}
<div class="pagination">
<span class="step-links mr-2">
{% if page_obj.has_previous %}
« first
previous
{% endif %}
<span class="current mr-2">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
</span> {% if page_obj.has_next %}
next
last » {% endif %}
</span>
</div>
</div>
{% endif %} {% else %}
<div class="row">
<div class="col mt-5">
<a role="button" class="btn btn-outline-primary btn-lg" href="{% url 'createbook' %}">Add book</a>
</div>
<div class="col">
<h2>You haven't added any books yet...</h2>
<br>
<img src="../static/book/images/reading-list.svg" class="img-fluid mt-3" style="width:400px;" alt="Responsive image" title="stack of books">
</div>
</div>
</div>
{% endif %} {% endblock %}
views.py for currentbooks
from django.contrib import messages
...
#login_required
def currentbooks(request):
book_list = Book.objects.filter(user=request.user)
paginator = Paginator(book_list, 2)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(request, 'book/currentbooks.html', {'page_obj': page_obj, 'book_list': book_list})
my createbook.html to add books in the book folder
{% extends 'book/base.html' %} {% block title %} Add Book{% endblock %} {% block content %}
<div class="container mt-5">
<h1>Create Book...</h1>
</div>
<div class="form-group mt-3">
<form method="POST" enctype="multipart/form-data">
{% csrf_token %} {{ error }} {{ form.media }} {{ form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
<button type="button" class="btn btn-outline-warning" onclick="$('#cancel').click()">Cancel</button>
</form>
<form style='display: none;' method="POST" action="{% url 'currentbooks' %}">
{% csrf_token %}
<button id="cancel" type="submit">Cancel</button>
</form>
</form>
</div>
{% endblock %}
My editbook.html view to delete in the book folder
{% extends "book/base.html" %} {% block title %} Edit Book {% endblock %} {% block content %} {% if user.id == book.user_id %}
<div class="container mt-5">
<h1>Edit Book...</h1>
{% if error %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endif %}
</div>
<div class="form-group mt-3">
<form method="POST" enctype="multipart/form-data">
{% csrf_token %} {{ form.media }} {{ form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
<button type="button" class="btn btn-warning" onclick="$('#cancel').click()">Cancel</button>
<button type="button" class="btn btn-danger" onclick="$('#delete').click()">Delete</button>
</form>
<form style='display: none;' method="POST" action="{% url 'deletebook' book.id %}">
{% csrf_token %}
<button id="delete" type="submit">Delete</button>
</form>
<form style='display: none;' method="POST" action="{% url 'currentbooks' %}">
{% csrf_token %}
<button id="cancel" type="submit">Cancel</button>
</form>
</div>
{% else %}
<div class="row justify-content-center mt-5">
<h1>You are not allowed to edit this book...</h1>
</div>
{% endif %} {% endblock %}
views.py in the book folder
from django.contrib import messages
...
# Create
#login_required
def createbook(request):
if request.method == 'GET':
form = BookForm()
return render(request, 'book/createbook.html', {'form': form})
else:
try:
form = BookForm(request.POST, request.FILES)
newbook = form.save(commit=False)
newbook.user = request.user
if form.is_valid():
newbook.save()
# This message does not show up under the redirect
messages.success(request, 'Book saved!')
return redirect('currentbooks')
except ValueError:
messages.error(request, 'Bad data passed in. Try again.')
return render(request, 'book/createbook.html', {'form':BookForm()})
# Delete
#login_required
def deletebook(request, book_pk):
book = get_object_or_404(Book, pk=book_pk, user=request.user)
if request.method == 'POST':
book.delete()
# This message does not show up under redirect
messages.info(request, 'Book deleted!')
return redirect('currentbooks')
My loginuser.html to login in the members folder
{% extends 'book/base.html' %} {% block title %} Login {% endblock %} {% block content %}
<div class="container">
<h1>User Login...</h1>
<div class="row">
<div class="col mt-5">
<form method="POST">
<div class="form-group">
{% csrf_token %} {{ error }}
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" class="form-control" id="username" aria-describedby="usernameHelp">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" class="form-control" id="password">
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-outline-danger btn-lg">Sign In</button>
</div>
</form>
</div>
<div class="col">
<img src="../../static/book/images/studying.svg" class="img-fluid" alt="Responsive image" title="woman reading II">
</div>
</div>
</div>
{% endblock %}
views.py in the members folder
from django.shortcuts import render, redirect, get_object_or_404, HttpResponseRedirect
...
from django.contrib import messages
...
# Auth functions
def signupuser(request):
if request.method == 'GET':
return render(request, 'registration/signupuser.html', {'form':UserCreationForm()})
else:
if request.POST['password1'] == request.POST['password2']:
try:
user = User.objects.create_user(request.POST['username'], password=request.POST['password1'])
user.save()
login(request, user)
# This message does not show in the redirect
messages.success(request, 'User successfully created.')
return redirect('currentbooks')
except IntegrityError:
return render(request, 'registration/signupuser.html', {'form':UserCreationForm()})
else:
# This message does show up under render
messages.error(request, 'Passwords do not match.')
return render(request, 'registration/signupuser.html', {'form':UserCreationForm()})
def loginuser(request):
if request.method == 'GET':
return render(request, 'registration/loginuser.html', {'form':AuthenticationForm()})
else:
user = authenticate(request, username=request.POST['username'], password=request.POST['password'])
if user is None:
messages.error(request, 'Username and password do not match.')
# This message does show up under render
return render(request, 'registration/loginuser.html', {'form':AuthenticationForm()})
else:
login(request, user)
# This message does not show up under redirect
messages.success(request, 'Logged in successfully.')
return redirect('currentbooks')
#login_required
def logoutuser(request):
if request.method == 'POST':
logout(request)
# This message does not show up. I tried HttpResponseRedirect as a last option.
messages.success(request, 'Logged out successfully!')
return HttpResponseRedirect(reverse_lazy('loginuser'))
So ultimately, the messages don't seem to work with redirects, but they do work if I render and declare the folder and template name. Otherwise, no message displays if there is a redirect. I'm not quite sure what is wrong or why redirects are not working with these messages.
Matt Gleason's answer is incorrect, because messages framework doesn't store it in request object: https://docs.djangoproject.com/en/3.2/ref/contrib/messages/#storage-backends
Messages do work with redirects just fine out of the box. Check if everything is OK with your cookies (it's a default storage)

Model in header doesn't appear in views that use the header

Model defined in the header of my pages appears on page load and refresh on the main page, but when I navigate to another view the model doesn't appear there. The rest of the header is there, just the dynamic data that isn't.
Where am I going wrong? New to both Python and Django, so if anyone can help, please don't be afraid to patronize and Eli5 :)
Model defined in models.py:
from django.db import models
from django.utils import timezone
# Create your models here.
class Propaganda(models.Model):
slogan = models.CharField(max_length=140, blank=True, null=True)
def __str__(self):
return self.slogan
header.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Christopher's weblog</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Blog site.">
<!-- Let's get the static files where we use them, but this could be before the html tag -->
{% load staticfiles %}
<link rel="stylesheet" href="{% static 'blog/css/bulma.css' %}" type="text/css"/>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- <link rel="stylesheet" href="{% static 'blog/css/cupar.css' %}" type="text/css" /> -->
</head>
<body>
<section class="hero is-success is-bold">
<div class="hero-body">
<div class="container">
{% block slogan %}
{% for propaganda in propagandas %}
<h6>{{ propaganda.slogan }} it's</h6>
{% endfor %}
{% endblock %}
<h1 class="title" style="display: inline-block;">
<span class="icon">
<i class="fa fa-home"></i>
</span>
The Guide
</h1>
{% if user.is_authenticated %}
<div class="field">
<div class="control">
<a href="{% url 'post_new' %}" class="button is-warning is-pulled-right">
<span class="icon">
<i class="fa fa-plus-square"></i>
</span>
<span>New post</span>
</a>
</div>
</div>
{% endif %}
</div><!-- #container -->
</div>
</section>
<!-- content under header in here-> -->
{% block content %}
{% endblock %}
</body>
</html>
views.py
from django.template import RequestContext
from django.shortcuts import render, get_object_or_404, redirect
from .models import Post, Propaganda
from .forms import PostForm
from django.utils import timezone
# Create your views here.
def post_list(request):
posts = Post.objects.all()
propagandas = Propaganda.objects.all().order_by('?')[:1]
return render(request, 'blog/post_list.html', {'posts': posts, 'propagandas': propagandas})
post_detail.html (where the model does not appear):
{% extends 'blog/header.html' %}
{% block content %}
some html / form that has nothing to do with the header.
{% endblock %}
post_list.html (the 'index' page where the model works fine)
{% extends "blog/header.html" %}
{% block content %}
{% for post in posts %}
<section class="section">
more html
{% endblock %}
need to pass the data from each view function that is required in the header you are extending (re-using) in each template.
def post_detil(request, id):
posts = Post.objects.all()
propagandas = Propaganda.objects.all().order_by('?')[:1]
# ... add in other stuff relevant to post details ...
post = Post.objects.get(pk=id)
return render(request, 'blog/post_detail.html', {'posts': posts, 'propagandas': propagandas, 'post': post})
Stick with it #Rin and Len, you'll get there :)
First: Why are you not showing the view of post_detail. Isn't that the one that does not work?
Second: Even though you are extending a base template you still have to pass the appropriate context in order to generate the desired dynamic data.
I hope it helps.

Django template extending

I am new with Django and trying to understand how to use templates and I have an issue with template extending. I have 3 templates. the first one in the base.html
{% load staticfiles%}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<link rel="stylesheet" type="text/css" href="{%static 'css/main.css'%}">
<title>Home</title>
</head>
<body >
<div class="page-header">
<h1>Django Project</h1>
</div>
<div class="content container">
<div class="row">
<div class="col-sm-8">
{%block content %}
{%endblock%}
</div>
<div class="col-sm-4">
{%block lastposts %}
{%endblock%}
</div>
</div>
</div>
</body>
</html>
Second one is post_list.html (which I render from views)
{% extends 'blog/base.html' %}
{% block content %}
{%for post in posts %}
<h1>{{post.title}}</h1>
<p>{{post.text|linebreaks}}</p>
<p><b>Author: </b>{{post.author}}</p>
<p><b>Published Date: </b>{{post.published_date}}</p>
{%endfor%}
{% endblock %}
and latest_posts.html
{% extends 'blog/base.html' %}
{% block lastposts %}
<h3>Latest Posts</h3>
{%for post in posts%}
<h4>{{post.title}}</h4>
{% endfor %}
{% endblock %}
The problem is that the content of latest_posts.html does not show up. I know that something is wrong. In that case how I can use extending in django to to separate my code in these 3 files. Thanks.
*UPDATE
views.py
from django.shortcuts import render
from django.utils import timezone
from .models import Post
# Create your views here.
def post_list(request):
posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
return render(request, 'blog/post_list.html', {'posts': posts})
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.post_list, name='post_list'),
]
If you want to display the contents of latest_posts.html in post_list.html, you'll have to include it
post_list.html
{% extends 'blog/base.html' %}
{% block content %}
{%for post in posts %}
<h1>{{post.title}}</h1>
<p>{{post.text|linebreaks}}</p>
<p><b>Author: </b>{{post.author}}</p>
<p><b>Published Date: </b>{{post.published_date}}</p>
{%endfor%}
{% endblock %}
{%block lastposts %}
{% include 'blog/latest_posts.html' %}
{% endblock %}
latest_posts.html (only remove the extend and block tags)
<h3>Latest Posts</h3>
{%for post in posts%}
<h4>{{post.title}}</h4>
{% endfor %}