Comment is not displaying in django after submission - python

I have tried to submit a comment from app rather than django admin. Comment is not displaying when submitted from my created app. But it is displaying when I add a comment from django admin app. May be I am doing something wrong in views.py file. Can anyone help me on this? Thank you.
views.py:
#login_required
def book_review(request,id):
book = get_object_or_404(Bookslist, id=id)
comment=Comment.objects.all().filter(post_id=id)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.user_id = request.user
post.message= comment
post.save()
return redirect('book_review', id=id)
else:
form=CommentForm()
return render(request, "books/book_review.html", {'book':book, 'comment':comment, 'form': form})
models.py:
class Comment(models.Model):
message= models.TextField('Message',null=True)
date_comment=models.DateTimeField(default=now, null=True)
user_id= models.ForeignKey(User, on_delete=models.CASCADE,null=True)
post_id=models.ForeignKey(Bookslist,on_delete=models.CASCADE,null=True)
forms.py:
from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['message', ]
book_review.html:
{% extends 'books/base.html' %}
{% load static %}
{% block stylesheet %}
<link rel="stylesheet" href="{% static 'accounts/accounts.css' %}">
{% endblock %}
{% block content %}
<div class = "container">
<ul class = "nav nav-tabs" id = "myTab" role = "tablist">
<li class = "nav-item">
<a class = "nav-link active" id = "summary-tab" data-toggle = "tab"
href = "#summary" role = "tab" aria-controls = "summary"
aria-selected = "true">Summary</a>
</li>
<li class = "nav-item">
<a class = "nav-link" id = "characters-tab" data-toggle = "tab"
href = "#characters" role = "tab" aria-controls = "characters"
aria-selected = "false">Characters</a>
</li>
<li class = "nav-item">
<a class = "nav-link" id = "relatedbooks-tab" data-toggle = "tab"
href = "#relatedbooks" role = "tab" aria-controls = "relatedbooks"
aria-selected = "false">Related Books</a>
</li>
</ul>
<div class = "tab-content" id = "myTabContent">
<div class = "tab-pane fade show active" id = "summary" role = "tabpanel"
aria-labelledby = "summary-tab"><br><br>
{{book.summary}}
</div>
<div class = "tab-pane fade" id = "characters" role = "tabpanel"
aria-labelledby = "characters-tab"><br><br>
{{book.c1}}<br><br>{{book.c2}}<br><br>{{book.c3}}<br><br>{{book.c4}}<br><br>{{book.c5}}<br><br>
{{book.c6}}<br><br>{{book.c7}}<br><br>{{book.c8}}<br><br>{{book.c9}}<br><br>
{{book.c10}}
</div>
<div class = "tab-pane fade" id = "relatedbooks" role = "tabpanel"
aria-labelledby = "relatedbooks-tab">Content for related books tab</div>
</div>
<br>
<br>
<div class="container">
<form method="post" class="mb-4">
{% csrf_token %}
<div class="form-group">
<label for="exampleFormControlTextarea1">Leave your comment:</label>
<textarea class="form-control" id="exampleFormControlTextarea1" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-success">Post</button>
</form>
{% for com in comment %}
<div class="card mb-2">
<div class="card-body p-3">
<div class="row">
<div class="col-2">
<img src="{% static 'images/icon2.webp' %}" alt="{{ com.user_id }}" class="w-100">
<small>Posts: {{ com.count }}</small></div>
<div class="col-10">
<div class="row mb-3">
<div class="col-6">
<strong class="text-muted">{{ com.user_id }}</strong>
</div>
<div class="col-6 text-right">
<small class="text-muted">{{ com.date_comment }}</small>
</div>
</div>
{{ com.message }}<br><br>
{% if com.user_id == user %}
<button type="button" class="btn btn-primary">Reply</button>
{% endif %}
</div>
</div></div></div></div>
{% endfor %}
</div>
</div>
</div>
<!-- jQuery library -->
<script src = "https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity = "sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin = "anonymous">
</script>
<!-- Popper -->
<script src = "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity = "sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin = "anonymous">
</script>
<!-- Latest compiled and minified Bootstrap JavaScript -->
<script src = "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity = "sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous">
</script>
{% endblock %}

You need to add the post_id to the newly created comment.
Like so:
post.post_id = id
Also make sure you are using the correct naming for your variables i believe post should be comment in this scenario based on the form being of CommentForm: model = Comment
This replacement would make for sense for the code:
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.user_id = request.user
comment.message= comment
comment.post_id = id
comment.save()

Related

The modal appears but the profile edit form don't appear on it, any idea why?

