Django MPTT, can't get parent_id for threaded comments reply - mysql

My Problems are as follows:
Im relatively new to Django. so sorry for this mess.
I've tried to implement threaded comments to my blog via MPTT. But when i pressing the 'Reply' Button django throws me a Type Error
Normal parent comments working correctly
When i just create a comment with via the admin site, i can create parent comments and child comments and they will be indented just as expected in the main Application too...
my Database is mySQL.
The Error:
in _calculate_inter_tree_move_values
space_target = target_right - 1
~~~~~~~~~~~~~^~~
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'
my models.py:
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from mptt.models import MPTTModel, TreeForeignKey
STATUS = (
(0,"Draft"),
(1,"Publish")
)
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(User, on_delete= models.CASCADE, related_name='blog_posts')
updated_on = models.DateTimeField(auto_now=True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post_detail',args=[self.slug])
class Comment(MPTTModel):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=False)
parent=TreeForeignKey('self', null=True, blank=True, on_delete=models.CASCADE, related_name='children')
class MPTTMeta:
order_insertion_by = ['created_on',]
def __str__(self):
return 'Comment {} by {}'.format(self.body, self.name)
#just for the threaded comments
def get_comments(self):
return Comment.objects.filter(parent=self).filter(active=True)
views.py:
from django.shortcuts import render, get_object_or_404, redirect, HttpResponseRedirect
from django.views import generic
#from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
#from django.template import loader
from .models import Post, Comment
from .forms import CommentForm
class PostList(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'index.html'
paginate_by = 3
#class PostDetail(generic.DetailView):
# model = Post
# template_name = 'post_detail.html'
class AboutMe(generic.TemplateView):
template_name = 'about_me.html'
class Contact(generic.TemplateView):
template_name = 'contact.html'
class Impressum(generic.TemplateView):
template_name = 'impressum.html'
class StaticContent(generic.TemplateView):
template_name = 'static_html_content.html'
class SideBar(generic.TemplateView):
template_name = 'sidebar.html'
#class PostDetail(generic.DetailView):
# model = Post
# context_object_name = "post"
# template_name = "post_detail.hhml"
def post_detail(request, post):
template_name = 'post_detail.html'
post = get_object_or_404(Post, slug=post, status=1)
comments = post.comments.filter(active=True)
new_comment = None
#comment posted
if request.method == 'POST':
comment_form = CommentForm(request.POST)
if comment_form.is_valid():
# Create comment object but dont save to database yet
new_comment = comment_form.save(commit=False)
# Assign thecurrent post to the comment
new_comment.post = post
#save the comment to the database
new_comment.save()
#redirect to the same page and focus on that comment
return HttpResponseRedirect('/' + post.slug)
#return redirect(post.get_absolute_url()+'#'+str(new_comment.id))
else:
comment_form = CommentForm()
return render(request, template_name, {'post': post, 'comments': comments, 'new_comment': new_comment, 'comment_form': comment_form})
def reply_page(request):
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
post_id = request.POST.get('post_id')
parent_id = request.POST.get('parent')
post_url = request.POST.get('post_url')
print(post_id)
print(parent_id)
print(post_url)
print('was here reply!')
reply = form.save(commit=False)
reply.post = Post(id=post_id)
reply.parent = Comment(id=parent_id)
reply.save()
return redirect(post_url+'#'+str(reply.id))
return redirect('/')
forms.py:
from .models import Comment
from django import forms
from mptt.forms import TreeNodeChoiceField
class CommentForm(forms.ModelForm):
parent = TreeNodeChoiceField(queryset=Comment.objects.all())
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['parent'].widget.attrs.update(
{'class': 'd-none'})
self.fields['parent'].label = ''
self.fields['parent'].required = False
class Meta():
model = Comment
fields = ('name', 'parent', 'email', 'body')
widgets = {
'name': forms.TextInput(attrs={'class': 'col-sm-12'}),
'email': forms.TextInput(attrs={'class': 'col-sm-12'}),
'body': forms.Textarea(attrs={'class': 'form-control'}),
}
def save(self, *args, **kwargs):
Comment.objects.rebuild()
return super(CommentForm, self).save(*args, **kwargs)
post_details.html:
{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% load mptt_tags%}
{% block content %}
<header class="masthead" style="height: 13.9em;">
<!-- javascript add -->
<script src="{% static 'js/main.js'%}"></script>
</header>
<div class="container">
<div class="row">
<div class="col-md-8 card mb-4 mt-3 left top">
<div class="card-body">
<h1>{% block title %} {{ post.title }} {% endblock title %}</h1>
<p class=" text-muted">{{ post.author }} | {{ post.created_on }}</p>
<p class="card-text ">{{ post.content | safe }}</p><br>
<a href="{% url 'home' %}" style="float: right;"
class="btn btn-danger">Go Back</a><br><br>
</div>
</div>
{% block sidebar %} {% include 'sidebar.html' %} {% endblock sidebar %}
</div>
<div class="row">
<div class="col-md-8 card mb-4 mt-3 left top">
<div class="card-body">
<h3>Add Comment</h3>
<form method="POST" action="">
{% csrf_token %}
{{ comment_form | crispy }}
<button type="submit" class="btn btn-danger">Comment</button>
</form>
<!-- count comments section-->
{% with comments.count as total_comments %}
<h3 class="mt-5">
{{ total_comments }} comment{{ total_comments|pluralize }}
</h3>
{% endwith %}
<!-- show comment section -->
<div>
<ul style="list-style-type: none;">
{% recursetree comments %}
<li>
<!-- parent body -->
<div>
<div class="border p-4 rounded">
<h4>{{ node.name }}</h4>
<small class="text-muted">On {{ node.created_on }}</small>
<h5>{{ node.body }}</h5> <br>
<button class="btn btn-danger btn-sm" onclick="handleReply({{node.id}})">Reply</button>
<div id="reply-form-container-{{node.id}}" style="display:none">
<form method="POST" action="{% url 'reply' %}" class="mt-3">
{% csrf_token %}
<input type="hidden" name="post_id" value="{{post.id}}">
<input type="hidden" name="parent" value="{{comment.id}}">
<input type="hidden" name="post_url" value="{{post.get_absolute_url}}">
{{comment_form|crispy}}
<div>
<button type="button" onclick="handleCancel({{node.id}})" class="btn btn-danger border btn-sm">Cancel</button>
<button type="submit" class="btn btn-danger btn-sm">Submit</button>
</div>
</form>
</div>
</div>
</div>
<br>
<!-- if children -->
{% if not node.is_leaf_node %}
<ul ul style="list-style-type: none;">
<div class="children pl-2 pl-md-5">
{{ children }}
</div>
</ul>
{% endif %}
</li>
{% endrecursetree%}
</ul>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
I've tried to change the values in the formfields of the post_details.html to node.parent.id
but nothing seems to happen.
Also i tried to change the parent_id's datatype to see if there something happens.
but because it runs in this Opperant-Error i think it could be an issue with saving to the mySQL Database...

Ok... Now i have have found the answer.
In views.py i've edited these lines:
parent_id = request.POST.get('parent')
and replace 'parent' with 'commend_id'
parent_id = request.POST.get('comment_id')
In post_detail.html i have changed the form:
<input type="hidden" name="parent" value="{{comment.id}}">
to...
<input type="hidden" name="comment_id" value="{{node.id}}">
Now it runs as expected! YAY!

Related

ValueError at /plants/plants/ too many values to unpack (expected 2) when using django_filters

Hej!
I'm having trouble with my django filter.
When I put {{myFilter}} in the template I only get an ObjectNumber and when I put {{myFilter.form}} I get the error:
ValueError at /plants/plants/
too many values to unpack (expected 2)
Does anyone have an idea what's going on?
# views.py
def plants_view(request):
plants = Plant.objects.all()
myFilter = PlantFilter(plants)
context = {"plants": plants, "myFilter": myFilter}
return render(request, 'plants/search_table.html', context)
# filters.py
class PlantFilter(django_filters.FilterSet):
class Meta:
model = Plant
fields = ['name',]
it doesn't matter if I use fields = [ ] or fields = '__all__' .
template.html
{% extends "landing/base.html" %}
{% load static %}
{% load i18n %}
{% load admin_urls %}
{% block page-title %} {%translate "View Plants" %} {% endblock %}
{% block head %}
<link href="{% static 'landing/vendor/tabulator/dist/css/tabulator.min.css' %}" rel="stylesheet">
<link href="{% static 'landing/vendor/tabulator/dist/css/bootstrap/tabulator_bootstrap4.min.css' %}" rel="stylesheet">
{% endblock %}
{% block content %}
<br>
<div class="row">
<div class="col">
<div class="card card-body">
<form method="get">
{{myFilter.form}}
<button class="btn-primary" type="submit">Search</button>
</form>
</div>
</div>
</div>
</br>
# models.py
class Plant(models.Model):
name = models.CharField(
max_length=200
)
def __str__(self):
return f"{self.name}"
def serialize(self):
return {
"Name": self.name
}
Did you follow the documentation on this page ?
views.py
def plants_view(request):
plants = Plant.objects.all()
myFilter = PlantFilter(request.GET, queryset=plants)
context = {"plants": plants, "myFilter": myFilter}
return render(request, 'plants/search_table.html', context)
template.html
<form method="get">
{{ myFilter.form.as_p }}
<button class="btn-primary" type="submit">Search</button>
</form>

Change the name of output of form-variables Django

I'm following this Django guide for creating a "recipe" home-page, and I'm completly new to Django and html.
I am using the CreateView class for creating a new class of the instance opskrift
class opskrift(models.Model):
title = models.CharField(max_length=100)
algorithm = models.TextField()
time_taken = models.CharField(max_length=10)
prep_time = models.CharField(max_length=10)
n_persons = models.CharField(max_length=5)
def __str__(self):
return self.title
with the view
class OpskriftCreateView(CreateView):
model = opskrift
fields = ["title","algorithm","time_taken","prep_time","n_persons"]
The problem is, that it displays the variable names i.e n_persons, prep_time on the homepage etc. but I would like to make it Number of persons, Preperation time.
Is there a way to do so using the template below
{% extends "indkoeb/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="OPSKRIFT">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">New</legend>
{{form|cripsy}}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Save</button>
</div>
</form>
</div>
{% endblock content %}
class opskrift(models.Model):
title = models.CharField(max_length=100)
algorithm = models.TextField()
time_taken = models.CharField(max_length=10)
prep_time = models.CharField(max_length=10,verbose_name="Preperation time")
n_persons = models.CharField(max_length=5,verbose_name='Number of persons')

Django from is not being past into html template

As in the question title "{{form}}" from is not being loaded into html template I checked by previous projects I have almost the same code, differences are required fields, naming etc. mechanic is the same.
In those projects registration function works perfectly here it's not even throwing an error just don't display anything.
No wonder what might be wrong in here.
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
class RegistrationForm(UserCreationForm):
email = forms.EmailField(max_length=60, help_text="Required field")
class Meta:
model = Profile
fields = ["email", "username", "password", "password2", "calories_plan", "diet_type"]
views.py
def registration_view(request):
context = {}
if request.POST:
form = RegistrationForm(request.POST)
if form.is_valid():
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
new_account = authenticate(email=email, password=password)
login(request, new_account)
else:
context["registration_form"] = form
else:
form = RegistrationForm()
context["registration_form"] = form
return render(request, "Account/registration.html", context)
html template
{% extends 'main.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>Join today
{{ form }}
</legend>
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Sign Up</button>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">
Already have an account?
<a href="#" class="ml-2">
Log In
</a>
</small>
</div>
</div>
{% endblock %}
And how it looks in browser.
You're passing 'registration_form' to the context, but in template you are calling {{ form }}.
Replace:
{{ form }}
with:
{{ registration_form }}

i get an error. django.urls.exceptions.NoReverseMatch

l am started to learn Django few days ago, and I get this error:
django.urls.exceptions.NoReverseMatch: Reverse for 'create_order' with no arguments not found. 1 pattern(s) tried: ['create_order/(?P[^/]+)/$']*
urls.py
path('create_order/<str:pk>/', views.createOrder, name='create_order'),
views.py
def createOrder(request, pk):
customer = Customer.objects.get(id=pk)
form = OrderForm(initial={'customer': customer})
if request.method == 'POST':
# print('Printing:', request.POST)
form = OrderForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
context = {
'form': form
}
return render(request, 'accounts/order_form.html', context)
order_form.html
{% extends 'accounts/main.html' %}
{% load static %}
{% block content %}
<br>
<div class="row">
<div class="col-12 col-md-6">
<div class="card card-body">
<form action="" method="post">
{% csrf_token %}
{{form}}
<input class="btn btn-sm btn-danger" type="submit" value="Conform">
</form>
</div>
</div>
</div>
{% endblock %}
customer.html
<div class="row">
<div class="col-md">
<div class="card card-body">
<h5>Customer:</h5>
<hr>
<a class="btn btn-outline-info btn-sm btn-block" href="">Update Customer</a>
<a class="btn btn-outline-info btn-sm btn-block" href="{% url 'create_order' customer.id %}">Place Order</a>
</div>
</div>
As the error said, it tried with empty argument, means there was no customer value available in context. So you need to send the customer value through context, like this:
context = {
'customer' : customer,
'form': form
}
I was also following this tutorial from youtube(dennis ivy) and got the same error,
don't know what is the problem but just replace the file urls.py from github with the same context and it's not showing that error,.
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name="home"),
path('products/', views.products, name='products'),
path('customer/<str:pk_test>/', views.customer, name="customer"),
path('create_order/<str:pk>/', views.createOrder, name="create_order"),
path('update_order/<str:pk>/', views.updateOrder, name="update_order"),
path('delete_order/<str:pk>/', views.deleteOrder, name="delete_order"),
]
views.py
from django.forms import inlineformset_factory
def createOrder(request, pk):
OrderFormSet = inlineformset_factory(Customer, Order, fields=('product', 'status'), extra=10 )
customer = Customer.objects.get(id=pk)
formset = OrderFormSet(queryset=Order.objects.none(),instance=customer)
#form = OrderForm(initial={'customer':customer})
if request.method == 'POST':
#print('Printing POST:', request.POST)
#form = OrderForm(request.POST)
formset = OrderFormSet(request.POST, instance=customer)
if formset.is_valid():
formset.save()
return redirect('/')
context = {'form':formset}
return render(request, 'accounts/order_form.html', context)
order_form.html
{% extends 'accounts/main.html' %}
{% load static %}
{% block content %}
<div class="row">
<div class="col-md-6">
<div class="card card-body">
<form action="" method="POST">
{% csrf_token %}
{{ form.management_form }}
{% for field in form %}
{{field}}
<hr>
{% endfor %}
<input type="submit" name="Submit">
</form>
</div>
</div>
</div>
{% endblock %}
again I don't know why it was showing this error and where was the problem but just relapced it with the same code from github and it worked..if someone know how it worked , that will be really helpful in near future. thanks to all regards Haris Ahmad

Language choice affects text overflow in html(bootstrap) (Django)

I'm using bootstrap to implement my post detail page.
It works well and fit perfectly into tho format when using Korean.
But, if I wrote english contents, it overflow the format.
What's wrong with it?
Here is the code :
models.py
from django.db import models
from django.core.urlresolvers import reverse
from django.conf import settings
def upload_location(instance, file_name):
return "{}/{}".format(instance.author.username, file_name)
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
content = models.TextField()
image = models.ImageField(upload_to=upload_location, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ('-created_at',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse(
"posts:detail",
kwargs={
"pk": self.id,
}
)
def get_image_url(self):
if self.image:
return self.image.url
return "http://placehold.it/300x200"
post_detail.html
{% extends 'chacha_dabang/skeleton/base.html' %}
{% load pipeline %}
{% block content %}
<div class="container">
<section class="post-content-section">
<h2> {{ post.title }} </h2>
<h5 style="text-align: right;"> {{ post.created_at }} </h5>
<hr class="thin">
<img src="{{ post.get_image_url }}" alt="image">
<p> {{ post.content }} </p>
</section>
</br>
<hr class="thin">
</br>
<section id="comment-section" data-post-id={{ post.pk }}>
<h3> 댓 글 (<span id="comment-count"></span>)</h3>
<ul>
</ul>
<form method="POST" action="">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
</section>
</div>
{% endblock %}
{% block custom_js %}
{% javascript "comments" %}
{% javascript "message" %}
{% endblock %}