Error When submit comment for the second post in Django - django

I creating a blog in this blog feed there are posts and for each post there are comments, So my problem when I submit a comment for the first post is submitting successfully but when I try to submit a comment for the second post or third it doesn't submit
My comments Form
class PostCommentForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
class Meta:
model = PostCommentIDF
fields = {'post', 'content'}
widgets = {
'content': forms.Textarea(attrs={'class': 'rounded-0 form-control', 'rows': '1', 'placeholder': 'Comment', 'required': 'True', })
}
def save(self, *args, **kwargs):
PostCommentIDF.objects.rebuild()
return super(PostCommentForm, self).save(*args, **kwargs)
My comments view
#login_required
def add_comment_post(request):
if request.method == 'POST':
if request.POST.get('action') == 'delete':
id = request.POST.get('nodeid')
c = PostCommentIDF.objects.get(id=id)
c.delete()
return JsonResponse({'remove': id})
else:
comment_form = PostCommentForm(request.POST )
if comment_form.is_valid():
user_comment = comment_form.save(commit=False)
user_comment.author = request.user
user_comment.save()
result = comment_form.cleaned_data.get('content')
user = request.user.username
return JsonResponse({'result': result, 'user': user})
return JsonResponse({'result': "No action took"})
My comment form in home page template
<form id="Postcommentform" class="Postcommentform" method="post" style="width: 100%;">
{% load mptt_tags %}
{% csrf_token %}
<select class="d-none" name="post" id="id_post">
<option value="{{ video.id }}" selected="{{ video.id }}"></option>
</select>
<div class="d-flex">
<label class="small font-weight-bold">{{ comments.parent.label }}</label>
{{ comments.parent }}
{{comments.content}}
<button value="Postcommentform" id="Postnewcomment" type="submit" style="color: white; border-radius: 0;" class="d-flex justify-content-end btn btn-primary">Post</button>
</div>
</form>
Update
My comment Model
class PostCommentIDF(MPTTModel):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
author = models.ForeignKey(Account, on_delete=models.CASCADE)
content = models.TextField()
publish = models.DateTimeField(auto_now_add=True)
Post Model
class Post(models.Model):
author = models.ForeignKey(Account, on_delete=models.CASCADE)
article = models.TextField(null=True, blank=True)
photo_article = models.ImageField(max_length=255, upload_to=get_poster_filepath)
created_date = models.DateTimeField(auto_now_add=True)
I use Ajax for submet the comment, When I submit comment for first post this shows {result: "comment", user: "user1"} but when I submit comment for any diffrent post except the first one this shows {result: "No action took"}
How I can let the user submit comment to any post not just for the first one
Edit
myCommentForm = document.getElementById("Postcommentform")
$(document).on('click', '#Postnewcomment, #Postnewcommentinner', function (e) {
e.preventDefault();
var button = $(this).attr("value");
var placement = "Postcommentform"
if (button == "Postnewcommentform") {
var placement = "becomm"
}
$.ajax({
type: 'POST',
url: '{% url "video:addcomment_post" %}',
data: $("#" + button).serialize(),
cache: false,
success: function (json) {
console.log(json);
$('<div id="" class=" p-2" style=""> \
<div class="d-flex bd-highlight mb-3">\
<div class="p-2 bd-highlight"><img src="{{request.user.profile_image.url}}" alt="" class="rounded-circle bd-highlight" width="30" height="30"> ' + json['user'] + '</div> <div class="ml-auto p-2 bd-highlight">Posted: Just now!</div> \
</div>\
<div>' + json['result'] + '</div> \
</div>'
).insertAfter('#Boo');
document.getElementById("Postcommentform").reset();
},
error: function (xhr, errmsg, err) {
}
});
})
function myFunction(id) {
if (document.contains(document.getElementById("Postnewcommentform"))) {
document.getElementById("Postnewcommentform").remove();
}
var a = document.getElementById(id);
a.insertAdjacentHTML('afterend',
'<form id="Postnewcommentform" class="Postnewcommentform py-2" method="post"> \
{% csrf_token %}\
<div class="d-flex justify-content-between"><h2>Reply:</h2><div><button type="button" class="btn btn-outline-secondary" onclick="formExit()"">Close</button></div></div> \
<select name="parent" class="d-none" id="id_parent"> \
<option value="' + id + '" selected="' + id + '"></option> \
</select> \
<label id="id_content" required="" for="id_content">Content:</label> \
<textarea name="content" cols="40" rows="5" class="form-control" required="" id="id_content"></textarea> \
{% csrf_token %} \
<button type="submit" value="Postnewcommentform" id="Postnewcommentinner" class="btn btn-primary btn-lg btn-block">Submit</button> \
</form>');
}

