简体   繁体   中英

Allow user to select random blog bost

I've started using Django 2.0 and Python 3.6.3 to develop a website which will display customized "Posts", as in a blog Post.

I want the user to be able to click a button that basically says "Random Post". This button will take them to a template which loads a random blog post.

Here's my Post model:

class Post(models.Model):
    post_id = models.AutoField(primary_key=True)
    ... other fields
    ... other fields

    def publish(self):
        self.published_date = timezone.now()
        self.save()

    def __str__(self):
        return self.title     

Here are some relevant views:

class PostListView(ListView):
    model = Post
    template_name = 'blog/post_list.html'

class PostDetailView(DetailView):
    model = Post
    template_name = 'blog/post_detail.html'

Here is my problematic view:

import random

def random_post(request):
    post_ids = Post.objects.all().values_list('post_id', flat=True) 
    random_obj = Post.objects.get(post_id=random.choice(post_ids))
    context = {'random_post': random_obj,}
    return render(request, 'blog/random_post.html', context)

Here I am trying to create a Values List of all post_id values for the Post model. Then I'm trying to get a random choice from this Values List, which would be a random id. Then I'm trying to create a context and render a template using this logic.

Here are relevant urlpatterns:

urlpatterns = [
    path('post/<int:pk>/', 
        views.PostDetailView.as_view(),name='post_detail'),
    path('post/random/<int:pk>', views.random_post, name='random_post'),

Needless to say this is not working.

If I leave off the "int:pk" it renders a blank template with no data - no blog Post. If I include the , it causes an error - No Arguments Found. I assume that no data is being queried in the view, or the data isn't being properly sent from the view to the template.

I am new to Django. I appreciate your help!

For the behaviour you want, your URLs should be:

urlpatterns = [
    path('post/random/', views.random_post, name='random_post'),
    path('post/<int:pk>/', 
        views.PostDetailView.as_view(),name='post_detail'),
]

and your random_post view is:

def random_post(request):
    post_count = Post.objects.all().count()
    random_val = random.randint(1, post_count-1)
    post_id = Post.objects.values_list('post_id', flat=True)[random_val]
    return redirect('post_detail', pk=post_id)

This makes two queries - one to get the count of all posts, and one to get ID of the post in the random position. The reason for doing this is that then you don't have to get all of the IDs from the database - if you have thousands of posts, that would be very inefficient.

Here's the view that works.

def random_post(request):
    post_count = Post.objects.all().count()  
    random_val = random.randint(0, post_count-1)  
    post_id = Post.objects.values_list('post_id', flat=True)[random_val]   
    return redirect('post_detail', pk=post_id) #Redirect to post detail view

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM