How to apply django lazy loading to load my comments? - django

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

Related

Second page of Pagination not working in django after searching

Searching result is not appearing in second page what should I change to solve my problem ? and I'm using elasticsearch as search engine
index.html
<ul>
{% for i in paginator.page_range %}
{% if i <= page_number|add:5 and i >= page_number|add:-5 %}
<li class=" {% if i == page_number %} active {% endif %} " >
{{forloop.counter}}
</li>
{% endif %}
{% endfor %}
</ul>
and this is in my views.py
def index(request):
q = request.GET.get('q')
if q:
articles = PostDocument.search().query("match", title=q, )
paginator = Paginator(articles, 5)
page_number = request.GET.get('page', 1)
page_obj = paginator.get_page(page_number)
return render(request, 'index.html', {
'articles': page_obj.object_list,
'paginator': paginator,
'page_number': int(page_number),
})
else:
articles = ''
return render(request, 'index.html', {'articles': articles})
If you write ?page=…, then the ?q=… parameter is "dropped". The trick is to add it to the querystring when you go to the next object:
def index(request):
q = request.GET.get('q')
if q:
articles = PostDocument.search().query("match", title=q, )
paginator = Paginator(articles, 5)
page_number = request.GET.get('page', 1)
page_obj = paginator.get_page(page_number)
return render(request, 'index.html', {
'articles': page_obj.object_list,
'paginator': paginator,
'page_number': int(page_number),
'q' : q
})
else:
articles = ''
return render(request, 'index.html', {'articles': articles})
and then render this with:
{{forloop.counter}}
The |urlencode template filter [Django-doc] is necessary to percentage encode the query, for example if it contains a question mark (?), ampersand (&), etc.

How to hide html button if queryset doesn't have next blog post in Django?

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>

Django template variable does not show up

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})

Django 'dict' object has no attribute 'getlist'

Inspired by this blog post, I am trying to make a views that handles profiles searches by saving the search parameters into session so that the query can be preserved through pagination.
Here is the views:
def profile_search(request):
args = {}
qs=[]
if not request.method == 'POST':
if 'search-profiles-post' in request.session:
request.POST = request.session['search-profiles-post']
request.method = 'POST'
if request.method == "POST":
form = AdvancedSearchForm(request.POST)
request.session['search-profiles-post'] = request.POST
if form.is_valid():
cd = form.cleaned_data
s_country=cd['country']
s_province=cd['province']
s_city = cd['city']
if s_city: qs.append( Q(city__in=s_city))
if s_country: qs.append(Q(country__icontains = s_country))
if s_province: qs.append( Q(province__icontains=s_province))
f = None
for q in qs:
if f is None:
f=q
else: f &=q
print f
if f is not None:
profiles = UserProfile.objects.filter(f).order_by('-created_at')
else:
form = AdvancedSearchForm()
profiles = UserProfile.objects.all().order_by('-created_at')
paginator = Paginator(profiles,12)
page= request.GET.get('page')
try:
results = paginator.page(page)
except PageNotAnInteger:
results = paginator.page(1)
except EmptyPage:
results = paginator.page(paginator.num_pages)
args.update(csrf(request))
args['form'] = form
args['results'] = results
return render_to_response('userprofile/advanced_search.html', args,
context_instance=RequestContext(request))
Here is the form:
<form action="/search/" method="post">{% csrf_token %}
<ul class="list-unstyled">
<li><h3>Country</h3></li>
<li>{{form.country}}</li><br>
<h4>Province</h4>
<li>{{form.province}}</li>
<h4>City</h4>
<li>{{form.city}}</li>
</ul>
<input type="submit" name="submit" value="search" />
</form>
Search Results:
{% for p in results %}
<div">
<div>
<br>
<strong><a href="/profile/{{p.username}}" >{{p.username}}</a></strong>
{{p.country}} <br>
{{p.province}} <br>
{{p.city}} <br>
</div>
</div>
{% endfor %}
<div>
<div class="pagination">
{% if results.has_previous %}
<< Prev &nbsp
{% endif %}
{% if results.has_next %}
Next >>
{% endif %}
</div>
</div>
</div>
and the urls.py
url(r'^search/', 'userprofile.views.profile_search'),
This is the mysterious error theat I get:
Traceback:
File "/home/supermario/.djenv/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
204. response = middleware_method(request, response)
File "/home/supermario/.djenv/local/lib/python2.7/site-packages/debug_toolbar/middleware.py" in process_response
89. new_response = panel.process_response(request, response)
File "/home/supermario/.djenv/local/lib/python2.7/site-packages/debug_toolbar/panels/request.py" in process_response
31. 'post': [(k, request.POST.getlist(k)) for k in sorted(request.POST)],
Exception Type: AttributeError at /search/
Exception Value: 'dict' object has no attribute 'getlist'
I got stock on this for a while so really appreciate your hints.
request.POST should be the dict-like QueryDict but not the simple python dict:
from django.http import QueryDict
request.POST = QueryDict('').copy()
request.POST.update(request.session['search-profiles-post'])

