使用外键数据对 Django 视图进行分页
Paginating Django View with Foreign Key Data
我正在尝试构建一个允许将照片添加到相册的简单 Django 图库。到目前为止一切正常(上传照片、添加到相册、分页所有照片列表、照片 details/display 页等),直到我尝试显示 'album' 页。我可以获取页面来呈现相册和 所有 相关照片,但是如果我尝试对相册进行分页,事情就会开始变得奇怪。
这是我的模型:
# models.py
class Albums(models.Model):
id = models.AutoField(primary_key=True, unique=True)
name = models.CharField(max_length=500)
slug = models.SlugField(max_length=500, unique=True)
description = models.TextField(blank=True, null=True)
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
return super().save(*args, **kwargs)
class Photos(models.Model):
id = models.AutoField(primary_key=True, unique=True)
album = models.ForeignKey(
Albums, on_delete=models.SET_NULL, null=True, blank=True, verbose_name="Album"
)
photo = models.ImageField(upload_to="photos/")
slug = models.CharField(max_length=16, null=False, editable=False) # I know I'm not using a SlugField here; that's on purpose
title = models.CharField(max_length=500)
description = models.TextField(blank=True, null=True)
upload_date = models.DateTimeField(
default=timezone.now, verbose_name="Date uploaded"
)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
[...] # stuff to get the image's EXIF data and use that to set the slug
self.slug = str(datetime.strftime(img_date, "%Y%m%d%H%M%S"))
[...] # plus a bunch of other stuff that happens on save, not important here
super(Photos, self).save()
def delete(self, *args, **kwargs):
[...] # a bunch of stuff that happens on delete, not important here
super(Photos, self).delete()
让我痛苦的观点:
# views.py
class PhotoAlbum(DetailView):
context_object_name = "album"
model = Albums
slug_field = "slug"
template_name = "page.html"
def get_photos(self, **kwargs):
# get the integer id of the album
a = Albums.objects.filter(slug=self.kwargs["slug"])
a_id = a.values()[0]["id"]
# get the list go photos in that album
photos = Photos.objects.all().order_by("-capture_date").filter(album_id=a_id)
return photos
def get_context_data(self, **kwargs):
context = super(PhotoAlbum, self).get_context_data(**kwargs)
context["photos"] = self.get_photos()
return context
这些在基本模板中工作...
# album.html
<h2>{{ album.name }}</h2>
<p>{{ album.description }}</p>
<ul>
{% for photo in photos %}
<li><a href="{% url 'photo_detail' photo.slug %}">{{ photo.title }}</a></li>
{% endfor %}
</ul>
...但是如果我尝试通过更改...对照片进行分页...
photos = Photos.objects.all().order_by("-capture_date").filter(album_id=a_id)
...到...
photos = Paginator(Photos.objects.all().order_by("-capture_date").filter(album_id=a_id), 10)
...我一无所获
在搜索过程中,我看到的与分页相关的几乎所有问题都是针对 DRF 的,所以在这里有点碰壁。我在显示照片到相册的关系时遇到了各种麻烦(get_photos()
函数),所以我猜我的部分问题在于此。关于如何让它工作有什么建议吗?
Paginator
会给你一个分页器对象,而不是你正在分页的对象。要获取对象,首先需要指定页面,例如:
paginator = Paginator(Photos.objects.all().order_by("-capture_date").filter(album_id=a_id), 10)
photos = paginator.page(1)
photos
此处将包含第 1 页上的 Photos
个对象。
基于 Brian Destura's , I went back and started again using a ListView
and after re-reading the Django docs 和一些乱七八糟的东西,根据我的观点得出了这个解决方案,基于一些测试,它对我有用:
class AlbumDetail(ListView):
context_object_name = "photos"
template_name = "page.html"
paginate_by = 6
def get_queryset(self):
a = Albums.objects.filter(slug=self.kwargs["slug"])
a_id = a.values()[0]["id"]
self.albums = get_object_or_404(Albums, slug=self.kwargs["slug"])
return Photos.objects.filter(album_id=a_id).order_by("-capture_date")
def get_context_data(self, **kwargs):
context = super(AlbumDetail, self).get_context_data(**kwargs)
context["album"] = self.albums
return context
viwes.py
class PhotoAlbum(ListView):
context_object_name = "album"
model = Albums
slug_field = "slug"
template_name = "page.html"
paginate_by = 5
page.html
这是分页逻辑
{%if is_paginated %}
{%if page_obj.has_previous %}
<a style="margin-left: 20px; padding: 10px 20px;" class=" btn btn-primary" href="?page={{page_obj.previous_page_number}}"> {{page_obj.num_pages}} previous</a>
{% endif %}
{%if page_obj.has_next %}
{% if page_obj.num_pages == 1 %}
<a style="margin-left: 930px; padding: 10px 28px;" class=" btn btn-primary" href="?page={{page_obj.next_page_number}}">next </a>
{% else %}
<a style="margin-left: 880px; padding: 10px 28px;" class=" btn btn-primary" href="?page={{page_obj.next_page_number}}">next </a>
{% endif %}
{% endif %}
{% endif %}
我正在尝试构建一个允许将照片添加到相册的简单 Django 图库。到目前为止一切正常(上传照片、添加到相册、分页所有照片列表、照片 details/display 页等),直到我尝试显示 'album' 页。我可以获取页面来呈现相册和 所有 相关照片,但是如果我尝试对相册进行分页,事情就会开始变得奇怪。
这是我的模型:
# models.py
class Albums(models.Model):
id = models.AutoField(primary_key=True, unique=True)
name = models.CharField(max_length=500)
slug = models.SlugField(max_length=500, unique=True)
description = models.TextField(blank=True, null=True)
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
return super().save(*args, **kwargs)
class Photos(models.Model):
id = models.AutoField(primary_key=True, unique=True)
album = models.ForeignKey(
Albums, on_delete=models.SET_NULL, null=True, blank=True, verbose_name="Album"
)
photo = models.ImageField(upload_to="photos/")
slug = models.CharField(max_length=16, null=False, editable=False) # I know I'm not using a SlugField here; that's on purpose
title = models.CharField(max_length=500)
description = models.TextField(blank=True, null=True)
upload_date = models.DateTimeField(
default=timezone.now, verbose_name="Date uploaded"
)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
[...] # stuff to get the image's EXIF data and use that to set the slug
self.slug = str(datetime.strftime(img_date, "%Y%m%d%H%M%S"))
[...] # plus a bunch of other stuff that happens on save, not important here
super(Photos, self).save()
def delete(self, *args, **kwargs):
[...] # a bunch of stuff that happens on delete, not important here
super(Photos, self).delete()
让我痛苦的观点:
# views.py
class PhotoAlbum(DetailView):
context_object_name = "album"
model = Albums
slug_field = "slug"
template_name = "page.html"
def get_photos(self, **kwargs):
# get the integer id of the album
a = Albums.objects.filter(slug=self.kwargs["slug"])
a_id = a.values()[0]["id"]
# get the list go photos in that album
photos = Photos.objects.all().order_by("-capture_date").filter(album_id=a_id)
return photos
def get_context_data(self, **kwargs):
context = super(PhotoAlbum, self).get_context_data(**kwargs)
context["photos"] = self.get_photos()
return context
这些在基本模板中工作...
# album.html
<h2>{{ album.name }}</h2>
<p>{{ album.description }}</p>
<ul>
{% for photo in photos %}
<li><a href="{% url 'photo_detail' photo.slug %}">{{ photo.title }}</a></li>
{% endfor %}
</ul>
...但是如果我尝试通过更改...对照片进行分页...
photos = Photos.objects.all().order_by("-capture_date").filter(album_id=a_id)
...到...
photos = Paginator(Photos.objects.all().order_by("-capture_date").filter(album_id=a_id), 10)
...我一无所获
在搜索过程中,我看到的与分页相关的几乎所有问题都是针对 DRF 的,所以在这里有点碰壁。我在显示照片到相册的关系时遇到了各种麻烦(get_photos()
函数),所以我猜我的部分问题在于此。关于如何让它工作有什么建议吗?
Paginator
会给你一个分页器对象,而不是你正在分页的对象。要获取对象,首先需要指定页面,例如:
paginator = Paginator(Photos.objects.all().order_by("-capture_date").filter(album_id=a_id), 10)
photos = paginator.page(1)
photos
此处将包含第 1 页上的 Photos
个对象。
基于 Brian Destura's ListView
and after re-reading the Django docs 和一些乱七八糟的东西,根据我的观点得出了这个解决方案,基于一些测试,它对我有用:
class AlbumDetail(ListView):
context_object_name = "photos"
template_name = "page.html"
paginate_by = 6
def get_queryset(self):
a = Albums.objects.filter(slug=self.kwargs["slug"])
a_id = a.values()[0]["id"]
self.albums = get_object_or_404(Albums, slug=self.kwargs["slug"])
return Photos.objects.filter(album_id=a_id).order_by("-capture_date")
def get_context_data(self, **kwargs):
context = super(AlbumDetail, self).get_context_data(**kwargs)
context["album"] = self.albums
return context
viwes.py
class PhotoAlbum(ListView):
context_object_name = "album"
model = Albums
slug_field = "slug"
template_name = "page.html"
paginate_by = 5
page.html
这是分页逻辑
{%if is_paginated %}
{%if page_obj.has_previous %}
<a style="margin-left: 20px; padding: 10px 20px;" class=" btn btn-primary" href="?page={{page_obj.previous_page_number}}"> {{page_obj.num_pages}} previous</a>
{% endif %}
{%if page_obj.has_next %}
{% if page_obj.num_pages == 1 %}
<a style="margin-left: 930px; padding: 10px 28px;" class=" btn btn-primary" href="?page={{page_obj.next_page_number}}">next </a>
{% else %}
<a style="margin-left: 880px; padding: 10px 28px;" class=" btn btn-primary" href="?page={{page_obj.next_page_number}}">next </a>
{% endif %}
{% endif %}
{% endif %}