for some reason im unable to display the comments of a category_request and i have now idea why, is smb. maybe able to have an eye on that, praticaly i should work but i dont see the mistake here.
as far as i see I'm using category_request_comment from the view to get a releated comment objects from a category_request... any idea?
Template Snippet:
{% for category_request_comment in category_request_comments %}
<div class="comment">
<p>{{ category_request_comment.content|readmore:15 }}</p>
{% if category_request_comment.content.published_date %}
<div class="date">
<a>Comment by: {{ category_request_comment.author }}</a><br>
<a>Commented at: {{ category_request_comment.published_date }}</a>
</div>
{% endif %}
{% if request.user == category_request_comment.author %}
<a class="commentoption" href="{% url 'comment_edit' pk=category_request_comment.pk %}">Edit</a><a> | </a>
<a class="commentoption" href="{% url 'comment_delete' pk=category_request_comment.pk %}">Delete</a>
{% endif %}
</div>
{% endfor %}
views.py
def category_request_detail(request, pk):
category_request = get_object_or_404(CategoryRequests, pk=pk)
list_category_request = CategoryRequests.objects.get_queryset().filter(id=pk).order_by('-pk')
paginator = Paginator(list_category_request, 20)
page = request.GET.get('page')
category_request_comment = paginator.get_page(page)
return render(request, 'myproject/category_request_detail.html', {'category_request': category_request, 'category_request_comment': category_request_comment})
views.py (only for Reference)
def category_request_comment_new(request, pk):
if request.method == "POST":
form = CategoryRequestsCommentForm(request.POST)
if form.is_valid():
category_request = get_object_or_404(CategoryRequests, pk=pk)
requests_comment = form.save(commit=False)
requests_comment.author = request.user
requests_comment.published_date = timezone.now()
requests_comment.category_request = category_request
requests_comment.save()
return redirect('category_request_detail', pk=requests_comment.category_request.pk)
else:
form = CategoryRequestsCommentForm()
return render(request, 'myproject/comment_new.html', {'form': form})
urls.py
url(r'^categories/requests/$', myproject_views.category_request_list, name='category_request_list'),
Thanks in advance
Your template is looking for an object called category_request_comments, but you have not sent anything with that name to the template.
def category_request_detail(request, pk):
category_request = get_object_or_404(CategoryRequests, pk=pk)
list_comments = CategoryRequests_Comment.objects.get_queryset().filter(category_request_id=pk).order_by('-pk')
paginator = Paginator(list_comments, 10)
page = request.GET.get('page')
comments = paginator.get_page(page)
return render(request, 'myproject/category_request_detail.html', {'category_request': category_request, 'comments': comments})
Related
Sorry if this is too much code, but I believe it is all relevant to the question at hand.
Long story short, on my series_detail page, all episodes belonging to each series is shown, as well as forms to add a new episode or edit an existing one.
The edit episode form, however, requires an instance, which always returns the very first object of the episodes queryset. This is presumably because of the .first(), but I used this since you can only have one object passed as an instance.
What I am trying to achieve is:
after showing the edit modal next to each episode, show the instance of each episode instead of only the first episode.
save only that episode's instance after the form is filled
achieve this without redirecting to an edit page
models.py
class Series(models.Model):
name = models.CharField(max_length=100)
class Episode(models.Model):
series = models.ForeignKey(Series, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
episode_no = models.IntegerField(null=True)
description = models.TextField(max_length=500)
image = models.ImageField(upload_to='pics/episodes',)
forms.py
class EpisodeForm(forms.ModelForm):
name = forms.CharField()
description = forms.CharField(widget=forms.Textarea, required=False)
episode_no = forms.IntegerField()
class Meta:
model = Episode
fields = ['name', 'description', 'episode_no' ,'image']
views.py
def series_detail(request, pk):
try:
series = Series.objects.get(pk=pk)
except:
return render(request, 'error_404.html')
episodes = Episode.objects.filter(series=series).first()
if request.method == 'POST':
if 'addepisodeform' in request.POST:
e_form = EpisodeForm(request.POST, request.FILES, prefix='addepisode')
e_form.instance.series = Series.objects.get(pk=pk)
if e_form.is_valid():
e_form.save()
return redirect('series_detail', pk=pk)
messages.success(request, 'Episode was created')
else:
return redirect('series_detail', pk=pk)
messages.error(request, 'Episode was not created')
elif 'editepisodeform' in request.POST:
edit_e_form = EpisodeForm(request.POST, request.FILES, instance=episodes, prefix='editepisode')
edit_e_form.instance.series = Series.objects.get(pk=pk)
if edit_e_form.is_valid():
edit_e_form.save()
return redirect('series_detail', pk=pk)
messages.success(request, 'Episode was updated')
else:
return redirect('series_detail', pk=pk)
messages.error(request, 'Episode was not updated')
else:
e_form = EpisodeForm(prefix='addepisode')
edit_e_form = EpisodeForm(instance=episodes, prefix='editepisode')
context = {
'episodes': episodes,
'e_form': e_form,
'edit_e_form': edit_e_form
}
return render(request, 'series/series_detail.html', context)
def delete_episode(request, pk1, pk2):
try:
series = Series.objects.get(pk=pk1)
except:
return render(request, 'error_404.html')
try:
episode = Episode.objects.get(series=series, episode_no=pk2)
except:
return render(request, 'error_404.html')
episode.delete()
return redirect('series_detail', pk=pk1)
urls.py
path('series/<int:pk>/', views.series_detail, name='series_detail'),
path('series/<int:pk1>/episode/<int:pk2>/delete/', views.delete_episode, name='delete_episode'),
series_detail.html
<button type="submit" name="addepisodeform">
Add Episode
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ e_form }}
</form>
</button>
{% for episode in episodes %}
{{ episode.name }}
{{ episode.description}}
<img src="{{ episode.image.url }}" height="125px" width="300px" style="object-fit: cover;">
<button type="submit" name="editepisodeform">
Edit Episode
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ edit_e_form }}
</form>
</button>
{% endfor %}
Okay, so it turns out that formsets were the way to go after all. Thanks to Willem Van Onsem's answer, I decided to go that route after all and it worked like a charm.
A form can only edit one instance, but with formsets, I was able to not only edit each episode rather than just the first instance, but even create a new object and delete multiple objects at the same time!
views.py
#import the formset
from django.forms import modelformset_factory, inlineformset_factory
#formset
EpisodeFormset = inlineformset_factory(Series, Episode, fields=('name', 'episode_no', 'description', 'image'), can_delete=True, extra=1)
#post call
if request.method == 'POST':
if 'editepisodeform' in request.POST:
formset = EpisodeFormset(request.POST, request.FILES, instance=series, prefix='editepisode')
if formset.is_valid():
formset.save()
return redirect('series_detail', pk=pk)
else:
return redirect('series_detail', pk=pk)
else:
formset = EpisodeFormset(instance=series)
series_detail.html
<div>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<button type="submit" class="btn btn-primary" name="editepisodeform">Edit</button>
{{ form.as_p }}
{% for episode in episodes %}
{% if episode.episode_no == form.episode_no.value %}
Episode: {{ episode.episode_no }} <br>
Name: {{ episode.name }} <br>
<img src="{{ episode.image.url }}" height="125px" width="300px" style="object-fit: cover;"> <br> {% endif %}
{% endif %}
{% endfor %}
{% endfor %}
</form>
</div>
I would like to hide the Next button in my blog if there is no next blog post available.
Is there some kind of built-in method to check has_next has_previous or do I need to create some logic in my view and extend the template with let's say {% if Foo %} show button {% endif %} ?
views.py
def render_post(request, id):
category_count = get_category_count()
most_recent = Post.objects.order_by('-timestamp')[:3]
post = get_object_or_404(Post, id=id)
next_post_id = int(id) + 1
previous_post_id = int(id) - 1
PostView.objects.get(post=post)
context = {
'post': post,
'id': id,
'next_post_id': next_post_id,
'previous_post_id': previous_post_id,
'most_recent': most_recent,
'category_count': category_count,
}
return render(request, 'post.html', context)
html
<div id="button-wrapper">
<button class="buttons" type="submit">Previous</button>
<button class="buttons" type="submit">Next</button>
</div>
You could do it by checking that the previous/next posts exist and returning the results in the context:
views.py
def render_post(request, id):
category_count = get_category_count()
most_recent = Post.objects.order_by('-timestamp')[:3]
post = get_object_or_404(Post, id=id)
next_post_id = int(id) + 1
previous_post_id = int(id) - 1
try:
previous_post_exists = Post.objects.filter(id=previous_post_id).exists()
except Post.DoesNotExist:
previous_post_exists = False
try:
next_post_exists = Post.objects.filter(id=next_post_id).exists()
except Post.DoesNotExist:
next_post_exists = False
context = {
'post': post,
'id': id,
'next_post_id': next_post_id,
'previous_post_id': previous_post_id,
'previous_post_exists': previous_post_exists,
'next_post_exists': next_post_exists,
'most_recent': most_recent,
'category_count': category_count,
}
return render(request, 'post.html', context)
You would then need to check those values in your template:
html
<div id="button-wrapper">
{% if previous_post_exists %}
<button class="buttons" type="submit">Previous</button>
{% endif %}
{% if next_post_exists %}
<button class="buttons" type="submit">Next</button>
{% endif %}
</div>
I am tried but i am not getting the desired output for lazy loading
views.py
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
content_type = ContentType.objects.get_for_model(Post)
obj_id = post.id
comments = Comment.objects.filter(
content_type=content_type, object_id=obj_id)
parent_id = request.POST.get("parent_id")
csubmit = False
if parent_id:
content_type = ContentType.objects.get_for_model(Comment)
Comment.objects.create(content_type=content_type,
object_id=parent_id,
parent_id=parent_id,
user=request.user,
text=request.POST.get("text"))
if request.method == 'POST':
form = CommentForm(data=request.POST)
if form.is_valid():
new_comment = form.save(commit=False)
new_comment.content_type = content_type
new_comment.user = request.user
new_comment.save()
csubmit = True
else:
form = CommentForm()
paginator = Paginator(comments, 10)
try:
comments = paginator.page(page)
except PageNotAnInteger:
comments = paginator.page(1)
except EmptyPage:
comments = paginator.page(paginator.num_pages)
return render(request, 'post_detail.html', {'post': post,
'comments': comments, 'csubmit': csubmit, 'form': form})
I want to apply lazy loading in the above view and want to apply on template.Above i added pagination and rendered in template
post_details.html
{%for comment in comments %}
<br>
{{comment.text}}<br/>
by {{comment.user}}<br>
<a href='#' class="rep_cmt" data-parentid="
{{comment.id}}">Reply</a><br>
{% for comment in comment.children.all %}
{{comment}}
{% endfor %}
{%endfor%}
{% if comments.has_next %}
<a class="infinite-more-link" href="?page={{ comments.next_page_number
}}">More</a>
{% endif %}
<div class="loading" style="display: none;">
Loading...
</div>
<script>
var infinite = new Waypoint.Infinite({
element: $('.rep_cmt')[0],
onBeforePageLoad: function () {
$('.loading').show();
},
onAfterPageLoad: function ($items) {
$('.loading').hide();
}
});
</script>
In above i added script to render data in lazy loading process but it is not rendering
I have a for loop that lists all the testimony instances in my model. I'd like to have the button in the code below delete the related instance when clicked.
html
{% block content %}
{% for testimony in testimonies %}
<a href="{% url "main:update_testimony_view" slug=testimony.slug %}">
<h3>{{testimony.name}}</h3>
<button type="button" class="btn btn-danger">Delete</button>
</a>
{% endfor %}
****
{% endblock content %}
views.py
def create_testimony_view(request):
if request.method == "POST":
form = CreateTestimonyForm(request.POST)
if form.is_valid():
testimony = form.save(commit=False)
testimony.save()
return redirect('main:homepage_view')
else:
form = CreateTestimonyForm
context = {
"title": "Create - Testimony",
"form": form,
"testimonies": Testimony.objects.all(),
}
return render(request=request, template_name="main/create/create_testimony.html", context=context)
def update_testimony_view(request, slug):
instance = get_object_or_404(Testimony, slug=slug)
if request.method == 'POST':
form = CreateTestimonyForm(
request.POST, request.FILES, instance=instance)
if form.is_valid():
testimony = form.save(commit=False)
testimony.save()
return redirect('main:homepage_view')
else:
form = CreateTestimonyForm(instance=instance)
context = {
"title": "Update - Testimony",
"form": form,
"instance": instance,
}
return render(request=request, template_name="main/create/create_testimony.html", context=context)
Thanks for any help
You need to make a POST request to the server which will delete the instance.
Please have a look at Form documentation. https://docs.djangoproject.com/en/3.0/topics/forms/
You need to add simple form and view to delete testimony.
html,
{% for testimony in testimonies %}
<a href="{% url "main:update_testimony_view" slug=testimony.slug %}">
<h3>{{testimony.name}}</h3>
<form action="{% url 'main:delete_testimony' testimony.pk %}" method="POST">
<button type="button" class="btn btn-danger">Delete</button>
</form>
</a>
{% endfor %}
view,
def delete_testimony(request, pk):
deleted = False
try:
Testimony.objects.delete(pk=pk)
deleted = True
except Testimony.DoesNotExist:
pass
return JsonResponse({'deleted':deleted})
I have a situation where I display a Form sometimes and sometimes I don't display it.
Actually, there are multiple forms using the same Submit button.
What do I do to take care of the situation when a particular form is not shown in the template.
The template code
{% extends BASE_TEMPLATE %}
{% load crispy_forms_tags %}
{% block title %}<h2>New Thread</h2>{% endblock %}
{% block content %}
<div class="col-md-6">
<form method="post" accept-charset="utf-8">{% csrf_token %}
{{ threadForm|crispy }}
{{ postForm|crispy }}
{% if SHOW_WIKI %}
{{ wikiFrom|crispy }}
{% endif %}
<input type="submit" class="btn btn-primary btn-sm" value="Submit"/>
</form>
</div>
{% endblock %}
This is the view code
#login_required
def createThread(request, topic_title=None):
if topic_title:
try:
if request.method == 'POST':
topic = Topic.getTopic(topic_title)
threadForm = ThreadSUForm(request.POST, prefix='thread')
postForm = PostForm(request.POST, prefix='post')
show_wiki = getattr(settings, "REFORUMIT_ALLOW_WIKI_FOR_THREADS", False) and topic.is_wiki_allowed
wikiForm = WikiCreateForm(request.POST, prefix='wiki')
if threadForm.is_valid() and postForm.is_valid() and wikiForm.is_valid():
thread = threadForm.save(commit=False)
post = postForm.save(commit=False)
wiki = wikiForm.save(commit=False)
thread.op = post
thread.wiki_revision = None
post.setMeta(request)
wiki.setMeta(request)
if is_authenticated(request):
post.created_by = request.user
wiki.author = request.user
thread.save()
wiki.wiki_for = thread
wiki.save()
post.save()
thread.wiki_revision = wiki
thread.save()
return HttpResponseRedirect(thread.get_absolute_url)
else:
topic = Topic.getTopic(topic_title)
threadForm = ThreadSUForm(prefix='thread', initial={"topic": topic})
postForm = PostForm(prefix='post')
wikiForm = WikiCreateForm(prefix='wiki')
show_wiki = getattr(settings, "REFORUMIT_ALLOW_WIKI_FOR_THREADS", False) and topic.is_wiki_allowed
context = dict(threadForm=threadForm, postForm=postForm, wikiFrom=wikiForm, SHOW_WIKI=show_wiki)
return render(request, 'reforumit/create_thread.html', context)
except Topic.DoesNotExist:
pass
return redirect('topics')
This won't give exact answer but you can change code a bit. Providing you if conditional section only.
if threadForm.is_valid() and postForm.is_valid():
thread = threadForm.save(commit=False)
post = postForm.save(commit=False)
thread.wiki_revision = None
thread.op = post
post.setMeta(request)
if is_authenticated(request):
post.created_by = request.user
post.save()
thread.save()
if wikiForm.is_valid():
print("WikiForm is valid!")
wiki = wikiForm.save(commit=False)
print("Wiki has content")
wiki.setMeta(request)
if is_authenticated(request):
wiki.author = request.user
wiki.wiki_for = thread
wiki.save()
thread.wiki_revision = wiki
thread.save()
return HttpResponseRedirect(thread.get_absolute_url)