Django, why this is not working(reply of comment function) - python

I want to make reply of comment function. so I added parent option in Answer model. answer_create() working well.
but, when i submit reply of comment, url is different with url i setting.
i think i should be http://127.0.0.1:8000/debateboard/305/
but return http://127.0.0.1:8000/debateboard/answer/reply/31/
help me plz
models.py
class Question(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='author_question')
subject = models.CharField(max_length=200)
content = models.TextField()
create_date = models.DateTimeField()
modify_date = models.DateTimeField(null=True, blank=True)
voter = models.ManyToManyField(User, related_name='voter_question')
def __str__(self):
return self.subject
class Answer(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='author_answer')
question = models.ForeignKey(Question, on_delete=models.CASCADE)
content = models.TextField()
create_date = models.DateTimeField()
modify_date = models.DateTimeField(null=True, blank=True)
voter = models.ManyToManyField(User, related_name='voter_answer')
######### i added this parent to make reply of comment
parent = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True, related_name='+')
def __str__(self):
return self.content
#property
def children(self):
return Answer.objects.filter(parent=self).order_by('-create_date').all()
#property
def if_parent(self):
if self.parent is None:
return True
return False
urls.py
urlpatterns = [
path('', base_views.index, name = 'index'),
path('<int:question_id>/', base_views.detail, name = 'detail'),
path('answer/create/<int:question_id>/', answer_views.answer_create, name = 'answer_create'),
path('answer/reply/<int:answer_id>/', answer_views.reply_comment_create , name='reply_comment_create'),
view
def detail(request, question_id):
# question = Question.objects.get(id = question_id)
question = get_object_or_404(Question, pk = question_id)
context = {'question' : question}
return render(request, 'debateboard/detail.html', context)
#login_required(login_url='common:login')
def reply_comment_create(request, answer_id):
answer = get_object_or_404(Answer, pk=answer_id)
# question = get_object_or_404(Question, pk = answer.question.id)
if request.method == "POST":
form = AnswerForm(request.POST)
if form.is_valid():
sub_answer = form.save(commit=False)
sub_answer.author = request.user
sub_answer.create_date = timezone.now()
sub_answer.parent = answer.id
sub_answer.save()
# return redirect('{}#answer_{}'.format(resolve_url('debateboard:detail', question_id = answer.question.id), answer.id))
return redirect('debateboard:detail', question_id = answer.question.id)
else:
return HttpResponseNotAllowed('only post is possible')
context = {'question' : answer.question, 'form': form}
return render(request, 'debateboard/detail.html', context)
#login_required(login_url = 'common:login')
def answer_create(request, question_id):
question = get_object_or_404(Question, pk = question_id)
# question.answer_set.create(content=request.POST.get('content'), create_date = timezone.now())
if request.method == 'POST':
form = AnswerForm(request.POST)
if form.is_valid():
answer = form.save(commit=False)
answer.author = request.user
answer.create_date = timezone.now()
answer.question = question
answer.save()
# return redirect('debateboard:detail', question_id = question.id)
return redirect('{}#answer_{}'.format(resolve_url('debateboard:detail', question_id = question.id), answer.id))
else:
return HttpResponseNotAllowed('Only POST is possible.')
context = {'question': question, 'form': form}
return render(request, 'debateboard/detail.html', context)
html
<!-- for reply of comment -->
<form action="{% url 'debateboard:reply_comment_create' answer.id %}" method="POST">
{% csrf_token %}
<div class="form-group">
<textarea name="reply_comment_{{ answer.id }}" id="reply_comment_{{ answer.id }}" cols="20" rows="5"></textarea>
<button type="submit">dd</button>
</div>
</form>
<!-- for comment-->
<form action="{% url 'debateboard:answer_create' question.id %}" method="post">
{% csrf_token %}
<div class="form-group">
<textarea {% if not user.is_authenticated %}disabled placeholder="로그인후 이용가능" {% endif %} name="content" id="content" cols="30" rows="15"></textarea>
</div>
<input {% if not user.is_authenticated %}disabled placeholder="로그인후 이용가능" {% endif %} type="submit" class="btn btn-primary" value="답변등록">
</form>

The address is structured this way because you add an object of class Answer. Anyway, look at how your url is constructed.
path('answer/reply/<int:answer_id>/', answer_views.reply_comment_create , name='reply_comment_create'),
If you want, check the SlugField which can be useful for create custom url.

Related

I cannot post comment in Django, no error

I'm working on a Django blog and I'm stuck here... I want to post comment and when I do that it just refresh the page and nothing happens.
I have no idea where I'm making a mistake, please see my code below:
this is views.py
def post_detail(request, slug):
post = get_object_or_404(Post, slug=slug)
related_posts = post.tags.similar_objects()[:3]
comments = post.comments.filter(active=True)
new_comment = None
if request.method == 'POST':
if request.user.is_authenticated:
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.post = post
new_comment.author = request.user
new_comment.save()
else:
messages.warning(request, 'You need to be logged in to add a comment.')
else:
if request.user.is_authenticated:
comment_form = CommentForm(initial={'author': request.user})
else:
comment_form = CommentForm()
context = {'post': post, 'related_posts': related_posts, 'comments': comments, 'new_comment': new_comment, 'comment_form': comment_form}
return render(request, 'post_detail.html', context)
this is comment part post_detail.html
{% if user.is_authenticated %}
<!--comment form-->
<div class="comment-form">
<h3 class="mb-30">Leave a Reply</h3>
<form class="form-contact comment_form" action="{% url 'post_detail' post.slug %}" method="post">
{% csrf_token %}
<div class="row">
<div class="col-12">
<div class="form-group">
{{ comment_form | crispy }}
</div>
</div>
</div>
<div class="form-group">
<button type="submit" class="button button-contactForm">Post Comment</button>
</div>
</form>
</div>
{% else %}
<div class="alert alert-danger" role="alert">
Please log in to post a comment.
</div>
{% endif %}
this is models.py
class Post(models.Model):
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created at")
updated_at = models.DateTimeField(auto_now=True, verbose_name="Updated at")
published_at = models.DateTimeField(null=True, blank=True, editable=False, verbose_name="Published at")
post_title = models.CharField(max_length=200, verbose_name="Title")
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey('auth.User', verbose_name="Author", on_delete=models.CASCADE)
category = models.ForeignKey(Category, verbose_name="Category", on_delete=models.CASCADE)
tags = TaggableManager()
body = QuillField()
image = StdImageField(upload_to='featured_image/%Y/%m/%d/', variations={'standard':(1170,820),'banner':(1170,530),'single_post':(1170,556),'thumbnail':(500,500)})
image_credit = models.CharField(max_length=200, verbose_name="Image credit:")
status = models.IntegerField(choices=STATUS, default=0)
def get_absolute_url(self):
return reverse('post_detail', args=[self.slug])
def get_readtime(self):
result = readtime.of_text(self.body)
return result.text
class Meta:
verbose_name = "Post"
verbose_name_plural = "Posts"
ordering = ['-created_at']
def publish(self):
self.is_published = True
self.published_at = timezone.now()
self.save()
def __str__(self):
return self.post_title
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
body = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=False)
class Meta:
ordering = ['created_on']
def __str__(self):
return 'Comment "{}" by {}'.format(self.body, self.author.username)
this is forms.py
class CommentForm(forms.ModelForm):
author = forms.CharField(widget=forms.HiddenInput)
class Meta:
model = Comment
fields = ('body', 'user')
Please not that I can post comment over admin page (http://127.0.0.1:8000/admin), but on the front-end doesn't work for some reason.
Any ideas?
You need to redirect() after dealing with POST data, the tip is not specific to Django, its a good web practice in general so:
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
def post_detail(request, slug):
post = get_object_or_404(Post, slug=slug)
related_posts = post.tags.similar_objects()[:3]
comments = post.comments.filter(active=True)
new_comment = None
if request.method == 'POST':
if request.user.is_authenticated:
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.post = post
new_comment.author = request.user
new_comment.save()
return redirect(post.get_absolute_url()) # redirect here
else:
messages.warning(request, 'You need to be logged in to add a comment.')
else:
if request.user.is_authenticated:
comment_form = CommentForm(initial={'author': request.user})
else:
comment_form = CommentForm()
context = {'post': post, 'related_posts': related_posts, 'comments': comments, 'new_comment': new_comment, 'comment_form': comment_form}
return render(request, 'post_detail.html', context)

Field 'id' expected a number but got '9dzlzyftu9k5fi5ta8omk1mxgx1lyvhg'

It works fine until the form is created, but if i enter a value and click the Submit button, the following error code is displayed. The long string of the error code is cart_id. How can I change it? This is a simulated payment system that receives a cart with products and makes a payment.
models.py
class Cart(models.Model):
cart_id = models.CharField(max_length=250, blank=True)
customer = models.ForeignKey(User, on_delete=models.CASCADE)
date_added = models.DateField(auto_now_add=True)
class Meta:
db_table = 'Cart'
ordering=['date_added']
def __str__(self):
return self.cart_id
class Payment(models.Model):
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
card_number = models.IntegerField()
validity = models.IntegerField()
cvc = models.IntegerField()
card_password = models.IntegerField()
def __str__(self):
return '{0} {1}'.format(self.cart, self.card_number)
urls.py
urlpatterns = [
path('add/<int:pk>/', views.add_cart, name='add_cart'),
path('', views.cart_detail, name='cart_detail'),
path('remove/<int:pk>/', views.cart_remove, name='cart_remove'),
path('full_remove/<int:pk>/', views.full_remove, name='full_remove'),
path('payment_charge/', views.payment_charge, name='payment_charge'),
]
view.py
def _cart_id(request):
cart = request.session.session_key
if not cart:
cart = request.session.create()
return cart
def payment_charge(request):
if request.method == "POST":
form = PaymentForm(request.POST, request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.cart_id = _cart_id(request)
post.save()
return redirect('cart:cart_detail')
else:
form = PaymentForm()
context = {
'form' : form
}
return render(request, 'cart/payment_form.html', context)
forms.py
class PaymentForm(forms.ModelForm):
class Meta:
model = Payment
fields = ('card_number','validity','cvc','card_password')
base.html
<div class="mx-auto">
<a href="{% url 'cart:payment_charge' %}" type="button"
class="btn btn-outline-dark my_custom_button">
Continue Shopping
</a>
</div>
payment_form.html
<form action="" method="POST">
{% csrf_token %}
<table>
{{form.as_table}}
</table>
<input type="submit" value="제출">
</form>

Comments on Django Post won't save

I am trying to post comments to a post in Django, but my form is never valid. I have discovered that this is because my request.method is always a GET and not a POST. I would like to allow a user to add a new comment and have it automatically save to the database and display on my post's detail view.
views.py
def add_comment_to_post(request, pk):
print("REQUEST METHOD", request.method)
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
print("POST")
print(request.POST)
form = CommentForm(request.POST)
if form.is_valid():
print("HREE")
comment = form.save(commit=False)
comment.author = request.user
comment.date_posted = timezone.now()
comment.post = post
comment.save()
return redirect('post_detail', pk=comment.post.pk)
else:
print("ELSE")
form = CommentForm()
# Note the indentation (this code will be executed both if NOT POST
# and if form is not valid.
return render(request, 'main/add_comment_to_post.html', {'form': form, 'post':post})
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['author', 'content']
models.py
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
comment_id = models.AutoField(primary_key=True)
author = models.ForeignKey(Profile, on_delete=models.CASCADE)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
# approved_comment = models.BooleanField(default=False)
def approve(self):
self.approved_comment = True
self.save()
class Meta:
ordering = ['date_posted']
def __str__(self):
return 'Comment {} by {}'.format(self.content, self.author.first_name)
class Post(models.Model):
run_id = models.AutoField(primary_key=True)
author = models.ForeignKey(Profile, on_delete=models.CASCADE)
title = models.TextField(max_length=100, blank=False, default="title holder.")
distance = models.FloatField(default=0.0, blank=False)
time = models.IntegerField(default=0, blank=False)
date_posted = models.DateTimeField(default=timezone.now)
location = models.TextField(max_length=100, blank=False, default="")
image = models.TextField(max_length=250, blank=True)
content = models.TextField(max_length=1000, blank=True, default="")
#property
def pace(self):
if self.distance == 0.0:
return 0.0
return round(self.time / self.distance, 2)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
urls.py
urlpatterns = [
# path('', views.home, name="main-home"),
path('', PostListView.as_view(), name="main-home"),
path('admin/', admin.site.urls),
path('register/', views.register, name="register"),
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('about/', views.about, name="main-about"),
path('search/', SearchResultsView.as_view(), name="main-search"),
path('post/<int:pk>/comment/', views.add_comment_to_post, name='add_comment_to_post'),
]
add_comment_to_post.html
{% extends "main/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<h1>New comment</h1>
<form action="" method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">New Comment</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<a class="btn btn-outline-info" type="submit" href="{% url 'post-detail' pk=post.pk %}">Send</a>
</div>
</form>
{% endblock %}
What I have tried
checking out what type of request it is and handling it
searching other similar posts to no avail
changing the views function
Any help would be appreciated.
You didn't define else state for if form.is_valid(): statement. So, if your form has errors, view render your template again.
<div class="form-group">
<a class="btn btn-outline-info" type="submit" href="{% url 'post-detail' pk=post.pk %}">Send</a>
</div>
Your problem is this is a link and not actually a form submit. Try replacing that link with a simple <input type="submit" value="Send">.

How do i limit the numbers if comment to be displayed

I have multiple comments on my homepage, how do i limit the comment to be displayed on a post. Like, i have 10 comments and i want to display only 2 comments.
class Image(models.Model):
imageuploader_profile = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE, null=True, blank=True)
first_upload_image = models.FileField(upload_to ='picmate',null=True, blank=True)
second_upload_image = models.FileField(upload_to ='picmate',null=True, blank=True)
image_caption = models.CharField(max_length=700)
date = models.DateTimeField(auto_now_add=True, null= True)
class Meta:
verbose_name = 'Image'
verbose_name_plural = 'Images'
ordering = ['-date']
def __str__(self):
return self.image_caption
class Comments (models.Model):
comment_post = models.TextField()
author = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE, null=True, blank=True)
commented_image = models.ForeignKey('Image', on_delete=models.CASCADE, related_name='comments')
date = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'Comment'
verbose_name_plural = 'Comments'
ordering = ['-date']
def __str__(self):
return self.author.__str__()
def home(request):
all_images = Image.objects.filter(imageuploader_profile=request.user.id)
users = User.objects.all()
next = request.GET.get('next')
if next: return redirect(next)
context = {
'all_images': all_images,
'users': users,
}
return render(request,'home.html', context,)
#login_required
def comments(request, id):
post = get_object_or_404(Image,id=id)
# current_user = request.user
print(post)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.author = request.user
comment.commented_image = post
comment.save()
return redirect('/')
else:
form = CommentForm()
all_comments = Comments.objects.filter(
author=request.user.id,
commented_image=post,
)
{% for comment in post.comments.all %}
<div class="mb-1" style="padding-bottom:-10px;position:relative;top:-10px">
<div class="truncate card-meta dark-grey-text" style="">
<a href="#" class="username dark-grey-text text-lowercase">
{{ comment.author }}</a> {{ comment.comment_post }}
</div>
</div>
{% endfor %}
You can use the django template tag slice
{% for comment in post.comments.all|slice:":2" %}
{{ comment.author }}
{% endfor %}

How to place default value in to dropdown form field in django

I'm building a post-comment model in one view, one page, something like facebook. I have two forms in my home.html and view.py: new post and new comment. In each post container, there is a new comment form.
I have a problem because I don't know how to relate comment to post - specifically how to pass post.id to my comment form.
Is it possible to pass my {{ post.id }} to my {{newCommentForm.field }}? That each comment has a default value of post's id?
My home.html:
{% for post in posts %}
<div class="container">
<a class="user" href="#">{{ post.author }}</a>, {{ post.date_posted }}
<img src="{{ post.author.profile.image.url }}" alt="{{ post.author }}"style="width:100%;">
<p>{{ post.content }}</p>
<form METHOD="POST" class="new_post">
{% csrf_token %}
{{ newCommentForm.content }}
{{ newCommentForm.post }}
<button type="submit" name="newCommentSubmit">Add</button>
</form>
</div>
{% endfor %}
models.py
class Post(models.Model):
content = models.TextField(max_length=1000)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.content
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField(max_length=500)
date = models.DateTimeField(default=timezone.now)
def add_coment(self):
self.date = timezone.now()
self.save()
def __str__(self):
return self.content
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return f'{self.user.username}'
views.py
#login_required()
def home(request):
newPostForm = newPost()
newCommentForm = newComment()
if request.method == 'POST':
if 'newPostSubmit' in request.POST:
newPostForm = newPost(request.POST, prefix='newpost')
if newPostForm.is_valid():
instance = newPostForm.save(commit=False)
instance.author = request.user
instance.date_posted = timezone.now()
instance.save()
newCommentForm = newComment(prefix='newcomment')
elif 'newCommentSubmit' in request.POST:
newCommentForm = newComment(request.POST, prefix='newcomment')
if newCommentForm.is_valid():
instance = newCommentForm.save(commit=False)
instance.author = request.user
instance.date_posted = timezone.now()
instance.save()
newPostForm = newPost(prefix='newpost')
else:
newPostForm = newPost(prefix='newpost')
newCommentForm = newComment(prefix='newcomment')
context = {
'newPostForm': newPostForm,
'newCommentForm': newCommentForm,
'posts': Post.objects.all().order_by('-date_posted'),
'comments': Comment.objects.all()
}
return render(request, 'blog/home.html', context)
def about(request):
return render(request, 'blog/about.html')
My model is working now, comments are added, but I need to choose my post (post.id) manually from the default dropdown field witch all posts.
Add your post to comment like this:
if newCommentForm.is_valid():
instance = newCommentForm.save(commit=False)
instance.author = request.user
instance,=.post = request.post
instance.date_posted = timezone.now()
instance.save()
And send post in request!

Categories

Resources