In my project there is an opportunity even for unauthorized users to leave a comment to a post. So, I have commentForm:
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('author', 'text',)
and model:
class Comment(models.Model):
post = models.ForeignKey('blog.Post', on_delete=models.CASCADE, related_name='comments')
author = models.CharField(max_length=200)
text = models.TextField()
If user is authorized, I want to substitute to author fileld username and don't show the input on page, otherwise site visitor should fill this input himself. I've tried to write this in appropriate view:
if request.user.is_authenticated:
form = CommentForm(request.POST, initial={'author': request.user.username})
But form.is_valid is false.
Then I've tried:
if request.user.is_authenticated:
form.fields['author'] = request.user.username
During form validating appeared 'string' object has no attribute 'disabled'.
The question is how to deal with it the right way? Thanks.
post_detail.html
{% extends 'blog/base.html' %}
{% block content %}
<div class="post">
{% if post.published_date %}
<div class="date">
{{ post.published_date }}
</div>
{% else %}
<a class="btn btn-default" href="{% url 'post_publish' post_id=post.pk blog_id=blog.pk %}">Publish</a>
{% endif %}
{% if user.is_authenticated and user == post.blog.author%}
<a class="btn btn-default" href="{% url 'post_remove' post_id=post.pk blog_id=blog.pk %}">удалить</a>
<a class="btn btn-default" href="{% url 'post_edit' post_id=post.pk blog_id=blog.pk %}">редактировать</a>
{% endif %}
<h1>{{ post.title }}</h1>
<p>{{ post.text|safe|linebreaks }}</p>
</div>
<hr>
<p>New comment</p>
<form method="POST" class="post-form">{% csrf_token %}
<!-- HERE I HIDE AUTHOR FIELD FROM LOGGED IN USERS -->
{% if user.is_authenticated %}
{{ form.text }}
{{ form.text.errors }}
{% else %}
{{ form.as_p }}
{% endif %}
<button type="submit" class="save btn btn-default">Send</button>
</form>
{% for comment in post.comments.all %}
<div class="comment">
<div class="date">
{{ comment.created_date }}
<!-- {% if not comment.approved_comment %} -->
<a class="btn btn-default" href="{% url 'comment_remove' post_id=post.pk blog_id=blog.pk com_id=comment.pk %}">удалить</a>
<!-- {% endif %}-->
</div>
<strong>{{ comment.author }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
{% endblock %}
views.py
from .models import Post, Comment, Blog
from django.shortcuts import render
from django.utils import timezone
from django.shortcuts import render, get_object_or_404
from .forms import PostForm, CommentForm, BlogForm
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import logout, login
from django.contrib.auth.models import User
def post_detail(request, blog_id, post_id):
blog = get_object_or_404(Blog, pk=blog_id)
post = get_object_or_404(Post, pk=post_id)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
if request.user.is_authenticated:
comment.author = request.user.username
comment.post = post
comment.save()
return redirect('post_detail', blog_id=blog_id, post_id=post.pk)
else:
form = CommentForm()
return render(request, 'blog/post_detail.html', {'post': post, 'blog': blog, 'form': form})
#login_required
def post_publish(request, blog_id, post_id):
post = get_object_or_404(Post, pk=post_id)
post.publish()
return redirect('post_detail', blog_id=blog_id, post_id=post.pk)
#login_required
def post_remove(request, blog_id, post_id):
post = get_object_or_404(Post, pk=post_id)
post.delete()
return redirect('post_list', blog_id=blog_id)
#login_required
def comment_remove(request, blog_id, post_id, com_id):
comment = get_object_or_404(Comment, pk=com_id)
comment.delete()
return redirect('post_detail', blog_id=blog_id, post_id=post_id)
#login_required
def post_edit(request, blog_id, post_id):
post = get_object_or_404(Post, pk=post_id)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('post_detail', blog_id = blog_id, post_id=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'blog/post_edit.html', {'form': form})
def post_list(request, blog_id):
blog = get_object_or_404(Blog, pk=blog_id)
posts = blog.posts.all().filter(published_date__isnull=False).order_by('published_date')
return render(request, 'blog/post_list.html', {'posts': posts, 'blog': blog})
I don't know if this is the best way to solve my problem, but it helped:
change a form value before validation in Django form
Related
I have got an error when I tried to display a form in function-based view in Django. I could display it in another HTML file and users can make their comments to the blog. But, I think it can be more convenient for users if they can make a comment on the same blog-detail HTML file, so I wanna implement it.
When I tried, this error showed up. "NoReverseMatch at /blogs/blog/30/
Reverse for 'blog' with no arguments not found. 1 pattern(s) tried: ['blogs/blog/(?P[0-9]+)/$']"
Any comments can help me and thanks for your time in advance!!
Here are the codes I wrote...
from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('user', 'text',)
#views.py
#login_required
def blog(request, pk):
blog = get_object_or_404(Blog, pk=pk)
form = CommentForm()
# if request.method == 'POST':
# form = CommentForm(request.POST)
# if form.is_valid():
# comment = form.save(commit=False)
# comment.blog = blog
# comment.save()
# return redirect('blog', pk=blog.pk)
# else:
# form = CommentForm()
if blog.link_1 is not None and blog.link_2 is not None:
link_1 = blog.link_1
link_2 = blog.link_2
context = {
'blog': blog,
'link_1': link_1,
'link_2': link_2,
'form': form,
}
elif blog.link_1 is not None or blog.link_2 is not None:
link_1 = blog.link_1
link_2 = blog.link_2
context = {
'blog': blog,
'link_1': link_1,
'link_2': link_2,
'form': form,
}
else:
context = {
'blog': blog,
'form': form,
}
return render(request, 'blog/blog.html', context)
#login_required
def add_comment(request, pk):
blog = get_object_or_404(Blog, pk=pk)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.blog = blog
comment.save()
return redirect('blog', pk=blog.pk)
else:
form = CommentForm()
context = {
'form': form,
}
return render(request, 'blog/blog.html', context)
#urls.py
path('blog/<int:pk>/', views.blog, name='blog'),
path('blog/<int:pk>/comment/', views.add_comment, name='add_comment'),
#blog.html
{% extends 'base.html' %}
{% block title %}|{{ blog.title }}{% endblock %}
{% block content %}
<div class="header-bar">
← 戻る
</div>
<div class="body-container">
<div class="created-edit-delete">
<p>
{% if request.user == blog.user %}
あなたが{{ blog.created }}に作成</p>
{% else %}
{{ blog.user }}が{{ blog.created }}に作成</p>
{% endif %}
<div class="icons">
{% if request.user == blog.user %}
{% endif %}
</div>
</div>
<h1>{{ blog.title }}</h1>
<p class="blog-content">{{ blog.content_1 }}</p>
{% if blog.content_2 %}
<p class="blog-content">{{ blog.content_2 }}</p>
{% endif %}
{% if blog.content_2 %}
<p class="blog-content">{{ blog.content_3 }}</p>
{% endif %}
<div class="ref-links">
{% if link_1 %}
参考リンク
{% endif %}
{% if link_2 %}
参考リンク
{% endif %}
</div>
<hr>
<div class="comment-area">
<div class="comment-form">
<h2>New comment</h2>
<form action="{% url 'add_comment' blog.id %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="button">追加</button>
</form>
</div>
<div class="comment-all">
{% for comment in blog.comments.all %}
<div class="comment">
<div class="date">{{ comment.created }}</div>
<strong>{{ comment.user }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
</div>
</div>
</div>
{% endblock %}
You have called blog URL here ← 戻る and forgot to pass id inside your URL that's why it's showing this error
NoReverseMatch at /blogs/blog/30/ Reverse for 'blog' with no arguments not found. 1 pattern(s) tried: ['blogs/blog/(?P[0-9]+)/$']
you have to pass id here like this
← 戻る
Sorry for being an embarrassing noob, but I have managed to complete like 99% of the Django Girls tutorial only to realize that there is one essential function in my basic blog site that's not working - the post titles on the main view don't link to their respective post views, even though the code seems alright to me... Guess I am really missing a glaringly obvious mistake! I was considering to switch from pk to slug, could that be an effective workaround?
views.py
from django.shortcuts import render, get_object_or_404
from django.shortcuts import redirect
from django.utils import timezone
from .models import Post
from .forms import PostForm
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})
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
def post_new(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.published_date = timezone.now()
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
def post_edit(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.published_date = timezone.now()
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'blog/post_edit.html', {'form': form})
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.post_list, name='post_list'),
path('post/<int:pk>/', views.post_detail, name='post_detail'),
path('post/new/', views.post_new, name='post_new'),
path('post/<int:pk>/edit/', views.post_edit, name='post_edit'),
]
post_detail.html
{% extends 'blog/base.html' %}
{% block content %}
<article class="post">
<aside class="actions">
{% if user.is_authenticated %}
<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}">
{% include './icons/pencil-fill.svg' %}
</a>
{% endif %}
</aside>
{% if post.published_date %}
<time class="date">
{{ post.published_date }}
</time>
{% endif %}
<h2>{{ post.title }}</h2>
<p>{{ post.text|linebreaksbr }}</p>
</article>
{% endblock %}
post_list.html
% extends 'blog/base.html' %}
{% block content %}
{% for post in posts %}
<article class="post">
<time class="date">
{{ post.published_date }}
</time>
<h2>{{ post.title }}</h2>
<p>{{ post.text|linebreaksbr }}</p>
</article>
{% endfor %}
{% endblock %}
Thank you for your patience!
I want to create a post update/edit function but I have a problem. When I click "Update" button there is no error but there is no change. I think reason of that a mistake that I made in models.py but I can not figure it out. And here is my code
models.py
class Post(models.Model):
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
title = models.CharField(max_length=200)
.
.
.
def get_update_url(self):
return reverse('post:post_update', kwargs={'slug': self.slug})
views.py
def post_update(request, slug):
if not request.user.is_authenticated():
return Http404()
post = get_object_or_404(Post, slug=slug)
form = PostForm(request.POST or None, request.FILES or None, instance=post)
if form.is_valid():
form.save()
messages.success(request, "Updated")
return HttpResponseRedirect(get_absolute_url())
context = {
'form': form
}
return render(request, "blog/post_update.html", context)
post_update.html
{% extends 'blog/base.html' %}
{% load crispy_forms_tags %}
{% block body %}
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1>Form</h1>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
{{ form.media }}
<input class="btn btn-primary" type="submit" value="Create post">
</form>
</div>
</div>
</div>
{% endblock %}
post_detail.html
//update link
<p >update</p>
urls.py
url(r'^(?P<slug>[\w-]+)/update/$', post_update, name="update"),
forms.py
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'text',)
Where is my mistake? What can I do?
I have a problem with django forms, when submitting a form nothing seems to happen, even the server didn't get any response except GET request to view the form template.
here is my code for the forms.py :
from django.forms import ModelForm
from .models import Post
class PostForm(ModelForm):
class Meta:
model = Post
fields = [
"title",
"content",
"category"
]
and here is my post_form.html :
{% extends 'base.html' %}
{% block content %}
<h1>form</h1>
<form method="POST" action=".">
{% csrf_token %}
{{ form.as_p }}
</form>
<button type="submit">Create Post</button>
{% endblock content %}
and here is my handling for the form in views.py :
def post_create(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.save()
return redirect("posts:detail", pk=post.pk)
else :
form = PostForm()
context = {
"form":form,
}
return render(request,"post_form.html", context)
forms.py
from django.forms import ModelForm
from .models import Post
class PostForm(ModelForm):
class Meta:
model = Post
fields = ["title", "content", "category"]
views.py
def post_create(request):
form = PostForm()
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save()
return redirect("posts:detail", pk=post.pk)
return render(request,"post-form.html", {"form": form})
post-form.html
{% extends 'base.html' %}
{% block content %}
<h1>form</h1>
{% for error in form.non_field_errors %}
<article class="message is-danger alert-message">
<div class="message-body">
<p>{{ error|escape }}</p>
</div>
</article>
{% endfor %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Create Post">
</form>
{% endblock content %}
in your views:
if form.is_valid():
form.commit = False
form.save()
or
if form.is_valid():
form.save(commit=false)
I suggest the latter
Don't Forget Place Your Submit Button In Form Tag !
how to prevent people from editing post and publishing and approving and deleting post of other people who are logined in the system in django.i am creating a forum where anyone can post question.i need help to control users who are already registered in the system
this my post_deatil.html
{% extends 'blog/base.html' %}
{% block content %}
<div class="post">
{% if post.published_date %}
<div class="date">
{{ post.published_date }}
</div>
{% else %}
{% if id.is_authenticated %}
<a class="btn btn-primary" href="{% url 'post_publish' pk=post.pk %}">Publish</a>
<a class="btn btn-danger" href="{% url 'post_remove' pk=post.pk %}"><span class="glyphicon glyphicon-remove"></span></a>
<a class="btn btn-success" href="{% url 'post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
{% endif %}
{% endif %}
<h1>{{ post.title }}</h1>
<p>{{ post.text|linebreaksbr }}</p>
</div>
<hr>
<a class="btn btn-info" href="{% url 'add_comment_to_post' pk=post.pk %}">Add comment</a>
{% for comment in post.comments.all %}
{% if user.is_authenticated or comment.approved_comment %}
<div class="comment">
<div class="date">
{{ comment.created_date }}
{% if not comment.approved_comment %}
<a class="btn btn-danger" href="{% url 'comment_remove' pk=comment.pk %}"><span class="glyphicon glyphicon-remove"></span></a>
<a class="btn btn-success" href="{% url 'comment_approve' pk=comment.pk %}"><span class="glyphicon glyphicon-ok"></span></a>
Cancel
{% endif %}
</div>
<strong>{{ comment.author }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
{% endif %}
{% empty %}
<p>No comments here yet:</p>
{% endfor %}
{% endblock %}
this my view.py
from django.shortcuts import render
from django.utils import timezone
from .models import Post, Comment
from django.shortcuts import render, get_object_or_404
from .forms import PostForm, CommentForm
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
def post_list(request):
posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
"""posts = Post.objects.filter(published_date__lte=timezone.now()).get_latest_by('published_date')"""
return render(request, 'blog/post_list.html', {'posts': posts})
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
#login_required
def post_new(request):
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
#login_required
def post_new(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
#login_required
def post_draft_list(request):
posts = Post.objects.filter(published_date__isnull=True).order_by('created_date')
return render(request, 'blog/post_draft_list.html', {'posts': posts})
#login_required
def post_publish(request, pk):
post = get_object_or_404(Post, pk=pk)
post.publish()
return redirect('post_detail', pk=pk)
#login_required
def publish(self):
self.published_date = timezone.now()
self.save()
#login_required
def post_remove(request, pk):
post = get_object_or_404(Post, pk=pk)
post.delete()
return redirect('post_list')
#login_required
def post_edit(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.published_date = timezone.now()
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'blog/post_edit.html', {'form': form})
#login_required
def add_comment_to_post(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('post_detail', pk=post.pk)
else:
form = CommentForm()
return render(request, 'blog/add_comment_to_post.html', {'form': form})
#login_required
def comment_approve(request, pk):
comment = get_object_or_404(Comment, pk=pk)
comment.approve()
return redirect('post_detail', pk=comment.post.pk)
#login_required
def comment_remove(request, pk):
comment = get_object_or_404(Comment, pk=pk)
post_pk = comment.post.pk
comment.delete()
return redirect('post_detail', pk=post_pk)
You can control it just by checking is authenticated user of session a author of entry.