Ошибка разбиения на страницы в Django с представлениями и шаблоном
У меня есть база данных, Записи, и я хочу, чтобы элементы в текущем Entry
отображается в шаблоне entry.html
, Затем я хочу, чтобы на боковой панели была ссылка на предыдущую запись (если она существует) и следующую запись (если она существует). Это мой текущий views.py:
def entry(request, projects_id=1, entries_id=1):
entries_list = Entries.objects.filter(project_id=projects_id)
paginator = Paginator(entries_list, 1)
page = request.GET.get('page')
try:
all_entries = paginator.page(page)
except PageNotAnInteger:
all_entries = paginator.page(1)
except EmptyPage:
all_entries = paginator.page(paginator.num_pages)
return render_to_response('entry.html',
{'projects': Projects.objects.get(id=projects_id),
'entry': Entries.objects.get(project_id=projects_id, entry_unique=entries_id),
'all_entries': all_entries}
)
Это мой текущий код вызова paginator в шаблоне:
{% if all_entries.has_previous %}
<a href="/projects/get/{{projects.id}}/entries/get/{{entry.entry_unique|add:"-1"}}"><img src="/static/assets/img/arrow_left.png" width="40"></a>
{% endif %}
{% if all_entries.has_next %}
<a href="/projects/get/{{projects.id}}/entries/get/{{entry.entry_unique|add:"1"}}"><img src="/static/assets/img/arrow_right.png" width="40"></a>
{% endif %}
Проблема сейчас в том, что она показывает только стрелку вправо, а не левую, и не основывается на том, есть ли еще записи после текущей. Я настроил его так, чтобы entry_unique и поле id были разными для каждой записи, так как я хочу, чтобы записи увеличивались на 1 для каждого проекта, а не для всего сайта, на случай, если это как-то связано с этим.
Это моя модель для записей:
class Entries(models.Model):
project_id = models.ForeignKey(Projects)
entry_unique = models.IntegerField(default=0)
entry_pubdate = models.DateTimeField('date published')
Так что моя главная проблема заключается в том, что, хотя моя таблица записей имеет id
колонка, project_id
как я определяю, какому Проекту принадлежит Заявка, и entry_unique
увеличивается на единицу для каждой записи на проект, так что запись 1 равна 1, запись 2 равна 2, независимо от того, что id
столбец есть.
Однако, при использовании paginator, он никогда не показывает мне стрелку previous_entry, только стрелку next_entry, и это не имеет никакого отношения к тому, есть ли другой entry_unique или нет. По сути, я сортирую по project_id, чтобы определить, с какими записями я работаю, но мне нужно манипулировать этими записями с помощью entry_unique.
РЕДАКТИРОВАТЬ: И последнее, но не менее важное: похоже, что has_next возвращает true, только если есть еще один project_id, который находится выше, поэтому, если я перейду к своему проекту с наибольшим номером, has_next вернет false и не покажет мне стрелку вправо. Но я все еще не могу заставить has_previous работать.
2 ответа
ОК, мне удалось заставить его работать, изменив мой Views.py:
def entry(request, projects_id=1, entries_id=1):
current_entry = Entries.objects.get(project_id=projects_id, entry_unique=entries_id)
current_entry_unique = current_entry.entry_unique
entry_previous = current_entry_unique
entry_previous -= 1
if Entries.objects.filter(project_id=projects_id, entry_unique=entry_previous).exists():
prev_entry = Entries.objects.get(project_id=projects_id, entry_unique=entry_previous)
else:
prev_entry = None
entry_next = current_entry.entry_unique
entry_next += 1
if Entries.objects.filter(project_id=projects_id, entry_unique=entry_next).exists():
next_entry = Entries.objects.get(project_id=projects_id, entry_unique=entry_next)
else:
next_entry = None
return render_to_response('entry.html',
{'projects': Projects.objects.get(id=projects_id),
'entry': Entries.objects.get(project_id=projects_id, entry_unique=entries_id),
'prev_entry': prev_entry,
'next_entry': next_entry }
)
И тогда мой entry.html выглядит так:
{% if prev_entry %}
<a href="/projects/get/{{projects.id}}/entries/get/{{entry.entry_unique|add:"-1"}}"><img src="/static/assets/img/arrow_left.png" width="40"></a>
{% endif %}
{% if next_entry %}
<a href="/projects/get/{{projects.id}}/entries/get/{{entry.entry_unique|add:"1"}}"><img src="/static/assets/img/arrow_right.png" width="40"></a>
{% endif %}
Это может быть не красиво, но я делаю то, что хочу. Однако могут быть способы заставить его работать более красиво.
Без пагинатора:
def entry(request, projects_id, entries_id):
entries_in_project = Entries.objects.filter(project_id=projects_id)
entry = get_object_or_404(entries_in_project, entry_unique=entries_id)
try:
prev_entry_id = entries_in_project.filter(entry_unique__lt=entries_id)
.order_by('-entry_unique').values('entry_unique')[:1][0]['entry_unique']
except IndexError:
prev_entry_id = None
try:
next_entry_id = entries_in_project.filter(entry_unique__gt=entries_id)
.order_by('entry_unique').values('entry_unique')[:1][0]['entry_unique']
except IndexError:
next_entry_id = None
return render_to_response('entry.html',{
'projects': Projects.objects.get(id=projects_id), 'entry': entry,
'next_entry_id': next_entry_id, 'prev_entry_id': prev_entry_id,
})
Лучший путь:
Все это можно заменить встроенной функциональностью:
https://docs.djangoproject.com/en/dev/ref/models/options/
class Entries(models.Model):
project_id = models.ForeignKey(Projects)
entry_pubdate = models.DateTimeField('date published')
class Meta:
order_with_respect_to = 'project_id'
def entry(request, projects_id, entries_id):
entry = get_object_or_404(Entries,project_id=projects_id, id=entries_id)
next_entry = entry.get_next_in_order()
prev_entry = entry.get_previous_in_order()
return render_to_response('entry.html',{
'projects': Projects.objects.get(id=projects_id), 'entry': entry,
'next_entry': next_entry, 'prev_entry': prev_entry,
})
В entry.html:
{% if next_entry %}<a href="{{ next_entry.get_absolute_url }}">Next</a>{% endif %}
{% if prev_entry %}<a href="{{ prev_entry.get_absolute_url }}">Previous</a>{% endif %}