Django error: 'WSGIRequest' object has no attribute 'post' for comments - python

I'm new to django and I'm working on a blog app and trying to enable comments for posts. When I write comments from admin page everthing works fine, but as a user I get following error: 'WSGIRequest' object has no attribute 'post'. Searching similar problems I see that mostly people switch request.Post for request.POST but I do not have that in my code, I wrote view for comment as a class not as def comment(request)… How do I solve this problem?
code from views.py:
class PostDetailView(DetailView):
model = Post
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = [title, summary, content, image]
def form_valid(self, form):
form.instance.author= self.request.user
return super().form_valid(form)
class CommentCreateView(LoginRequiredMixin, CreateView):
model = Comment
fields = ['content']
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.post = self.request.post
return super().form_valid(form)
code from models.py:
class Comment(models.Model):
post = models.ForeignKey(Post, related_name='comments', on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField()
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['created']
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
def __str__(self):
return 'Comment of user {}: {}'.format(self.user, self.content)
class Post(models.Model):
title= models.CharField(max_length=100)
summary= models.TextField(max_length=200, default='defalut text ...')
content= models.TextField()
image= models.ImageField(default='default.png', upload_to='post_pics')
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.image.path)
img.save(self.image.path)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
from post_detail.html:
{% extends "recepti/base.html" %}
{% block content %}
<article class="media content-section">
<img class="rounded-circle article-img" src="{{ object.author.profile.image.url }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-posts' object.author.username %}">{{ object.author }}</a>
<small class="text-muted">{{ object.date_posted|date:"F d, Y" }}</small>
<small class="">{{ object.comments.count }}</small> <i class="fa fa-comment"></i>
<small>0</small> <i class="fa fa-heart"></i><br>
{% if object.author == user %}
<div>
<a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'post-update' object.id %}">Update</a>
<a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'post-delete' object.id %}">Delete</a>
</div>
{% endif %}
</div>
<h2 class="article-title">{{ object.title}}</h2>
<p class="article-title">{{ object.summary}}</p>
<img src="{{ object.image.url }}">
<p class="article-content">{{ object.content}}</p>
<div class="btn-group" role="group" aria-label="Basic example">
<button type="button" class="btn btn-secondary">Like</button>
<a class="nav-item nav-link" href="{% url 'post-comment' %}">New comment</a>
</div>
<hr>
{% for comment in object.comments.all %}
<h5>{{ comment.user }}</h5>
<h6>{{ comment.created }}</h6>
<p>{{ comment.content }}</p>
{% empty %}
<p> No comments</p>
{% endfor %}
</div>
</article>
{% endblock content %}
code from urls.py:
urlpatterns = [
path('', PostListView.as_view(), name='recepti-home'),
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('post/new/', PostCreateView.as_view(), name='post-create'),
path('post/<int:pk>/update/', PostUpdateView.as_view(), name='post-update'),
path('post/<int:pk>/delete/', PostDeleteView.as_view(), name='post-delete'),
path('post/comment/', CommentCreateView.as_view(), name='post-comment'),
path('about/', views.about, name='recepti-about')
]
code from comment_form.html:
{% extends "recepti/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">New comment</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Submit</button>
</div>
</form>
</div>
{% endblock content %}

I guess the "post" is related to Comment.post not to the method you are using.
So Comment consists of 4 fields (one of them is autofield) but you listed only 'comment' in your fields - add other fields or use modelform

There are couple of little issues here; First, you need a way to specify the post which is going to have the comment in some way. You can use the primary key of post for that purpose. So you need to change the url like:
urls.py:
path('post/<int:post_pk>/comment/', CommentCreateView.as_view(), name='post-comment'),
and change the action attribute of the form as well:
template:
{% extends "recepti/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST" action="{% url 'post-comment' object.pk %}"> <-------------
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">New comment</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Submit</button>
</div>
</form>
</div>
{% endblock content %}
(based on the approach you used to render this template, you may need to replace post.pk with object.pk or something similar)
and finally, in the views.py, you can access the primary key of the post using self.kwargs:
class CommentCreateView(LoginRequiredMixin, CreateView):
model = Comment
fields = ['content']
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.post = self.kwargs.get('post_pk')
return super().form_valid(form)

Related

Cannot resolve keyword 'slug' into field

Im making comment and reply system in my blog using Django. Now im trying to get queryset of comments that dont have reply comments(if I dont do this, reply comments will be displayed on a page as regular comments). Here is error that i got:
FieldError at /post/fourh-news
Cannot resolve keyword 'slug' into field. Choices are: comm_to_repl, comm_to_repl_id, comment_content, created, id, post, post_of_comment, post_of_comment_id, replies, user_created_comment, user_created_comment_id
Request Method: GET
Request URL: http://127.0.0.1:8000/post/fourh-news
Django Version: 4.1.2
Exception Type: FieldError
Exception Value:
Cannot resolve keyword 'slug' into field. Choices are: comm_to_repl, comm_to_repl_id, comment_content, created, id, post, post_of_comment, post_of_comment_id, replies, user_created_comment, user_created_comment_id
Exception Location: D:\pythonProject28django_pet_project\venv\lib\site-packages\django\db\models\sql\query.py, line 1709, in names_to_path
Raised during: blog.views.ShowSingleNews
Python Version: 3.10.4
Model:
class Post(models.Model):
title = models.CharField(max_length=150, verbose_name='Название')
slug = models.CharField(max_length=100, unique=True, verbose_name='Url slug')
content = models.TextField(verbose_name='Контент')
created_at = models.DateTimeField(auto_now=True, verbose_name='Дата добавления')
updated_at = models.DateTimeField(auto_now=True, verbose_name='Дата обновления')
posted_by = models.CharField(max_length=100, verbose_name='Кем добавлено')
photo = models.ImageField(upload_to='photos/%Y/%m/%d', verbose_name='Фото', blank=True)
views = models.IntegerField(default=0)
category = models.ForeignKey('Category', on_delete=models.PROTECT, verbose_name='Категория')
tag = models.ManyToManyField('Tags', verbose_name='Тэг', blank=True)
comment = models.ForeignKey('Comment', verbose_name='Комментарий', on_delete=models.CASCADE, null=True, blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('single_news', kwargs={'slug': self.slug})
class Meta:
ordering = ['-created_at']
class Category(models.Model):
title = models.CharField(max_length=150, verbose_name='Название')
slug = models.CharField(max_length=100, unique=True, verbose_name='category_url_slug')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('category', kwargs={'slug': self.slug})
class Meta:
ordering = ['title']
class Tags(models.Model):
title = models.CharField(max_length=150, verbose_name='Название')
slug = models.CharField(max_length=100, unique=True, verbose_name='tag_url_slug')
def get_absolute_url(self):
return reverse('news_by_tag', kwargs={'slug': self.slug})
def __str__(self):
return self.title
class Meta:
ordering = ['title']
class Comment(models.Model):
user_created_comment = models.ForeignKey(User, related_name='user', on_delete=models.CASCADE, null=True)
post_of_comment = models.ForeignKey(Post, related_name='comments', on_delete=models.CASCADE, null=True)
comment_content = models.TextField(verbose_name='Текст комментария')
created = models.DateTimeField(auto_now=True)
comm_to_repl = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True, related_name='replies')
def get_absolute_url(self):
return reverse('single_news', kwargs={'slug': self.post_of_comment.slug})
class Meta:
ordering = ['-created']
View:
class ShowSingleNews(DetailView):
model = Post
template_name = 'blog/single_news.html'
context_object_name = 'post'
raise_exception = True
form = CommentForm
def post(self, request, *args, **kwargs):
form = CommentForm(request.POST)
if form.is_valid():
post = self.get_object()
form.instance.user_created_comment = request.user
form.instance.post_of_comment = post
commrepl = request.POST.get("commentID")
form.instance.comm_to_repl_id = int(commrepl)
form.save()
else:
print("some error with form happened")
print(form.errors.as_data())
return redirect(reverse("single_news", kwargs={
"slug": self.get_object().slug
}))
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = Post.objects.get(slug=self.kwargs['slug'])
context['form'] = self.form
self.object.views = F('views') + 1
self.object.save()
self.object.refresh_from_db()
return context
def get_queryset(self):
return Comment.objects.filter(replies=None)
Template:
{% extends 'base.html' %}
{% load static %}
{% load sidebar %}
{% block title %}
{{ title }}
{% endblock %}
{% block header %}
{% include 'inc/_header.html'%}
{% endblock %}
{% block content %}
<section class="single-blog-area">
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="border-top">
<div class="col-md-8">
<div class="blog-area">
<div class="blog-area-part">
<h2>{{ post.title}}</h2>
<h5> {{ post.created_at }}</h5>
<img src="{{ post.photo.url }}">
<div>
<span>Category: {{ post.category }}</span> <br>
<span>Posted by: {{ post.posted_by }}</span> <br>
</div>
<h5>Views: {{ post.views }}</h5>
<p>{{ post.content|safe }}</p>
<div class="commententries">
<h3>Comments</h3>
{% if user.is_authenticated %}
<form method="POST" action="{% url 'single_news' slug=post.slug %}">
{% csrf_token %}
<input type="hidden" id="commentID">
<div class="comment">
<input type="text" name="comment_content" placeholder="Comment" class="comment">
</div>
<div class="post">
<input type="submit" value="Post">
</div>
</form>
{% else %}
<h5>Login in order to leave a comment</h5>
{% endif %}
<ul class="commentlist">
{% if not post.comments.all %} </br>
<h5>No comments yet...</h5>
{% else %}
{% for comment in post.comments.all %}
<li>
<article class="comment">
<header class="comment-author">
<img src="{{ user.image.url }}" alt="">
</header>
<section class="comment-details">
<div class="author-name">
<h5>{{ comment.user_created_comment.username }}</h5>
<p>{{ comment.created }}</p>
</div>
<div class="comment-body">
<p>{{ comment.comment_content }} </p>
</div>
<div class="reply">
<p><span><i class="fa fa-thumbs-up" aria-hidden="true"></i>12</span><span><button class="fa fa-reply" aria-hidden="true"></button>7</span></p>
<form method="POST" action="{% url 'single_news' slug=post.slug %}">
{% csrf_token %}
<input type="hidden" name="commentID" value="{{ comment.id }}">
<div class="comment">
<input type="text" name="comment_content" placeholder="Comment" class="replyComment">
</div>
<div class="post">
<input type="submit" value="Reply">
</div>
</form>
</div>
</section>
{% if comment.replies.all %}
{% for reply in comment.replies.all %}
<ul class="children">
<li>
<article class="comment">
<header class="comment-author">
<img src="{% static 'img/author-2.jpg' %}" alt="">
</header>
<section class="comment-details">
<div class="author-name">
<h5>{{ reply.user_created_comment.username }}</h5>
<p>Reply to - {{ reply.comm_to_repl.user_created_comment }}</p>
<p>{{ reply.created }}</p>
</div>
<div class="comment-body">
<p>{{ reply.comment_content}}</p>
</div>
<div class="reply">
<p><span><i class="fa fa-thumbs-up" aria-hidden="true"></i>12</span><span><i class="fa fa-reply" aria-hidden="true"></i>7</span></p>
<form method="POST" action="{% url 'single_news' slug=post.slug %}">
{% csrf_token %}
<input type="hidden" name="commentID" value="{{ reply.id }}">
<div class="comment">
<input type="text" name="comment_content" placeholder="Comment" class="replyComment">
</div>
<div class="post">
<input type="submit" value="Reply">
</div>
</form>
</div>
</section>
</article>
</li>
</ul>
{% endfor %}
{% endif %}
</article>
{% endfor %}
{% endif %}
</ul>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="newsletter">
<h2 class="sidebar-title">Search for the news</h2>
<form action="{% url 'search' %}" method="get">
<input type="text" name="s" placeholder="Search...">
<input type="submit" value="Search">
</form>
</div>
{% get_popular_posts 5 %}
<div class="tags" style="">
<h2 class="sidebar-title">Tags</h2>
{% for ta in post.tag.all %}
<p>{{ ta.title }}</p>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
{% endblock %}
{% block footer %}
{% include 'inc/_footer.html' %}
{% endblock %}
Urls:
urlpatterns = [
path('', HomePage.as_view(), name='home'),
path('category/<str:slug>/', GetCategory.as_view(), name='category'),
path('post/<str:slug>', ShowSingleNews.as_view(), name='single_news'),
path('tag/<str:slug>', GetNewsByTag.as_view(), name='news_by_tag'),
path('search/', Search.as_view(), name='search'),
path('registration/', registration, name='registration'),
path('login/', loginn, name='login'),
path('logout/', logoutt, name='logout'),
forms:
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['comment_content']
You need to be a bit of change in passing URL in HTML like this...
<form method="POST" action="{% url 'single_news' post.slug %}">
{% csrf_token %}
<input type="hidden" id="commentID">
<div class="comment">
<input type="text" name="comment_content" placeholder="Comment" class="comment">
</div>
<div class="post">
<input type="submit" value="Post">
</div>
</form>
NOTE:- If you want to pass url with key you can do like this
<form method="POST" action="{% url 'single_news'?slug=post.slug %}">
{% csrf_token %}
<input type="hidden" id="commentID">
<div class="comment">
<input type="text" name="comment_content" placeholder="Comment" class="comment">
</div>
<div class="post">
<input type="submit" value="Post">
</div>
</form>

How to write an image attribute file in django (The 'image' attribute has no file associated with it)

I am building a django blog website and I am trying to upload an image on the website. I can access the photos on the admin page but whenever I try to access it on the page I get an enroll. The trace back says
"
The 'image' attribute has no file associated with it.
This my code for the model
class article(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField()
image = models.ImageField(null=True, blank=True, upload_to='static/media/article')
date = models.DateTimeField(default=timezone.now)
def __str__ (self):
return self.title
def get_absolute_url(self):
return reverse('article-detail', kwargs= {'pk':self.pk})
This is my views code
class ArticleCreateView(LoginRequiredMixin, CreateView):
model = article
fields= ['title', 'content', 'image']
def ArticleCreateView(request):
if request.method == "POST":
form = ArticleForm(request.POST, request.FILES)
if form.is_valid():
article = form.save(commit=False)
article.author = request.user.id
article.save()
return HttpResponse
this is the blog template code
{% extends "agri_tourism/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<section class="flex-container">
<div>
{% for article in articles %}
<article class="media content-section">
{% load static %}
<div class="media-body">
<div style="text-decoration:none; display: inline-block;" class="article-metadata">
<img class="rounded-circle article-img" src="{{user.profile.image.url}}">
<a style="text-decoration:none;" class="mr-2" href="#">{{ article.author }}</a>
<small class="article-date">{{ article.date|date:"F d, Y" }}</small>
</div>
<h2><a class="article-title" href="">{{ article.title }}</a></h2>
<p class="article-content">{{ article.content }}</p>
<img class="image-content" id="image-el" src = "{{article.image.url}}">
<div class="like-share-btns">
</div>
</article>
{% endfor %}
The form page code is below
{% extends "agri_tourism/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class = "content-section">
<div class = "container">
<div class = "row md-8">
<form method = "POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class = "form-group">
<legend class ="border-bottom mb-4">Blog article</legend>
{{form|crispy }}
{{form.media}}
</fieldset>
<div class= "form-group">
<button class="btn btn-outline-info" type="submit" style= "margin-top:4px; ">Submit the Article</button>
</div>
</form>
</div>
</div>
</div>
I want to access photos on the blog page
check the image with if condition like this...
<div class="media-body">
<div style="text-decoration:none; display: inline-block;" class="article-metadata">
{% if user.profile.image.url %}
<img class="rounded-circle article-img" src="{{user.profile.image.url}}">
{% endif %}
<a style="text-decoration:none;" class="mr-2" href="#">{{ article.author }}</a>
<small class="article-date">{{ article.date|date:"F d, Y" }}</small>
</div>
and also check those settings
urls.py (in project directory)
from django.conf import settings # --------> this
from django.conf.urls.static import static # --------> this
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('myapp.urls')),
]+static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # --------> this
settings.py (in project directory)
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

How can I restrict users to delete other's posts in django using class based views?

my views.py file:
from django.shortcuts import render
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.contrib.auth.mixins import (
LoginRequiredMixin,
UserPassesTestMixin,
)
from .models import Post
# Create your views here.
class PostListView(ListView):
model = Post
template_name = "blog/index.html"
context_object_name = "posts"
ordering = ["-date_posted"]
class PostDetailView(DetailView):
model = Post
class PostCreateView(CreateView, LoginRequiredMixin, UserPassesTestMixin):
model = Post
fields = ['title', 'genere', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(UpdateView, LoginRequiredMixin, UserPassesTestMixin):
model = Post
success_url = "blog-home"
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
class PostDeleteView(DeleteView, LoginRequiredMixin, UserPassesTestMixin):
model = Post
success_url = "/"
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
def about(request):
return render(request, 'blog/about.html')
My models.py:
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
# Create your models here.
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
genere = models.CharField(max_length=50, default='')
def __str__(self):
return f'{self.title} by {self.author}'
def get_absolute_url(self):
return reverse('blog-home')
my urls.py url:
from django.urls import path
from .views import PostListView, PostDetailView, PostCreateView, PostUpdateView, PostDeleteView
from . import views
urlpatterns = [
path("", PostListView.as_view(), name="blog-home"),
path("about", views.about, name="blog-about"),
path("post/<int:pk>", PostDetailView.as_view(), name="blog-detail"),
path("post/new", PostCreateView.as_view(), name="blog-create"),
path("post/<int:pk>/update", PostUpdateView.as_view(), name="blog-update"),
path("post/<int:pk>/delete", PostDeleteView.as_view(), name="blog-delete"),
]
index.html
{% extends "blog/base.html" %}
{% load static %}
{% block content %}
<div class="row tm-row">
{% for post in posts %}
<article class="col-12 col-md-6 tm-post">
<hr class="tm-hr-primary">
<a href="{% url 'blog-detail' post.id %}" class="effect-lily tm-post-link tm-pt-60">
<div class="tm-post-link-inner">
<img src="{% static 'img/img-01.jpg' %}" alt="Image" class="img-fluid">
</div>
<span class="position-absolute tm-new-badge">New</span>
<h2 class="tm-pt-30 tm-color-primary tm-post-title">{{ post.title }}</h2>
</a>
<p class="tm-pt-30">
{{ post.content|safe|truncatewords:"30"|linebreaks }}
</p>
<div class="d-flex justify-content-between tm-pt-45">
<span class="tm-color-primary">{{ post.genere }}</span>
<span class="tm-color-primary">{{ post.date_posted|date:'N j,Y' }}</span>
</div>
<hr>
<div class="d-flex justify-content-between">
<span>36 comments</span>
<span>by {{ post.author }}</span>
</div>
</article>
{% endfor %}
</div>
{% endblock %}
post_detail.html:
{% extends 'blog/base.html' %}
{% load crispy_forms_tags %}
{% load static %}
{% block content %}
<div class="container">
<article class="col-12 col-md-6 tm-post">
<hr class="tm-hr-primary">
<a href="" class="effect-lily tm-post-link tm-pt-60">
<div class="tm-post-link-inner">
<img src="{% static 'img/img-01.jpg' %}" alt="Image" class="img-fluid">
</div>
<span class="position-absolute tm-new-badge">New</span>
<h2 class="tm-pt-30 tm-color-primary tm-post-title">{{ object.title }}</h2>
{% if object.author == user %}
<a class="btn btn-outline-danger" href="{% url 'blog-delete' object.id %}">Delete</a>
<a class="btn btn-outline-secondary" href="{% url 'blog-update' object.id %}">Update</a>
{% endif %}
</a>
<p class="tm-pt-30">
{{ object.content }}
</p>
<div class="d-flex justify-content-between tm-pt-45">
<span class="tm-color-primary">{{ object.genere }}</span>
<span class="tm-color-primary">{{ object.date_posted|date:'N j,Y' }}</span>
</div>
<hr>
<div class="d-flex justify-content-between">
<span>36 comments</span>
<span>by {{ object.author }}</span>
</div>
</article>
</div>
{% endblock %}
post_confirm_delete.html:
{% extends 'blog/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="container">
<form method="POST">
{% csrf_token %}
<h2>Are You Sure You Want To Delete "{{ object.title }}"</h2>
<button class="btn btn-outline-danger">Yes, I'm Sure</button>
<a class="btn btn-outline-secondary" href="{% url 'blog-detail' object.id %}">Cancel</a>
</form>
</div>
{% endblock %}
So, what I'm getting is that suppose 2 person jeff and ram are users so ram cannot update the posts of jeff and vice versa.
And if jeff views the post of ram, so he does not get the update and delete, so he cannot edit the post of ram but if jeff goes to "127.0.0.1:8000/post/9/delete" from "127.0.0.1:800/post/9",
So he get the confirm delete page and he can even delete his post.
How can I fix this bug in my project??????
you can use get_queryset() to restrict query in database
class PostUpdateView(UpdateView, LoginRequiredMixin, UserPassesTestMixin):
model = Post
success_url = "blog-home"
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def get_queryset(self):
pk = self.kwargs.get(self.pk_url_kwarg)
return self.model.objects.filter(pk=pk,user=self.request.user)

How to add extra category field in django.views.generic

I have class in views.py:
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'content',]
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
I want to add object to fields, but when I'm trying to add like this:
fields = ['title', 'content', 'category']
the debugger send an error log like this:
FieldError at /post/new/
Unknown field(s) (category) specified for Post
I need an extra column to add category field when creating post in my django blog.
Here is blog_category.html
{% extends 'blog/base.html' %}
{% block content %}
<h1 class='mb-3'>Category: {{ category | title }}</h1>
{% for post in posts %}
<article class="media content-section">
<img class="rounded-circle article-img" src="{{ post.author.profile.image.url }}" alt="">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2 author_title" href="{% url 'user-posts' post.author.username %}">#{{ post.author }}</a>
<small class="text-muted">{{ post.date_posted|date:"N d, Y" }}</small>
<div>
<small class="text-muted">
Categories:
{% for category in post.categories.all %}
<a href="{% url 'blog_category' category.name %}">
{{ category.name }}
</a>
{% endfor %}
</small>
</div>
</div>
<h2><a class="article-title" href="{% url 'post-detail' post.id %}">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content|slice:200 }}...</p>
</div>
</article>
{% endfor %}
{% endblock content %}
models.py:
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
categories = models.ManyToManyField('Category', related_name='posts')
image = models.ImageField(upload_to='images', default="images/None/no-img.jpg")
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class Category(models.Model):
name = models.CharField(max_length=20)
My post_form.html:
{% extends 'blog/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Blog Post</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post</button>
</div>
</form>
</div>
{% endblock content %}
The main goal is:
create category field in views.py -> after pressing "Post" this field should push the content to the django admin panel and add category to the post(as title and content adding).
If someone have a ready solution or know how to solve this problem, I would be really happy.
fields = ['title', 'content', 'categories']

Django form action

I just started with Django and already scratching my head, I have a simple form with action set to null, On submit it goes to a url which I cannot find since I have to put a condition there as to which url should it hit.
template:
{% extends 'base.html' %}
{% block body_block %}
<div class="container">
<div class="">
<h2>Education Details</h2>
<form action="" method="post">
{{ form.as_p }}
{% csrf_token %}
<div class="d-flex justify-content-end">
{% if '/attorney-profile-wizard/additional-information/' not in request.META.HTTP_REFERER %}
<a href="{% url "attorney_edit" url_key %}"
class="material-button bg-red pl-2">Cancel</a>
{% else%}
<a href="/attorney-profile-wizard/additional-information/"
class="material-button bg-red pl-2">Cancel</a>
{% endif %}
<!--<a href="{% url "attorney_edit" url_key %}"-->
<!--class="material-button bg-red pl-2">Cancel</a>-->
<input type="submit" class="material-button" name="" value="Save Education">
</div>
</form>
</div>
</div>
{% endblock %}
Model:
class Education(models.Model):
degree = models.CharField(max_length=256)
school_name = models.CharField(max_length=256)
accolades = models.TextField(null=True)
start_year = models.IntegerField(blank=True, null=True)
end_year = models.IntegerField(blank=True, null=True)
is_law_school = models.BooleanField(default=False)
position = models.PositiveSmallIntegerField(blank=True, null=True)
attorney = models.ForeignKey(AttorneyProfile, related_name='educations')
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-id']
def __str__(self):
return '{} - {}'.format(self.attorney, self.degree)
views.py
class AttorneyEducationEditMixin(AttorneyEducationMixin, AttorneyEditMixin):
form_class = EducationForm
template_name = 'attorney/education/form.html'
class EducationCreateView(AttorneyEducationEditMixin, CreateView):
permission_required = 'educations.add_education'
class EducationUpdateView(AttorneyEducationEditMixin, EducationPermissionMixin,
UpdateView):
permission_required = 'educations.change_education'
class EducationDeleteView(AttorneyEducationMixin, EducationPermissionMixin,
DeleteView):
template_name = "attorney/shared/title_delete.html"
permission_required = 'educations.delete_education'
I even tried to override the form action trying the following way:
{% if '/attorney-profile-wizard/additional-information/' not in request.META.HTTP_REFERER %}
<form action="{% url "attorney_edit" url_key %}" method="post">
{% else %}
<form action="/attorney-profile-wizard/additional-information/" method="post">
{% endif %}
{{ form.as_p }}
{% csrf_token %}
<div class="d-flex justify-content-end">
{% if '/attorney-profile-wizard/additional-information/' not in request.META.HTTP_REFERER %}
<a href="{% url "attorney_edit" url_key %}"
class="material-button bg-red pl-2">Cancel</a>
{% else%}
<a href="/attorney-profile-wizard/additional-information/"
class="material-button bg-red pl-2">Cancel</a>
{% endif %}
<!--<a href="{% url "attorney_edit" url_key %}"-->
<!--class="material-button bg-red pl-2">Cancel</a>-->
<input type="submit" class="material-button" name="" value="Save Education">
</div>
</form>
This did not work and obviously is not the right way to do so. Where would I find the url for the action? I even checked urls.py file but it did not help much.

Categories