Django中按月份和年份分类帖子

weylhg0b  于 2023-05-19  发布在  Go
关注(0)|答案(1)|浏览(135)

我是一个Django的新手,我正在做一个有很多尝试和错误的项目。这有个案子我想在我的网站上实现这一点:
arc asia
每个条目都将有按月份和年份分组的帖子。如果我点击,我会看到一堆关于那个月和那个年的帖子。
我的网站现在只有4篇文章,都是去年9月发布的。我设法做到的外观是以下,这显然是错误的,因为2022年9月应该是一个单一的条目。必须有一些方法来做的组,但我似乎不能实现这一点:
group
我想用一个存档视图来做,因为我在那个尝试中失败了,我正在这样做。我想知道两种方法。以下是相关文件:

blog/models.py

class News(models.Model):
    STATUS_CHOICES = (
        ('draft', 'Draft'),
        ('published', 'Published'),
    )
    news_title = models.CharField(max_length=250)
    null=True)
    slug = models.SlugField(max_length=300, unique_for_date='nw_publish')
    news_author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='news_posts')
    news_body = RichTextField()
    image_header = models.ImageField(upload_to='featured_image/%Y/%m/%d/', null=True, blank=True)  # this

    nw_publish = models.DateTimeField(default=timezone.now)
    nw_status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
    tags = TaggableManager()

    def __unicode__(self):
        return '%name' % {'name': self.news_title}

    class Meta:
        ordering = ('nw_publish',)

    def __str__(self):
        return self.news_title

    def get_absolute_url(self):
        return reverse('news:news_detail', args=[self.slug])
blog/views.py

class NewsListView(TagMixin, ListView):
    model = News
    queryset = News.objects.all()
    context_object_name = 'newss'
    template_name = 'blog/news.html'

class NewsDetailView(TagMixin, DetailView):
    model = News
    date_field = "nw_publish"
    context_object_name = 'news'
    template_name = 'blog/news_detail.html'

    def get_context_data(self, *, object_list=None, **kwargs):
        data = super().get_context_data(**kwargs)
        data['news_details_view'] = News.objects.all()
        data['news_years'] = News.objects.annotate(year=ExtractYear('nw_publish')).values('year').annotate(total_entries=Count('year'))
        return data

class NewsTagView(TagMixin, ListView):
    model = News
    context_object_name = 'newss'
    template_name = 'blog/news.html'

    def get_queryset(self):
        return News.objects.filter(tags__slug=self.kwargs.get('tag_slug'))

class NewsYearArchiveView(YearArchiveView):
    context_object_name = 'news_years'
    date_field = "nw_publish"
    year_format = '%Y'
    make_object_list = True
    allow_future = True
    queryset = News.objects.filter(nw_status='published').order_by('nw_publish', 'news_title')
blog/urls.py

from django.urls import path, re_path

from . import views
from .views import Home, HomeDetail, Contact, ReportListView, ReportDetailView, NewsListView, NewsDetailView, \
    MemberListView, ProjectListView, ProjectDetailView, SearchView, ReportYearArchiveView, PhotoGallery, AboutDetail, \
    VideoGallery, FCListView, ReportTagView, NewsTagView, NewsYearArchiveView
from django.views.generic.base import RedirectView

# , Gallery

app_name = 'blog'
urlpatterns = [
    # post views

    path('', Home.as_view(), name='home'),
    path("search", SearchView.as_view(), name='search'),
    path('home/<slug:slug>/', HomeDetail.as_view(), name='details'),
    path('news/', NewsListView.as_view(), name='news_list'),
    path('news/<slug:slug>/', NewsDetailView.as_view(), name='news_detail'),
    path('news/taggit/tag/<slug:tag_slug>/', NewsTagView.as_view(), name='post_tag'),
    path('news/<int:year>/', NewsYearArchiveView.as_view(), name="news_year_archive"),
    
]
templates/news_details.html

{% extends 'base.html' %}

{% load static %}
{% block container %}
    <div class="stricky-header stricked-menu main-menu">
        <div class="sticky-header__content"></div><!-- /.sticky-header__content -->
    </div><!-- /.stricky-header -->
    <!--News Details Start-->
    ...
   
                        <div class="sidebar__single sidebar__category">
                            <h3 class="sidebar__title">Archives</h3>

                            <ul class="sidebar__category-list list-unstyled">
                                 {% for y in news_years %}
                                <li><a href={{ y.get_absolute_url }}><i class="fas fa-arrow-circle-right"></i>{{ y }}</a></li>
                               {% endfor %}
                            </ul>
                        </div>
                        <div class="sidebar__single sidebar__tags">
                            <h3 class="sidebar__title">Popular Tags</h3>

                            <div class="sidebar__tags-list">
                                {% for tag in tags %}
                                <a href="{% url 'blog:post_tag'  tag.slug %} ">{{ tag.name }}</a>
                               {% endfor %}
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>
    <!--News Details End-->
{% endblock %}

我想做的是:
1.将所有相同月份和年份的帖子组合在一起
1.使列表可点击
1.点击后显示文章列表(如何获得此列表?)
对不起,我是一个新手,我不知道Django的muuch;我还在学习,因此我被这个问题卡住了。
我想做的是:
将所有相同月份和年份的帖子合并在一起,使列表可点击,在点击后显示帖子列表(如何获得此列表?)对不起,我是一个新手,我不知道Django的muuch;我还在学习,因此我被这个问题卡住了。

zz2j4svz

zz2j4svz1#

唯一缺少的是**.order_by()**[Django-doc](是的,我知道这很奇怪),这将强制执行GROUP BY语句:

data['news_years'] = (
    News.objects.annotate(year=ExtractYear('nw_publish'))
    .values('year')
    .annotate(total_entries=Count('year'))
    .order_by()
)

至于使用months,最好使用 truncate 而不是extract,因为这样你仍然有一个date对象:

from django.db.models.functions import TruncMonth

data['news_years'] = (
    News.objects.values(month=TruncMonth('nw_publish'))
    .annotate(total_entries=Count('year'))
    .order_by()
)

点击后显示文章列表(如何获得此列表?)
您可以创建一个包含年份和月份的路径:

path(
    'posts/<int:year>/<int:month>/', SomeListView.as_view(), name='posts-by-month'
),

然后在模板中链接到以下内容:

{% for news_year in news_years %}
    <a href="{% url 'posts-by-month' news_year.month.year news_year.month.year %}">{{ news_year.month }} ({{ news_year.total_entries }})</a>
{% endfor %}

SomeListView中,您可以使用以下过滤:

class SomeListView(ListView):
    model = News

    def get_queryset(self, *args, **kwargs):
        return (
            super()
            .get_queryset(*args, **kwargs)
            .filter(
                nw_publish__year=self.kwargs['year'],
                nw_publish__month=self.kwargs['month'],
            )
        )

相关问题