Related

Django: how to make POST request with form data?

I'm learning Django and am running into an issue posting a piece of data to the database. Here's my code:
urls.py
urlpatterns = [
path("", views.index, name="index"),
...
path("listing/<int:listing_id>", views.display_listing, name="listing")
]
Models.py
class Bid(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='usr_bids')
price = models.DecimalField(max_digits=5, decimal_places=2)
class Listing(models.Model):
title = models.CharField(max_length=50)
bids = models.ManyToManyField(Bid, blank=True, related_name='bids')
price = models.DecimalField(max_digits=7, decimal_places=2)
closed = models.BooleanField(default=False)
Forms.py
class BidForm(ModelForm):
class Meta:
model = Bid
fields = ['price']
views.py
def display_listing(request, listing_id):
listing = Listing.objects.get(pk=listing_id)
if not request.user.is_authenticated:
return HttpResponseRedirect(reverse('login'))
if request.method == "POST":
user = User.objects.get(username=request.user)
if request.POST.get("button") == "Watchlist":
if not user.watchlist.filter(listing=listing):
watchlist = Watchlist()
watchlist.user = user
watchlist.listing = listing
watchlist.save()
else:
user.watchlist.filter(listing=listing).delete()
return HttpResponseRedirect(reverse('listing', args=(listing.id, )))
if not listing.closed:
if request.POST.get("button") == "Close":
listing.closed = True
listing.save()
else:
price = float(request.POST["price"])
bids = listing.bids.all()
if user.username != listing.creator.username:
if price <= listing.price:
return render(request, 'auctions/listing.html',{
'listing': listing,
'form': BidForm(),
'message': 'Increase your bid.'
})
form = BidForm(request.POST)
if form.is_valid():
bid = form.save(commit=False)
bid.user = user
bid.save()
listing.bids.add(bid)
listing.price = price
listing.save()
else:
return render(request, 'auctions/listing.html', {
'form': form
})
return HttpResponseRedirect(reverse('listing', args=(listing.id, )))
else:
return render(request, 'auctions/listing.html', {
'listing': listing,
'form': BidForm(),
'comments': listing.comments.all()
})
auction/listings.html
<div>
<form action="{% url 'listing' listing.id %}" method="POST">
{% csrf_token %}
<div class="form-group">
<label for="bid">{{ listing.bids.count }} bid(s) so far. You have the best bid!.</label>
</div>
<div class="form-group">
{{ form }}
</div>
<div class="form-group">
<input type="submit" name="button" class="btn btn-primary" value="Send Bid">
</div>
</form>
</div>
I populate a value (e.g. 300) in the price field. Then, I click the "Send Bid" button. Unfortunately, nothing happens.
Does anyone see why I'm unable to save a price to the database? Thanks in advance for taking a look!
At a first glance, you should rather have something like:
<form method="post">
{% csrf_token %}
{{ form }}
<input type="submit" name="button" class="btn btn-primary" value="Send Bid">
</form>
in your template.

when user reply to a comment it is showing time of comment. It should show actual time. How can I fix?