On my social app that I'm working on, there's still one issue. On my ProfileDetailView, to click on "Edit Profile" the modal form appear but there's no form. It was working before but when I fixed the close button and I don't know what happened.. I copied the modal html from bootstrap so i probably deleted/changed something and forgot to re-do it..
Form:
from django import forms
from .models import Profile, Post, Comment
class ProfileModelForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('first_name', 'last_name', 'bio', 'avatar')
class PostModelForm(forms.ModelForm):
content = forms.CharField(widget=forms.Textarea(attrs={'rows':2, 'cols': 30}))
class Meta:
model = Post
fields = ('content', 'picture')
class CommentModelForm(forms.ModelForm):
body = forms.CharField(label='', widget=forms.TextInput(attrs={'placeholder': 'Add a comment...', 'class':'comment'}))
class Meta:
model = Comment
fields = ('body',)
Views:
from django.contrib.auth import authenticate, login, logout
from django.db import IntegrityError
from django.http import HttpResponse, HttpResponseRedirect
from django.http.response import JsonResponse
from django.shortcuts import render, redirect, resolve_url, get_object_or_404
from django.urls import reverse, reverse_lazy
from django.core import serializers
from django.core.paginator import Paginator
from django.contrib import messages
from django.contrib.auth.models import User
from django.db.models import Q
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from itertools import chain
from .models import Relationship, Post, Profile, Like
from django.views.generic import TemplateView, View, UpdateView, DeleteView, ListView, DetailView
from .forms import ProfileModelForm, PostModelForm, CommentModelForm
def search_view(request):
if request.method == "POST":
searched = request.POST['searched']
profiles = Profile.objects.filter(slug__contains=searched)
return render(request, 'network/search.html',
{'searched':searched,
'profiles':profiles})
else:
return render(request, 'network/search.html',
{})
class ProfileDetailView(LoginRequiredMixin, DetailView):
model = Profile
template_name = 'network/profile.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
user = User.objects.get(username__iexact=self.request.user)
profile = Profile.objects.get(user=user)
rel_r = Relationship.objects.filter(sender=profile)
rel_s = Relationship.objects.filter(receiver=profile)
rel_receiver = []
rel_sender = []
for item in rel_r:
rel_receiver.append(item.receiver.user)
for item in rel_s:
rel_sender.append(item.sender.user)
context["rel_receiver"] = rel_receiver
context["rel_sender"] = rel_sender
context["posts"] = self.get_object().get_all_authors_posts()
context["len_posts"] = True if len(self.get_object().get_all_authors_posts()) > 0 else False
return context
#login_required
def profile_view(request):
profile = Profile.objects.get(user=request.user)
form = ProfileModelForm(request.POST or None, request.FILES or None, instance=profile)
confirm = False
if request.method == 'POST':
if form.is_valid():
form.save()
confirm = True
context = {
'profile': profile,
'form': form,
'confirm': confirm,
}
return render(request, 'network/profile.html', context)
profile.html:
{% extends "network/layout.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block title %}
My Profile
{% endblock title %}
{% block body %}
<!--Modal-->
<div class="modal fade" id="profileModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Update Your Profile</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<img width="100px" src="{{object.avatar.url}}">
<form action="", method="POST", enctype="multipart/form-data" class="form-horizontal">
{% csrf_token %}
{{ form }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Update</button>
</form>
</div>
</div>
</div>
</div>
<div>
{% if confirm %}
<div class="alert alert-info" role="alert">Your profile has been updated!</div>
{% endif %}
</div>
<div class="row py-5 px-4">
<div class="col-md-5 mx-auto">
<!-- Profile widget -->
<div class="bg-white shadow rounded overflow-hidden">
<div class="px-4 pt-0 pb-4 cover">
<div class="media align-items-end profile-head">
<div class="profile mr-3"><img src="{{object.avatar.url}}" width="130" class="rounded mb-2 img-thumbnail"></div>
<div class="media-body mb-5 text-white">
<h4 class="mt-0 mb-3">{{profile.first_name}} {{profile.last_name}}</h4>
<p style="color: black;" class="small mb-4"> <i class="fas fa-map-marker-alt mr-2"></i>{{profile.country}}</p>
</div>
</div>
</div>
<div class="bg-light p-5 d-flex justify-content-end text-center">
<ul class="list-inline mb-0">
<li class="list-inline-item">
<h5 class="font-weight-bold mb-0 d-block">{{object.get_posts_num}}</h5><small class="text-muted"> <i class="fas fa-image mr-1"></i>Posts</small>
</li>
<li class="list-inline-item">
<h5 class="font-weight-bold mb-0 d-block">{{object.get_followers_num}}</h5><small class="text-muted"> <i class="fas fa-user mr-1"></i>Followers</small>
</li>
<li class="list-inline-item">
<h5 class="font-weight-bold mb-0 d-block">340</h5><small class="text-muted"> <i class="fas fa-user mr-1"></i>Following</small>
</li>
<li class="list-inline-item">
<h5 class="font-weight-bold mb-0 d-block">{{object.like_count}}</h5><small class="text-muted"> <i class="fas fa-user mr-1"></i>Likes</small>
</li>
</ul>
</div>
<div class="ml-2">
{% if object.user not in rel_receiver and object.user not in rel_sender %}
<form action="{% url 'send-invite' %}" method="POST">
{% csrf_token %}
<input type="hidden" name="profile_pk" value={{object.pk}}>
<button type="submit" class=" btn btn-sm btn-success w-btn"><i class="bi-plus-lg"></i> Follow</button>
</form>
{% endif %}
{% if object.user in rel_receiver and request.user not in object.following.all %}
<button class="btn btn-sm disabled "><i class="bi-three-dots"></i> Waiting aprroval</button>
{% endif %}
{% if request.user in object.following.all %}
<form action="{% url 'remove-friend' %}" method="POST">
{% csrf_token %}
<input type="hidden" name="profile_pk" value={{object.pk}}>
<button type="submit" class=" btn btn-sm btn-dark w-btn"><i class="bi-dash-lg"></i> Unfollow</button>
</form>
{% endif %}
</div>
<div class="px-4 py-3">
<h5 class="mb-0">About</h5>
<button class="btn btn-sm btn-secondary float-right" id="modal-btn" data-toggle="modal" data-target="#profileModal">Edit Profile</button>
<div class="p-4 rounded shadow-sm bg-light">
<p class="font-italic mb-0">{{profile.bio}}</p>
</div>
</div>
<div class="py-4 px-4">
<div class="d-flex align-items-center justify-content-between mb-3">
<h5 class="mb-0">Recent posts</h5>Show all
</div>
{% if len_posts %}
<div class="row">
{% for post in posts %}
<div class="col-lg-6 mb-2 pr-lg-1 fluid">
{% if post.picture %}
<img class="card-img-profile" src="{{post.picture.url}}">
{% endif %}
{{post.content}}
</div>
{% endfor %}
{% else %}
<h1>This user didn't post anything yet..</h1>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
Model:
class Profile(models.Model):
first_name = models.CharField(max_length=64, blank=True)
last_name = models.CharField(max_length=64, blank=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
country = models.CharField(max_length=64, blank=True)
avatar = models.ImageField(upload_to='avatars', default='avatar.png')
background = models.ImageField(upload_to='backgrounds', default='background.png')
following = models.ManyToManyField(User, related_name='following', blank=True)
bio = models.TextField(default="No Bio..")
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(unique=True, blank=True)
objects = ProfileManager()
def __str__(self):
return f"{self.user.username}"
def get_absolute_url(self):
return reverse("profile-view", kwargs={"slug": self.slug})
__initial_first_name = None
__initial_last_name = None
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__initial_first_name = self.first_name
self.__initial_last_name = self.last_name
def save(self, *args, **kwargs):
ex = False
to_slug = self.slug
if self.first_name != self.__initial_first_name or self.last_name != self.__initial_last_name or self.slug=="":
if self.first_name and self.last_name:
to_slug = slugify(str(self.first_name) + " " + str(self.last_name))
ex = Profile.objects.filter(slug=to_slug).exists()
while ex:
to_slug = slugify(to_slug + " " + str(get_random_code()))
ex = Profile.objects.filter(slug=to_slug).exists()
else:
to_slug = str(self.user)
self.slug = to_slug
super().save(*args, **kwargs)
def get_followers(self):
return self.following.all()
def get_followers_num(self):
return self.following.all().count()
def get_my_posts(self):
return self.post_set.all()
def get_country(self):
return self.post_set.all()
def get_following_users(self):
following_list = [p for p in self.get_following()]
return following_list
def get_all_posts(self):
users = [user for user in self.get_following()]
posts = []
qs = None
for u in users:
p = Profile.objects.get(user=u)
p_posts = p.post_set.all()
posts.append(p_posts)
my_posts = self.post_set.all()
posts.append(my_posts)
if len(posts) > 0:
qs = sorted(chain(*posts), reverse=True, key=lambda obj: obj.created)
return qs
def get_posts_num(self):
return self.post_set.all().count()
def get_all_authors_posts(self):
return self.post_set.all()
def get_likes_given_num(self):
likes = self.like_set.all()
total_liked = 0
for item in likes:
if item.value == 'Like':
total_liked += 1
return total_liked
def get_likes_received_num(self):
posts = self.post_set.all()
total_liked = 0
for item in posts:
total_liked += item.all().count()
return total_liked
def get_proposals_for_following(self):
profiles = Profile.objects.all().exclude(user=self.user)
followers_list = [p for p in self.get_following()]
available = [p.user for p in profiles if p.user not in followers_list]
random.shuffle(available)
return available[:3]
STATUS_CHOICES = (
('send', 'send'),
('accepted', 'accepted')
)
Update posts html:
{% extends "network/layout.html" %}
{% block title %}
Update Post
{% endblock title %}
{% block body %}
<div class="card center" style="width: 30rem;">
<h3>Update post</h3>
<form action="" method="POST" enctype="multipart/form-data" class="form-group">
{% csrf_token %}
{{form}}
<button type='submit' class="btn float-right btn-sm btn-primary mt-5">Update</button>
</form>
</div>
{% endblock body %}
URLs:
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
from . import views
from .views import (
posts_of_following_profiles,
like_unlike_post,
invites_received_view,
invite_profiles_list_view,
send_invitation,
remove_friends,
accept_invitation,
reject_invitation,
search_view,
post_comment_create_view,
login_view,
logout_view,
register,
ProfileDetailView,
PostDeleteView,
PostUpdateView,
ProfileListView,
)
urlpatterns = [
path("", ProfileListView.as_view(), name="all-profiles-view"),
path("posts/", views.post_comment_create_view, name="posts"),
path("posts-follow/", posts_of_following_profiles, name="posts-follow"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
path("liked/", like_unlike_post, name="like-post-view"),
path("<pk>/delete", PostDeleteView.as_view(), name="post-delete"),
path("<pk>/update", PostUpdateView.as_view(), name="post-update"),
path("invites/", invites_received_view, name="invites-view"),
path("send-invite/", send_invitation, name="send-invite"),
path("remove-friend/", remove_friends, name="remove-friend"),
path("invites/accept/", accept_invitation, name="accept-invite"),
path("invites/reject/", reject_invitation, name="reject-invite"),
path("to-invite/", invite_profiles_list_view, name='invite-profiles-view'),
path("search/", views.search_view, name='search-view'),
path("<slug>", ProfileDetailView.as_view(), name="profile-view"),
]
screenchot
Code snippet:
<div class="modal-header">
<h5 class="modal-title">Update Your Profile</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<img src="/media/avatars/11892013_911718608883264_3848632245418610369_n.jpg" width="100px">
<form action="" ,="" method="POST" enctype="multipart/form-data">
<input type="hidden" name="csrfmiddlewaretoken" value="P2vu2WI916PGSbMOrXD14c9EFmfMVEk3T1vkf9rqsZC7hXD94Dq2Cjo4MVCIiEEp">
</form></div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Update</button>
</div>

Form wont validate, says that all fields are empty Django

In a view I have 3 forms:
forms.py
class PostForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(PostForm, self).__init__(*args, **kwargs)
class Meta:
model = Post
fields = ['subtitle', 'latitude', 'longitude', 'tags', 'body']
widgets = {
'body': forms.Textarea(attrs={'class': 'log-body editable'}),
'tags': forms.TextInput(attrs={'id': 'tags-field', 'class': 'log-form-field'}),
'latitude': forms.TextInput(attrs={'id': 'latitude-field', 'class': 'log-form-field'}),
'longitude': forms.TextInput(attrs={'id': 'longitude-field', 'class': 'log-form-field'}),
'subtitle': forms.TextInput(attrs={'id': 'subtitle-field', 'class': 'log-form-field'}),
}
labels = {
'subtitle': 'Subtitle:',
'tags': 'Tags:',
'latitude': 'Latitude',
'longitude': 'Longitude',
'body': ''
}
class ImageForm(forms.ModelForm):
images = forms.ImageField(label='Images', widget=forms.ClearableFileInput(
attrs={
'multiple': True,
'class': 'file-upload',
'id': 'file-upload-button-image',
'name': 'images'}
)
)
class Meta:
model = PostImage
fields = ('images',)
class VideoForm(forms.ModelForm):
videos = forms.FileField(label='Videos', widget=forms.ClearableFileInput(
attrs={
'multiple': True,
'class': 'file-upload',
'id': 'file-upload-button-video',
'name': 'images'
}
)
)
class Meta:
model = PostVideo
fields = ('videos',)
And I have a template that creates a post and stores the videos and pictures and that works great. Where I'm having a hard time is updating a 'Post'.
class PostEditView(TemplateView):
template_name = 'Logging/edit view.html'
post_form_class = PostForm
image_form_class = ImageForm
video_form_class = VideoForm
def get_context_data(self, **kwargs):
context = super(PostEditView, self).get_context_data(**kwargs)
context['post_pk'] = self.kwargs['pk']
context['post_form'] = PostForm(instance=Post.objects.get(pk=self.kwargs['pk']))
context['image_form'] = ImageForm(empty_permitted=True, use_required_attribute=False)
context['video_form'] = VideoForm(empty_permitted=True, use_required_attribute=False)
context['images'] = PostImage.objects.filter(post_id=self.kwargs['pk'])
context['videos'] = PostVideo.objects.filter(post_id=self.kwargs['pk'])
return context
def post(self, request, *args, **kwargs):
context = self.get_context_data()
post_data = request.POST or None
if post_data.get('Delete'):
if len(post_data.getlist('img-index[]')) > 0:
for i in post_data.getlist('img-index[]'):
PostImage.objects.filter(id=i).delete()
if len(post_data.getlist('vid-index[]')) > 0:
for i in post_data.getlist('vid-index[]'):
PostVideo.objects.filter(id=i).delete()
print(post_data)
post_form = PostForm(data=post_data, instance=Post.objects.get(pk=self.kwargs['pk']), prefix='post')
print(post_form.is_bound)
post_form.is_valid()
print(post_form.errors)
images = request.FILES.getlist('image-images')
videos = request.FILES.getlist('video-videos')
if post_form.is_valid():
print('valid form')
for i in images:
instance = PostImage(image=i, post=context['post_pk'])
instance.save()
for v in videos:
instance = PostVideo(video=v, post=context['post_pk'])
instance.save()
return super(PostEditView, self).render_to_response(context)
def form_save(self, form, request):
obj = form.save(commit=False)
obj.user = request.user
obj.author = request.user.first_name + ' ' + request.user.last_name
obj.event_type = 'Log Entry'
obj.save()
messages.success(self.request, "{} posted successfully".format(obj))
return obj
When I call is_valid() on post_form it always says false, although it does say its bound. My post object does contain the data from the form in my template, including a csrf token, but for some reason the form is never valid and says that all the fields are empty.
from print(post_data):
<QueryDict: {'csrfmiddlewaretoken': ['h5uxuACKsvBcO4lrPB7yKbYgr0BsASEklT3GTp6R3t8na13TadAfjbihl2VyGvdC'], 'subtitle': ['Test with photos'], 'latitude': ['48.000'], 'longitude': ['112.000'], 'tags': ['[]'], 'images': [''], 'videos': [''], 'body': ['<p>body test 2 saa</p>']}>
from print(post_form.is_bound):
True
from print(post_form.errors):
<ul class="errorlist">
<li>subtitle<ul class="errorlist"><li>This field is required.</li></ul></li><li>latitude
<ul class="errorlist"><li>This field is required.</li></ul></li><li>longitude
<ul class="errorlist"><li>This field is required.</li></ul></li><li>tags
<ul class="errorlist"><li>This field is required.</li
></ul></li><li>body
<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
Models.py
class Post(models.Model):
class Status(models.TextChoices):
active = 'Active'
inactive = 'Inactive'
user = models.ForeignKey(Account, on_delete=models.CASCADE)
author = models.CharField(max_length=255)
title = models.CharField(max_length=80, default='Log Entry: ' + datetime.datetime.now().strftime("%m/%d/%Y, %H:%M:%S"))
subtitle = models.CharField(max_length=255)
latitude = models.DecimalField(decimal_places=3, max_digits=6)
longitude = models.DecimalField(decimal_places=3, max_digits=6)
post_time = models.DateTimeField(auto_now_add=True)
tags = TaggableManager()
body = models.TextField()
history = HistoricalRecords()
event_type = models.CharField(max_length=50, choices=EventType.choices, default='Log Entry', editable=False)
status = models.CharField(max_length=10, choices=Status.choices, default='Active')
def __str__(self):
return 'Post by: ' + str(self.user) + " on: " + self.post_time.strftime("%m/%d/%Y at %H:%M:%S")
def get_image_filename(instance, filename):
title = instance.post.title
slug = slugify(title)
return "post_media/%s/%s" % (slug, filename)
class PostImage(models.Model):
post = models.ForeignKey(Post, default=None, on_delete=models.PROTECT)
image = models.ImageField(upload_to=get_image_filename, verbose_name='Image')
def filename(self):
return self.image.name.split('/')[-1]
class PostVideo(models.Model):
post = models.ForeignKey(Post, default=None, on_delete=models.PROTECT)
video = models.FileField(upload_to=get_image_filename, verbose_name='Video')
def filename(self):
return self.video.name.split('/')[-1]
template:
{% extends 'layout/base.html' %}
{% load static %}
{% block titleblock %}New Log{% endblock %}
{% block header %}
<script src="{% static 'Logging/js/medium-editor.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'Logging/css/medium-editor.min.css' %}">
<link rel="stylesheet" href="{% static 'Logging/css/new_post.css' %}">
{% endblock %}
{% block bodyblock %}
<form class="post-form" id="post-form" enctype="multipart/form-data" method="POST" action=".">
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="Modal-title" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Confirm</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Are you sure you want to delete these items?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-danger" name="Delete" value="1" form="post-form">Delete</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-10 col-sm-12">
{% csrf_token %}
{% for field in post_form %}
{% ifnotequal field.label '' %}
<div class="input">
{{ field.label_tag }}
{{ field }}
</div>
<br>
{% endifnotequal %}
{% endfor %}
</div>
<div class="col-lg-2 col-sm-12 button-col">
<label for="file-upload-button-image" class="custom-file-upload">
<div class="upload-button-wrapper">
{{ image_form.images }}
<p id="image-num"></p>
<img src="{% static 'layout/img/image.svg' %}" alt="svg" id="img-svg">
<img src="{% static 'layout/img/plus-circle.svg' %}" alt="svg+" id="plus-svg">
</div></label>
<label for="file-upload-button-video" class="custom-file-upload">
<div class="upload-button-wrapper">
{{ video_form.videos }}
<p id="video-num"></p>
<img src="{% static 'layout/img/film.svg' %}" alt="svg" id="img-svg">
<img src="{% static 'layout/img/plus-circle.svg' %}" alt="svg+" id="plus-svg">
</div></label>
</div>
</div>
<div class="row">
<div class="col-lg-4 col-md-6 col-sm-12 edit-col">
<div class="images_existing">
{% for image in images %}
<div class="stacker">
<div class="image-selector-wrapper">
<input type="checkbox" id="" name="img-index[]" class="invisible img-checkboxes" value="{{ image.pk }}">
<img class="thumbnail" src="{{ image.image.url }}" alt="{{ image.filename }}">
<h6>{{ image.filename }}</h6>
{% if forloop.first %}
<div class="num-indicator" id="image-number"></div>
{% endif %}
</div>
</div>
{% endfor %}
<div class="button-box">
<button type="submit" name="download" value="1" class="btn-primary">Download</button>
<button type="button" class="btn-danger" data-toggle="modal" data-target="#deleteModal">Delete</button>
</div>
</div><div class="edit" id="edit-images">Edit</div>
</div>
<div class="col-lg-4 col-md-6 col-sm-12 edit-col">
<div class="videos_existing">
{% for video in videos %}
<div class="stacker">
<div class="video-selector-wrapper">
<input type="checkbox" id="" name="vid-index[]" value="{{ video.pk }}" class="invisible video-cb">
<img class="thumbnail-video" src="{% static 'layout/img/film.svg' %}" alt="{{ video.filename }}">
<h6>{{ video.filename }}</h6>
{% if forloop.first %}
<div class="num-indicator" id="video-number"></div>
{% endif %}
</div></div>
{% endfor %}
</div><div class="edit" id="edit-video">Edit</div>
</div></div>
<div class="row">
<div class="col">
{{ post_form.body }}
<button type="submit" class="custom-submit-button"><img src="{% static 'layout/img/upload.svg' %}" alt="submit"> <span>Submit</span></button>
</div>
</div>
{% if post_form.errors %}
{% for field in post_form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in post_form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
</form>
<script>var editor = new MediumEditor('.editable');</script>
<script src="{% static 'Logging/js/new_post.js' %}"></script>
{% endblock %}
I can not for the life of my figure this out. Any help would be appreciated!

Bootstrap base navs in django for loop

I am trying to use base navs of bootstrap in django using for loop to display the summary and profile of book based on the book id. I am getting "Could not parse the remainder: '()' from 'book.objects.all()'" error. Please let me know if there is any other way to fix this. Can anyone please hint me how to go ahead?
book_review.html:-
{% extends 'books/base.html' %}
{% block content %}
<div class = "container">
<ul class = "nav nav-tabs" id = "myTab" role = "tablist">
<li class = "nav-item">
<a class = "nav-link active" id = "summary-tab" data-toggle = "tab"
href = "#summary" role = "tab" aria-controls = "summary"
aria-selected = "true">Summary</a>
</li>
<li class = "nav-item">
<a class = "nav-link" id = "profile-tab" data-toggle = "tab"
href = "#profile" role = "tab" aria-controls = "profile"
aria-selected = "false">Profile</a>
</li>
<li class = "nav-item">
<a class = "nav-link" id = "relatedbooks-tab" data-toggle = "tab"
href = "#relatedbooks" role = "tab" aria-controls = "relatedbooks"
aria-selected = "false">Related Books</a>
</li>
</ul>
<div class = "tab-content" id = "myTabContent">
<div class = "tab-pane fade show active" id = "summary" role = "tabpanel"
aria-labelledby = "summary-tab"><br><br>
{% for booksummary in book.objects.all() %}
{{booksummary.summary}}
{% endfor %}
</div>
<div class = "tab-pane fade" id = "profile" role = "tabpanel"
aria-labelledby = "profile-tab">
{% for bookprofile in book.objects.all() %}
<b><label for="title">Title:</label></b>
<p class="card-title">{{bookprofile.title}}</p>
<b><label for="author">Author:</label></b>
<p class="card-text">{{bookprofile.author}}</p>
<b><label for="release_date">Release Date:</label></b>
<p class="card-text">{{bookprofile.release_date}}</p>
<b><label for="language">Language:</label></b>
<p class="card-text">{{bookprofile.language}}</p>
<b><label for="genre">Genre:</label></b>
<p class="card-text">{{bookprofile.genre}}</p><br>
{% endfor %}
</div>
<div class = "tab-pane fade" id = "relatedbooks" role = "tabpanel"
aria-labelledby = "relatedbooks-tab">Content for related books tab</div>
</div>
<br>
<!-- jQuery library -->
<script src = "https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity = "sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin = "anonymous">
</script>
<!-- Popper -->
<script src = "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity = "sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin = "anonymous">
</script>
<!-- Latest compiled and minified Bootstrap JavaScript -->
<script src = "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity = "sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous">
</script>
{% endblock %}
views.py:
def book_review(request,id):
book = get_object_or_404(Bookslist, id=id)
return render(request, "books/book_review.html", {'book': book})
models.py:
class Bookslist(models.Model):
title=models.CharField(max_length=30, unique=True)
author=models.CharField(max_length=30)
release_date= models.DateField()
language= models.CharField(max_length=30)
genre= models.CharField(max_length=30)
image= models.ImageField(upload_to='book_images/')
summary = models.TextField(blank=True, null=True)
def __str__(self):
return self.title
urls.py:
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.home, name="Home"),
path('books/<int:id>/', views.book_review, name="book_review"),
path('about/', views.about, name="about"),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
You don't pass querysets like this in the template. If you want to show details of only one book then it should be
<div class = "tab-pane fade show active" id = "summary" role = "tabpanel" aria-labelledby = "summary-tab">
<br><br>
{{book.summary}}
</div>
<div class = "tab-pane fade" id="profile" role = "tabpanel" aria-labelledby = "profile-tab">
<b><label for="title">Title:</label></b>
<p class="card-title">{{book.title}}</p>
<b><label for="author">Author:</label></b>
<p class="card-text">{{book.author}}</p>
<b><label for="release_date">Release Date:</label></b>
<p class="card-text">{{book.release_date}}</p>
<b><label for="language">Language:</label></b>
<p class="card-text">{{book.language}}</p>
<b><label for="genre">Genre:</label></b>
<p class="card-text">{{book.genre}}</p>
<br>
</div>
If you want to show all the books then your view will be like this:
def book_review(request,id):
context ={}
book = get_object_or_404(Bookslist, id=id)
context['book'] = book
context['allBooks'] = Bookslist.objects.all()
return render(request, "books/book_review.html", context)
and then you will iterate over your book objects in template like this:
{% for b in allBooks %}
{{b.author}}
<!-- and so on for other attributes -->
{% endfor %}

Attribute error : 'WSGIRequest' object has no attribute 'get'

I've been working on a project lately and got the above error. It says " Error during template rendering".I have a similar model, which works perfectly fine. I've looked for similar errors but got none matching my situation. I don't know where I went wrong. It would be great if I get helpful answers.
Models.py
class ServiceTax(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE,related_name="service_tax",null=True,blank=True)
name=models.CharField(max_length=100)
percent=models.FloatField(default='0')
add_amount=models.IntegerField(default='0')
def __str__(self):
return self.name
Forms.py
class ServiceTaxForm(forms.ModelForm):
class Meta:
model = ServiceTax
fields = "__all__"
widgets = {
'name' : forms.TextInput(attrs={'class': 'form-control'}),
'percent' : forms.NumberInput(attrs={'class': 'form-control','step':'0.01'}),
'add_amount' : forms.NumberInput(attrs={'class':'form-control','maxlength':5}),
}
labels={
'add_amount': "Additional Amount"
}
Views.py
def tax_form(request,id=0):
if request.method == 'GET':
if id == 0:
form = ServiceTaxForm(request)
else:
tax = ServiceTax.objects.get(pk=id)
if tax in request.user.service_tax.all():
form = ServiceTaxForm(request,instance=tax)
else:
return redirect('/revenue/tax')
return render(request,'tax-form.html',{'form':form})
else:
if id==0:
form = ServiceTaxForm(request,request.POST)
if form.is_valid():
name = form.cleaned_data["name"]
percent = form.cleaned_data["percent"]
add_amount = form.cleaned_data["add_amount"]
t = AnnualTax(
name=name,
percent=percent,
add_amount=add_amount,
)
t.save()
request.user.service_tax.add(t)
else:
tax = ServiceTax.objects.get(pk=id)
if tax in request.user.service_tax.all():
form = ServiceTaxForm(request,request.POST,instance=tax)
if form.is_valid():
name = form.cleaned_data["name"]
percent = form.cleaned_data["percent"]
add_amount = form.cleaned_data["add_amount"]
tax_obj = ServiceTax.objects.get(pk=id)
tax_obj.name = name
tax_obj.percent = percent
tax_obj.add_amount = add_amount
tax_obj.save()
return redirect('/revenue/tax')
tax-form.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<i class="fa fa-chevron-circle-left fa-3x m-2"></i>
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<h4 class="card-title">Add Service Tax</h4>
</div>
<div class="card-body">
<form action="" method="POST" autocomplete="off">
{% csrf_token %}
<div class="row">
<div class="col-md-4 pr-1">
<div class="form-group">
{{ form.name | as_crispy_field}}
</div>
</div>
<div class="col-md-4 pr-1">
<div class="form-group">
{{ form.percent | as_crispy_field}}
</div>
</div>
<div class="col-md-4 pr-1">
<div class="form-group">
{{ form.add_amount | as_crispy_field}}
</div>
</div>
</div>
<button type="submit" class="btn btn-success btn-fill pull-right">
{% if request.get_full_path == '/income/tax/add/' %}
Add Tax
{% else %}
Update
{% endif %}
</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
You should retrieve your forms passing request.METHOD, not just request
As an example this piece of code form = ServiceTaxForm(request) should be form = ServiceTaxForm(request.POST)

Django Custom Tag Filtering

Need a little help.
I have a news site, and what I'm trying to do is make a custom tag (it has to be a custom tag, part of my task) that will display the latest 3 news in a category. So let's say I click on a "health" article, the article opens, and my custom tag renders the latest 3 news from the health category next to the article. I hope I didnt confuse you, I'm still learning.
My tag :
from django import template
from news.models import Article
register = template.Library()
#register.inclusion_tag("news/categories.html")
def show_results(category=None):
article = Article.objects.all()
if category:
article = article.filter(category=category)
return {'article': article[:3]}
My models:
class Category(models.Model):
category_title = models.CharField(max_length=200, default="")
def __str__(self):
return self.category_title
class Article(models.Model):
title = models.CharField('title', max_length=200, blank=True)
slug = AutoSlugField(populate_from='title', default="",
always_update=True, unique=True)
author = models.CharField('Author', max_length=200, default="")
description = models.TextField('Description', default="")
is_published = models.BooleanField(default=False)
article_text = models.TextField('Article text', default="")
pub_date = models.DateTimeField(default=datetime.now, blank=True)
article_image = models.ImageField('Article Image')
article_category = models.ForeignKey(Category, on_delete="models.CASCADE", default="")
img2 = models.ImageField('Article Image 2', default="", blank=True)
img3 = models.ImageField('Article Image 3', default="", blank=True)
img4 = models.ImageField('Article Image 4', default="", blank=True)
img5 = models.ImageField('Article Image 5', default="", blank=True)
img6 = models.ImageField('Article Image 6', default="", blank=True)
def __str__(self):
return self.title
My views:
from django.shortcuts import render, reverse, get_object_or_404
from django.views import generic
from news.models import Article, Category
from .forms import CommentForm
from django.http import HttpResponseRedirect
class IndexView(generic.ListView):
template_name = 'news/index.html'
context_object_name = 'latest_article_list'
def get_queryset(self):
return Article.objects.order_by("-pub_date").filter(is_published=True)[:6]
class CategoryView(generic.ListView):
template_name = 'news/categories.html'
context_object_name = 'category'
def get_queryset(self):
return Article.objects.filter(article_category__category_title="Politics")
class ArticlesView(generic.ListView):
context_object_name = 'latest_article_list'
template_name = 'news/articles.html'
paginate_by = 5
def get_context_data(self, **kwargs):
context = super(ArticlesView, self).get_context_data(**kwargs)
context['categories'] = Category.objects.all()
return context
def get_queryset(self):
category_pk = self.request.GET.get('pk', None)
if category_pk:
return Article.objects.filter(article_category__pk=category_pk).order_by("-pub_date")
return Article.objects.order_by("-pub_date")
def article(request, article_id):
article = get_object_or_404(Article, pk=article_id)
context = {'article': article}
return render(request, 'news/article.html', context)
edit: so, to clarify further, my question is : When I click on a "health" article and it opens, how do I make my custom tag filter only the articles from that specific category, sorry if it's confusing !
So if i click on health, I need the tag to render the latest 3 health articles, if I click on a "music" article, I need the tag to render the latest 3 news from the "music" category...I hope I didnt confuse you even more !
Thank you so so much !!!
edit2:
my html :
{% extends "news-base.html" %}
{% load static %}
{% load article_extras %}
{% block article %}
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
{% show_results article_category %}
<div class="preloader d-flex align-items-center justify-content-center">
<div class="spinner">
<div class="double-bounce1"></div>
<div class="double-bounce2"></div>
</div>
</div>
<!-- {% show_results article.category %} -->
<!-- ##### Post Details Area Start ##### -->
<section class="container post-details-area">
<div class="container single-article-div">
<hr class="hr-single">
<h2 class="single-article-titles">{{ article.title }}</h2>
<hr class="hr-single">
<img class="single-article-img" src="{{ article.article_image.url }}" alt="">
<!-- *********************************** -->
<hr class="hr-single">
<p>Category: {{ article.article_category }}</p>
<hr class="hr-single">
<div class="row justify-content-center">
<!-- Post Details Content Area -->
<div class="col-12 col-xl-8">
<div class="post-details-content bg-white box-shadow">
<div class="blog-thumb">
</div>
<div class="blog-content">
<div class="post-meta">
{{ article.pub_date }}
</div>
<h3 class="single-article-titles post-title"> {{ article.description }}</h3>
<hr>
<!-- Post Meta -->
<div class="post-meta-2">
<i class="fa fa-eye" aria-hidden="true"></i> 1034
<i class="fa fa-thumbs-o-up" aria-hidden="true"></i> 834
<i class="fa fa-comments-o" aria-hidden="true"></i> 234
</div>
<p>{{ article.article_text }}</p>
<hr />
{% include "partials/_thumbnails.html" %}
<hr>
<p>Author: {{ article.author }}</p>
<hr>
{% for comment in article.comments.all %}
<div class="comment">
<div class="date">{{ comment.created_date }}</div>
<strong>{{ comment.author }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
</div>
<!-- Post A Comment Area -->
<div class="post-a-comment-area bg-white mb-30 p-30 box-shadow clearfix">
<!-- Section Title -->
<div class="section-heading">
<h5>LEAVE A REPLY</h5>
</div>
<!-- Reply Form -->
<div class="contact-form-area">
<form action="#" method="post">
<div class="row">
<div class="col-12 col-lg-6">
<input type="text" class="form-control comment-section" id="name" placeholder="Your Name*"
required />
</div>
<div class="col-12 col-lg-6">
<input type="email" class="form-control comment-section" id="email" placeholder="Your Email*"
required />
</div>
<div class="col-12">
<textarea name="message" class="form-control" id="message" cols="30" rows="10"
placeholder="Message*" required></textarea>
</div>
<div class="col-12">
<button class="btn mag-btn comment-section" type="submit">
Submit Comment
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<script>
jQuery(document).ready(function ($) {
//set here the speed to change the slides in the carousel
$('#myCarousel').carousel({
interval: 5000
});
//Loads the html to each slider. Write in the "div id="slide-content-x" what you want to show in each slide
$('#carousel-text').html($('#slide-content-0').html());
//Handles the carousel thumbnails
$('[id^=carousel-selector-]').click(function () {
var id = this.id.substr(this.id.lastIndexOf("-") + 1);
var id = parseInt(id);
$('#myCarousel').carousel(id);
});
// When the carousel slides, auto update the text
$('#myCarousel').on('slid.bs.carousel', function (e) {
var id = $('.item.active').data('slide-number');
$('#carousel-text').html($('#slide-content-' + id).html());
});
});
</script>
{% endblock %}
Your template {% show_results article_category %} uses the variable article_category yet your view doesn't expose this variable in the contexts. Including it in your context should fix your problem, i.e.:
def article(request, article_id):
article = get_object_or_404(Article, pk=article_id)
context = {
'article': article,
'article_category': article.article_category.category_title
}
return render(request, 'news/article.html', context)
oh, and just noticed..., your template tag tries to filter on category:
if category:
article = article.filter(category=category)
but the name of the field in the model is article_category. In addition, since it's a foreign key, you'll need:
if category:
article = article.filter(article_category__category_title=category)
i.e. filter by the category_title field of the pointed to article_category.

Categories