How to implement Post/Redirect/Get in django pagination?

I have a view that filters out results for a posted search form:
def profile_advanced_search(request):
args = {}
if request.method == "POST":
form = AdvancedSearchForm(request.POST)
qs=[]
if form.is_valid():
cd = form.cleaned_data
s_country=cd['country']
s_province=cd['province']
s_city = cd['city']
if s_country: qs.append(Q(country__icontains = s_country))
if s_province: qs.append( Q(province__icontains=s_province))
if s_city: qs.append( Q(city__icontains=s_city))
f = None
for q in qs:
if f is None:
f=q
else: f &=q
list = UserProfile.objects.filter(f).order_by('-created_at')
else:
form = AdvancedSearchForm()
list = UserProfile.objects.all().order_by('-created_at')
paginator = Paginator(list,10)
page= request.GET.get('page')
try:
results = paginator.page(page)
except PageNotAnInteger:
results = paginator.page(1)
except EmptyPage:
results = paginator.page(paginator.num_pages)
args.update(csrf(request))
args['form'] = form
args['results'] = results
return render_to_response('userprofile/advanced_search.html', args,
context_instance=RequestContext(request))
the urls.py part is:
url(r'^search/$', 'userprofile.views.profile_advanced_search'),
The template is:
<form action="/search/" method="post">{% csrf_token %}
<ul class="list-unstyled">
<li><h3>Country</h3></li>
<li>{{form.country}}</li><br>
<h4>Province</h4>
<li>{{form.province}}</li>
<h4>City</h4>
<li>{{form.city}}</li>
</ul>
<input type="submit" name="submit" value="search" />
</form>
Search Results:
{% for p in results %}
<div">
<div>
<br>
<strong><a href="/profile/{{p.username}}" >{{p.username}}</a></strong>
{{p.country}} <br>
{{p.province}} <br>
{{p.city}} <br>
</div>
</div>
{% endfor %}
<div>
<div class="pagination">
{% if results.has_previous %}
<< Prev &nbsp
{% endif %}
{% if results.has_next %}
Next >>
{% endif %}
</div>
</div>
</div>
These work fine for the first page, but to deal with the later pages, it is suggested that I need to implement Post/Redirect/Get .
However I have had difficulty to make such views/template/urls to deal with GET pages regarding that all of the search parameters are arbitrary. So I appreciate a complete solution.
Do you need 2 views. First one for form search and second one to show results. You have not implemented redirect in any way in your sample code!
urls
...
url(r'^search/$',
'userprofile.views.profile_advanced_search'),
url(r'^show/(?P<country>\w+)/(?P<province>\w+)/(?P<site>\w+)/(?P<page>\d+)',
'userprofile.views.profile_advanced_show'),
...
profile_advanced_search
def profile_advanced_search(request):
args = {}
if request.method == "POST":
form = AdvancedSearchForm(request.POST)
qs=[]
if form.is_valid():
cd = form.cleaned_data
s_country=cd['country']
s_province=cd['province']
s_city = cd['city']
return HttpResponseRedirect(
reverse('userprofile.views.profile_advanced_show',
args=(s_country, s_province, s_city, 0, )))
return HttpResponseRedirect(
reverse('userprofile.views.profile_advanced_show',
args=('+', '+', '+', 0, )))
profile_advanced_show
def profile_advanced_show(request, s_country='',
s_province='', s_city='', page=0):
f = some filters with s_country, s_province and s_city
list = UserProfile.objects.filter(f).order_by('-created_at')
paginator = Paginator(list,10)
try:
results = paginator.page(page)
except PageNotAnInteger:
results = paginator.page(1)
except EmptyPage:
results = paginator.page(paginator.num_pages)
args.update(csrf(request))
form = AdvancedSearchForm(initial={ 's_country': s_country, ... } )
args['form'] = form
args['results'] = results
return render_to_response('userprofile/advanced_search.html', args,
context_instance=RequestContext(request))
Notice: improve it for not valid form submissions. Remember you can send parameters to second view via GET as key value instead route values.