I am learning django. I am working on a blog. When user reply to a comment it is showing time of its parent comment. It should show actual time of reply. I attached a picture with this post.Please have a look , you will better understand my question. How can I fix? I tried but all in vain. may be it is a silly mistake from me or i am not getting it. Thanks in advance
view.py
def blogPost(request, slug):
post = Post.objects.filter(slug=slug).first()
comments = BlogComment.objects.filter(post=post, parent=None)
replies = BlogComment.objects.filter(post=post).exclude(parent=None)
replyDict = {}
for reply in replies:
if reply.parent.sno not in replyDict.keys():
replyDict[reply.parent.sno] = [reply]
else:
replyDict[reply.parent.sno].append(reply)
context = {'post':post, 'comments':comments, 'user': request.user, 'replyDict': replyDict}
return render(request, 'blog/blogPost.html',context)
def postComments(request):
if request.method == 'POST':
comment = request.POST.get('comment')
user = request.user
postSno = request.POST.get('postSno')
post = Post.objects.get(sno=postSno)
parentSno = request.POST.get('parentSno')
if parentSno == "":
comments = BlogComment(comment=comment, user=user, post=post)
comments.save()
messages.success(request, 'Your Comment has been posted Successfully')
else:
parent = BlogComment.objects.get(sno=parentSno)
comments = BlogComment(comment=comment, user=user, post=post, parent=parent)
comments.save()
messages.success(request, 'Your reply has been posted Successfully')
return redirect(f"/blog/{post.slug}")
models.py
class Post(models.Model):
sno = models.AutoField(primary_key=True)
title = models.CharField(max_length=200)
content = models.TextField(max_length=10000)
author = models.CharField(max_length=20)
region = models.CharField(max_length=20)
slug = models.CharField(max_length=50, default="")
timestamp = models.DateTimeField(blank=True)
thumbnail = models.ImageField(upload_to="images", default="")
def __str__(self):
return self.title + 'by' + self.author
class BlogComment(models.Model):
sno = models.AutoField(primary_key=True)
comment = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True) #it is pointing the value of blogcomment so we use 'self'
timestamp = models.DateTimeField(default=now)
replytimestamp = models.DateTimeField(default=now)
def __str__(self):
return self.comment[0:10] + "..." + "by " + self.user.username
blogPost.html
{% for comment in comments %}
<div class="row border border-dark mx-0 my-3">
<div class="col-md-1"><img src="/media/images/usr.png" height="55px" width="55px"></div>
<div class="col-md-11"><b> {{comment.user.username}} </b>
<span class="badge badge-secondary">{{comment.timestamp | naturaltime}}</span>
<!--this will show time in 2 hours ago or x hour ago like-->
<div>
<p class="font-italic">{{comment.comment}}</p>
</div>
<div class="reply mx-0">
<p>
{% if user.is_authenticated %}
<button class="btn btn-primary btn-sm" type="button" data-toggle="collapse"
data-target="#replyBox{{comment.sno}}" aria-expanded="false" aria-controls="collapseExample">
reply
</button>
</p>
<div class="collapse" id="replyBox{{comment.sno}}">
<div class="card card-body mb-2">
<form action="/blog/postComments" method="POST">{% csrf_token %}
<div class="form-group">
<label for="comment">Post a Reply</label>
<input type="text" class="form-control" id="comment" name="comment"
placeholder="Write a reply Here">
<input type="hidden" name="parentSno" value="{{comment.sno}}">
</div>
<input type="hidden" name="postSno" value="{{post.sno}}">
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
{% endif %}
<div class="replies my-2">
{% for reply in replyDict|get_val:comment.sno %}
<!-- this will return replies associated with comment.sno in the replyDict[] -->
<div class="row my-2">
<div class="col-md-1"><img src="/media/images/usr.png" height="35px" width="35px"></div>
<div class="col-md-11">
<b> {{comment.user.username}} </b><span
class="badge badge-secondary">{{comment.timestamp | naturaltime}}</span>
<div>{{reply.comment}}</div>
</div>
<br>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
commentand reply pictures

How to order messages based on the time its send like in normal chats?

