Sanca Kembang Sanca Kembang - 1 month ago 5
Python Question

How to continue the object in django get_next/previous_by_date_created and published?

Anyone can help me how to continue the object in Django by

get_next/previous_by_date_created
and published only?

>>> obj_4 = Post.objects.get(pk=4)
>>> obj_4.publish
True
>>> obj_4.get_previous_by_date_created()
<Post: Title Post 3>
>>> obj_4.get_previous_by_date_created().publish
False
>>> obj_4.get_previous_by_date_created().pk
3
>>> obj_2 = Post.objects.get(pk=2)
<Post: Title Post 2>
>>> obj_2.publish
True
>>> obj_4.get_next_by_date_created()
<Post: Title Post 5>
>>> obj_4.get_next_by_date_created().publish
True
>>>


I need to continue the object by published only. For example:

>>> obj_4 = Post.objects.get(pk=4)
>>> obj_4.get_previous_by_date_created_and_published()
<Post: Title Post 2>


Other conditions, if we have such as bellow:

pk : [1, 2, 3, 4, 5, 6, 7, 8 ]
publish : [True, False, False, False, True, True, False, True]


And then, if i starting from
pk=5
, the output should be
pk=1
.

>>> obj_5 = Post.objects.get(pk=5)
>>> obj_5.get_previous_by_date_created_and_published().pk
1
>>>
>>> obj_5.get_previous_by_date_created_and_published().publish
True
>>>


Thanks so much before...

UPDATE SOLVED:

1.
views.py


class DetailPostView(generic.DetailView):
model = Post
template_name = 'detail.html'

def get_previous_by_created_and_published(self):
prev = Post.objects.filter(
created__lte=self.get_object().created,
publish=True
).order_by('-created').first()
return prev

def get_next_by_created_and_published(self):
next = Post.objects.filter(
created__gte=self.get_object().created,
publish=True
).order_by('-created').first()
return next

def get_context_data(self, **kwargs):
context_data = super(DetailPostView, self).get_context_data(**kwargs)
context_data[
'get_previous_by_created_and_published'
] = self.get_previous_by_created_and_published()
context_data[
'get_next_by_created_and_published'
] = self.get_next_by_created_and_published()
return context_data


2.
templates/detail.html


<ul class="pager">
<li class="previous">
{% if get_previous_by_created_and_published %}
<a href="{% url 'detail_post_page' slug=get_previous_by_created_and_published.slug %}">&larr; Previous</a>
{% endif %}
</li>
<li class="next">
{% if get_next_by_created_and_published %}
<a href="{% url 'detail_post_page' slug=get_next_by_created_and_published.slug %}">Next &rarr;</a>
{% endif %}
</li>
</ul>

Answer

An implementation which will work is:

def get_previous_by_created_and_published(self):
    prev = Post.objects.filter(created__lte=self.created,
                               published=True
                               ).order_by('-created').first()
    return prev

Though I'm assuming here that if there are multiple published posts created before this then you'll only want the most recent, as the name of your method suggests.

get_next_by_created_and_published will work in a similar manner, though with __gte and the ordering flipped.

Comments