(django) 根据用户的兴趣显示帖子

(django) Showing posts according to interests of users

我是 Django 的新手并且还在学习它,但我必须创建类似 medium.com 的东西。我想根据用户的兴趣向他们展示帖子。我在注册表单中添加了一个带有复选框的兴趣字段。当然,我在 Post 模型中添加了一个类别。那么,我怎样才能显示(仅对登录用户)他们感兴趣的出版物? 这是我在 posts app

中的 models.py 文件
from django.db import models
from django.utils import timezone
from django.urls import reverse
# Create your models here.
class Post(models.Model):
    CATEGORY = (
        ('sport', 'Sport'),
        ('science', 'Science'),
        ('it', 'IT'),
        ('art', "Art"),
    )

    
    title = models.CharField(verbose_name="Title for publication", max_length=50)
    category = models.CharField(verbose_name="Category", choices=CATEGORY, max_length=50)
    author = models.ForeignKey("accounts.User", verbose_name="Author:", on_delete=models.CASCADE)
    body = models.TextField(verbose_name="Body for publication")
    pub_date = models.DateTimeField(verbose_name="Date:", auto_now_add=True)
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)


    def get_absolute_url(self):
        return reverse("post_detail", kwargs={"pk": self.pk})
    

    def __str__(self):
        return self.title

这是我在帖子应用程序中的 vies.py 文件

from django.views.generic import ListView, DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from .models import Post
from django.urls import reverse_lazy

class PostListView(ListView):
    model = Post
    template_name = "index.html"    
    def get_queryset(self):
        return Post.objects.order_by('-pub_date')


class PostDetailView(DetailView):
    model = Post
    template_name = "./posts/post_detail.html"

class PostCreateView(CreateView):
    model = Post
    template_name = "./posts/new_post.html"
    fields = '__all__'

class PostUpdateView(UpdateView):
    model = Post
    template_name = "./posts/update_post.html"
    fields = ['body', 'title', 'category']

class PostDeleteView(DeleteView):
    model = Post
    template_name = "./posts/delete_post.html"
    success_url = reverse_lazy('index')


class SportPostListView(ListView):
    model = Post
    template_name = "./posts/sports.html"

class ITPostListView(ListView):
    model = Post
    template_name = "./posts/it.html"

class SciencePostListView(ListView):
    model = Post
    template_name = "./posts/ilm-fan.html"

class ArtPostListView(ListView):
    model = Post
    template_name = "./posts/sanat.html"

这是我的 index.html 文件

{% extends 'base.html' %}
{% block content %}
{% if object_list %}
    {% for post in object_list %}
        <h1>{{ post.title }}</h1>
        <p>{{ post.pub_date }}</p>
        <p>{{ post.author }}</p>
        <p>{{ post.body }}</p>
        <p>{{ post.category }}</p>
    {% endfor %}
{% else %}
    <p>No posts are available.</p>
{% endif %}
{% endblock content %}

这是我在帐户应用程序中的 forms.py 文件

from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django.db import models
from django import forms
class SignUpForm(UserCreationForm):
    INTERESTS = (
        ('sport', 'Sport'),
        ('science', 'Science'),
        ('it', 'IT'),
        ('art', "Art"),
        )
    username = forms.CharField(max_length=128, required=True)
    email = models.EmailField(verbose_name='emailingiz', unique=True, default='')
    first_name = forms.CharField(max_length=128, required=True)
    last_name = forms.CharField(max_length=128, required=True)
    interests = forms.MultipleChoiceField(required=True, widget=forms.CheckboxSelectMultiple, choices=INTERESTS)
    USERNAME_FIELD = 'email'

    class Meta:
        model = User
        fields = ('first_name', 'last_name', 'username', 'email', 'interests', 'password1', 'password2')
    

最后这个 views.py 帐户应用程序中的文件

from django.urls import reverse_lazy
from django.views.generic import CreateView
from .forms import SignUpForm

class SignUpView(CreateView):
    form_class = SignUpForm
    success_url = reverse_lazy('login')
    template_name = 'signup.html'

我不知道该怎么做,但我知道我必须在帖子应用程序的 views.py 文件中做一些事情,但是,我不知道该怎么做。 如果您能帮助我,将不胜感激。

我会制作另一个模型 Category。由于它将是自己的模型,您将能够在需要时即时添加未来的类别,而不是让那些硬编码 choices.

class Category(models.Model):
    name = models.CharField(default=None, blank=True, null=True)

那么您的 UserPost 模型将各自有一个与类别相关的 ManytoMany 字段。帖子在创建时可以标记为特定类别,用户将能够 select 一些他们感兴趣的类别并将它们存储在该字段中:

class User(AbstractBaseUser):
     interests = models.ManytoManyField(Category, default=None, blank=True)
class Post(models.Model):
     categories = models.ManytoManyField(Category, default=None, blank=True)

您可以使用 forms.modelChoiceField 使您的用户能够 select 一个类别。

在您的 PostListView 中,您需要做的就是更改 get_queryset 方法来过滤用户喜欢的帖子。

class PostListView(ListView):
    model = Post
    template_name = "index.html" 
   
    def get_queryset(self):
        user_interests = self.request.user.interests
        return Post.objects.filter(
        categories__in=user_interests).order_by('pub_date')

然后,您应该获取与用户兴趣共享类别的帖子。

这里是错误

Error during template rendering
In template /home/xesos/projects/mw/mw/templates/base.html, error at line 0

too many values to unpack (expected 2)
1   <!DOCTYPE html>
2   <html lang="en">
3   <head>
4       <meta charset="UTF-8">
5       <meta name="viewport" content="width=device-width, initial-scale=1.0">
6       <style>
7           
8       </style>
9       <title>
10          {% block title %}

为了避免这个错误,我在 forms.py 中做了一些更改,这里是

from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django import forms
from posts.models import Category

class SignUpForm(UserCreationForm):
    categories = Category.objects.values_list('name')
    listOfCategory = []
    listOfCategory += categories


    username = forms.CharField(max_length=128, required=True)
    email = forms.EmailField(required=True)
    first_name = forms.CharField(max_length=128, required=True)
    last_name = forms.CharField(max_length=128, required=True)
    USERNAME_FIELD = 'email'
    
    for i in range(0, len(listOfCategory)):
        listOfCategory.append(listOfCategory[i])
    interests = forms.ChoiceField(choices=[(x, x) for x in listOfCategory])

    class Meta:
        model = User
        fields = ('first_name', 'last_name', 'username', 'email', 'interests', 'password1', 'password2')