Hey guys I am having trouble with ordering the messages based on the timestamp like in normal chats. How to do it? can anyone give me a proper solution? I have updated the question with the model manager I use.
This is the model.
class Chat(models.Model):
first_user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='first_user_chat', null=True)
second_user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='second_user_chat', null=True)
timestamp = models.DateTimeField(auto_now_add=True)
class ChatMessage(models.Model):
chat = models.ForeignKey(Chat, blank=True, null=True, on_delete=models.SET_NULL)
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='sender', on_delete=models.CASCADE)
message = models.TextField()
# read = models.BooleanField(blank=False, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
views
class ChatView(LoginRequiredMixin, FormMixin, DetailView):
template_name = 'messenger/chat.html'
form_class = ComposeForm
success_url = './'
def get_queryset(self):
return Chat.objects.by_user(self.request.user).order_by('-timestamp')
def get_object(self):
other_username = self.kwargs.get("username")
obj, created = Chat.objects.get_or_new(self.request.user, other_username)
if obj == None:
raise Http404
return obj
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['messages'] = ChatMessage.objects.filter(user=self.request.user).order_by('-timestamp')
context['form'] = self.get_form()
return context
def post(self, request, *args, **kwargs):
if not self.request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
chat = self.get_object()
user = self.request.user
message = form.cleaned_data.get("message")
ChatMessage.objects.create(user=user, chat=chat, message=message)
return super().form_valid(form)
This is the template I use to render this. This also has all the javascript codes.
{% load static %}
{% static "channels/js/websocketbridge.js" %}
{% block content %}
<a class="btn btn-light" href="{% url 'messenger:inboxview' %}">Back to Inbox</a>
<div class="msg_history offset-md-1" id="chat-items">
{% for chat in object.chatmessage_set.all %}
{% if chat.user == user %}
<div class="outgoing_msg">
<div class="outgoing_msg_img">
<img class="rounded-circle" style="height: 30px; width: 30px; margin-right: 16px;"
src="{{ chat.user.profile.profile_pic.url }}">
</div>
<div class="sent_msg">
<p>
<div>
{{ chat.message }}
</div>
<small><span style="font-size: 6" class="time_date"> {{ chat.timestamp }}</span></small>
</p>
</div>
</div>
{% else %}
<div class="incoming_msg offset-md-8">
<div class="incoming_msg_img">
<img class="rounded-circle offset-md-7" style="height: 30px; width: 30px; margin-right: 16px;" src="{{ chat.user.profile.profile_pic.url }}">
</div>
<div class="received_msg">
<div class="received_withd_msg">
<p>
<div>
{{ chat.message }}
</div>
<small><span style="font-size: 6" class="time_date"> {{ chat.timestamp }}</span></small>
</p>
</div>
</div>
</div>
{% endif %}
{% endfor %}
</div>
<div class="type_msg offset-md-1">
<div class="input_msg_write">
<!-- text input / write message form -->
<form id='form' method='POST'>
{% csrf_token %}
<input type='hidden' id='myUsername' value='{{ user.username }}' />
{{ form.as_p }}
<center><button type="submit" class='btn btn-success disabled' value="Send">Send</button></center>
</form>
</div>
</div>
{% block javascript %}
<script src='https://cdnjs.cloudflare.com/ajax/libs/reconnecting-websocket/1.0.0/reconnecting-websocket.js'></script>
<script type="text/javascript">
// websocket scripts - client side*
console.log(window.location)
var loc = window.location
var formData = $("#form")
var msgInput = $("#id_message")
var chatHolder = $('#chat-items')
var me = $('#myUsername').val()
var wsStart = 'ws://'
if (loc.protocol == 'https:') {
wsStart = 'wss://'
}
var endpoint = wsStart + loc.host + loc.pathname
var socket = new ReconnectingWebSocket(endpoint)
// below is the message I am receiving
socket.onmessage = function(e) {
console.log("message", e)
var data = JSON.parse(event.data);
// Find the notification icon/button/whatever and show a red dot, add the notification_id to element as id or data attribute.
var chatDataMsg = JSON.parse(e.data)
chatHolder.append('<li>' + chatDataMsg.message + ' from ' + ' - ' + chatDataMsg.username + '</li>')
}
// below is the message I am sending
socket.onopen = function(e) {
console.log("open", e)
formData.submit(function(event) {
event.preventDefault()
var msgText = msgInput.val()
var finalData = {
'message': msgText
}
socket.send(JSON.stringify(finalData))
formData[0].reset()
})
}
socket.onerror = function(e) {
console.log("error", e)
}
socket.onclose = function(e) {
console.log("close", e)
}
</script>
<script>
document.addEventListener('DOMContentLoaded', function() {
const webSocketBridge = new channels.WebSocketBridge();
webSocketBridge.connect('/ws');
webSocketBridge.listen(function(action, stream) {
console.log("RESPONSE:", action);
})
document.ws = webSocketBridge; /* for debugging */
})
</script>
{% endblock %}
{% endblock %}
Please do let me know how to properly do it.
Thank you!
please try this:
in models.py add class Meta:
class ChatMessage(models.Model):
chat = models.ForeignKey(Chat, blank=True, null=True, on_delete=models.SET_NULL)
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='sender', on_delete=models.CASCADE)
message = models.TextField()
# read = models.BooleanField(blank=False, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["-timestamp"]
if this works it is because in the template you are iterating like this: {% for chat in object.chatmessage_set.all %} is not ordered.
Another thing that i see is that you are not using this: context['messages'] = ChatMessage.objects.filter(user=self.request.user).order_by('-timestamp') but i would change with something like this:
chat = self.get_object()
context["messages"] = chat.chatmessage_set.all().order_by("-timestamp")
and use that in template to iterate instead of object.chatmessage_set.all

django - pass multiple instance into form and save it in DB

I have a view where they are multiple posts and I want when the user like one of them, the form take the user_id and the post_id and save it into the DB. This is th Models.py:
class LikePost(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Posts, on_delete=models.CASCADE)
def __str__(self):
return '{} - {}'.format(self.user.username, self.post.name)
Forms.py:
class LikePostForm(forms.ModelForm):
class Meta:
model = LikedShops
fields = ['user', 'post']
widgets = {
'user': forms.HiddenInput(),
'post': forms.HiddenInput()
}
Views.py:
def posts(request):
if request.method == 'POST':
form = LikePostForm(request.POST)
if form.is_valid():
u = form.save(commit=False)
u.user = request.user
u.save()
return redirect('posts')
else:
form = LikePostForm()
context = {
'posts': Posts.objects.all(),
'form': form
}
return render(request, "posts.html", context)
and this the form in posts.html:
{% for post in posts %}
<div class="col-md-3">
<article class="card mb-4">
<header class="card-header">
<h4 class="card-title"><b>{{ post.name }}</b></h4>
</header>
<img style="width: 100%; height: 150px;" class="card-img" src="{{ post.image.url }}"/>
<div class="card-body">
<p class="card-text">{{ post.description }}</p>
</div>
{% if user.is_authenticated %}
<div class="card-footer">
<div class="row">
<div class="col">
<form action="/posts/" method="post">
{% csrf_token %}
{{ l_form|crispy }}
<button type="submit" class="btn btn-outline-success">Like</button>
</form>
</div>
</div>
</div>
{% endif %}
</article><!-- /.card -->
</div>
{% endfor %}
This is my edit, I did what you said, I made changes to:
forms.py:
class Meta:
model = Liked
fields = ['user', 'post']
widgets = {
'user': forms.HiddenInput(),
'post': forms.HiddenInput()
}
posts.html:
<form action="/posts/" method="post">
{% csrf_token %}
<input type="hidden" name="post" value="{{ post.pk }}">
{{ l_form|crispy }}
<button type="submit" class="btn btn-outline-success">Like</button>
</form>
views.py:
def posts(request):
if request.method == 'POST':
l_form = LikePostForm(request.POST, instance=request.user.profile)
if l_form.is_valid():
u = l_form.save(commit=False)
u.post = Posts.objects.filter(pk=l_form.cleaned_data.get('post')).first()
u.save()
messages.success(request, f"Form is valid!")
else:
messages.warning(request, f'Form is not valid! {request.POST}')
else:
l_form = LikePostForm(instance=request.user.profile)
context = {
'post': Posts.objects.all(),
'l_form': l_form
}
return render(request, "posts.html", context)
Now when I click the Like button, I got this message **Form is not valid! <QueryDict: {'csrfmiddlewaretoken': ['cNk9ZDS33Nj0l95TBfwtedL1jjAbzDSrH15VjMNZAcxjQuihWNZzOkVnIyRzsjwN'], 'post': ['1', ''], 'user': ['1']}>**
There are a couple of issues with your code.
First, the __str__() method should return a string and not a tuple
class LikePost(models.Model):
...
def __str__(self):
return '{} - {}'.format(self.user.username, self.post.name)
Second, there is a typo; change Pots to Posts:
context = {
'posts': Posts.objects.all(),
'form': form,
}
return render(request, "posts.html", context)
And third and last, the line u.post = request.post is throwing the error you mention, because the request object has no attribute post.
So change your form code to add the post in hidden state (I used fields instead of exclude):
class LikePostForm(forms.ModelForm):
class Meta:
model = LikePost
fields = ['post', ]
widgets = {
'post': forms.HiddenInput(),
}
and then change your view:
form = LikePostForm(request.POST)
if form.is_valid():
u = form.save(commit=False)
u.user = request.user
u.save()
After edit to the question:
Try adding post.pk as a hidden input in your form:
<form action="/posts/" method="post">
{% csrf_token %}
<input type="hidden" name="post" value="{{ post.pk }}">
{{ l_form|crispy }}
<button type="submit" class="btn btn-outline-success">Like</button>
</form>
or you can also do in your view:
u.post = Posts.objects.filter(pk=form.cleaned_data.get('post')).first()

Django model form not showing data in bootstrap modal

So, I am new to the django and what I am trying to achive is to edit a comment in bootstrap modal.
My problem is that when I launch modal for editing specific comment, comment text isn't shown in modal. I am using the same CommentForm class for creating and editing comment, as I am using the same principle for the rest model classes in my app.
Here is the edit comment view:
def edit_comment(request, p_id):
comment = get_object_or_404(Comment, pk=p_id)
task_id = comment.task.id
task = get_object_or_404(Task, pk=task_id)
if request.method == "POST":
form = CommentForm(request.POST, instance=comment)
if form.is_valid():
form.save()
return redirect(reverse('task_details', kwargs={'p_id' : task.id}))
else:
data = {
'form' : CommentForm(instance=comment),
}
return render(request, "polls/task_details.html",data)
Because the list of all comments attached to the task are shown in task details, an this is where i launch edit modal, here is the view:
def task_details(request, p_id):
projects = Project.objects.filter(users=request.user)
task = get_object_or_404(Task, pk=p_id)
comments = Comment.objects.filter(task__id=p_id)
proj_id = task.project.id
project = get_object_or_404(Project, pk=proj_id)
if request.method == "POST":
data = {'task': task,
'comments': comments,
'project' : project,
'form' : CommentForm(),
'projects' : projects}
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.user = request.user
comment.type = "comment"
comment.task = task
comment.save()
return render(request, "polls/task_details.html", data)
else:
data = {'task': task,
'comments': comments,
'project' : project,
'form' : CommentForm(),
'projects' : projects}
data.update(csrf(request))
return render(request, "polls/task_details.html", data)
forms.py:
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = ('comment_text',)
exclude = ('user', 'time_occurred', 'type', 'task', 'milestone')
widgets = {'comment_text': forms.Textarea(attrs={'class':"form-control",
'required':"",
'rows':3,
})}
labels = {"comment_text": _("Comment"),
}
urls.py:
url(r'^edit_comment/(?P<p_id>\d+)/$', views.edit_comment, {}, 'edit_comment'),
Comment is attached to the Task, and Comment inherits LogEvent abstract class, so here is the models.py part:
class Task(models.Model):
project = models.ForeignKey(Project)
user = models.ForeignKey(User, related_name='task_created_by')
assigned = models.ForeignKey(User, related_name='task_assigned_to', null=True)
priority = models.ForeignKey(Priority,null=True)
milestone = models.ForeignKey(Milestone)
name = models.CharField(max_length = 50)
description = models.CharField(max_length = 5000)
type = models.ForeignKey(Type, null=True)
state = models.CharField(max_length = 20, choices = State)
def __str__(self):
return self.name
class LogEvent(models.Model):
user = models.ForeignKey(User)
time_occurred = models.DateTimeField('time_occurred')
type = models.CharField(max_length = 50)
task = models.ForeignKey(Task, null=True, blank=True)
milestone = models.ForeignKey(Milestone, null=True, blank=True)
class Meta:
abstract = True
class Comment(LogEvent):
comment_text = models.TextField()
def save(self, *args, **kwargs):
''' On save, update timestamps '''
if not self.id:
self.time_occurred = datetime.datetime.today()
return super(Comment, self).save(*args, **kwargs)
def __str__(self):
return self.user.username
Finally, the template:
(This is the part of the task details template, where all comments attached to specific task are shown)
<div class="col-lg-12">
{% for comment in comments %}
<div class="well">
<p>
<i class="fa fa-fw fa-user"></i><strong>{{comment.user.get_full_name}}</strong>
<i class="fa fa-fw fa-clock-o"></i>{{comment.time_occurred}}
{% if comment.user == user %}
<a href=""
class="btn btn-info btn-xs btn-outline"
style="float: right; margin-left: 5px" data-toggle="modal" data-target="#EditModal{{forloop.counter}}"> <i class="fa fa-fw fa-edit"></i> Edit</a>
<!-- EDIT MODAL -->
<div class="modal fade" id="EditModal{{forloop.counter}}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog" >
<div class="modal-content" style=" border-color: #5cb85c;">
<div class="modal-header" style=" color: white;background-color: #5cb85c;border-color: #5cb85c;">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel" >Edit comment</h4>
</div>
<form action="{% url 'edit_comment' p_id=comment.id %}" method="post">
{% csrf_token %}
{% for field in form %}
<div class="modal-body">
{{field.errors}}
{{field}}
</div>
{% endfor %}
<div class="modal-footer">
<button type="button" class="btn btn-default btn-outline" data-dismiss="modal">Close</button>
<input type="submit" class="btn btn-success btn-outline" value="Save changes">
</div>
</form>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
{% endif %}
<p>{{comment.comment_text}}</p>
</div>
{% endfor %}
</div>
My question is what should I do to show the comment text in textarea inside the modal, or what have I missed, so the user can easily modify his comment, without copying the text before lauching the modal?