You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中实现基于用户博客行为的个性化博客推荐功能?

Been there, done that — django-recommends docs are notoriously sparse, so I feel your pain. Let’s walk through a practical, self-implemented solution that’s easy to tweak and maintain for your blog recommendation feature.

Practical Django Blog Recommendation Implementation

We’ll break this into 5 actionable steps, starting with tracking user behavior, then building the recommendation logic, and finally displaying the results.

1. Model Setup for User Behavior Tracking

First, we need to define models to capture the user actions you mentioned: search queries, blog reads, and category follows. Assuming you already have Blog and Category models set up (with a foreign key or many-to-many link between them), add these to your app’s models.py:

from django.db import models
from django.contrib.auth.models import User
from .models import Blog, Category  # Import your existing core models

class UserSearch(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="search_history")
    query = models.CharField(max_length=255)
    timestamp = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-timestamp"]

class UserBlogRead(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="read_blogs")
    blog = models.ForeignKey(Blog, on_delete=models.CASCADE, related_name="read_by_users")
    read_count = models.PositiveIntegerField(default=1)
    last_read = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = ["user", "blog"]  # Prevent duplicate entries for the same user-blog pair

class UserCategoryFollow(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="followed_categories")
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="followed_by_users")

    class Meta:
        unique_together = ["user", "category"]

Run migrations to apply these changes:

python manage.py makemigrations
python manage.py migrate

2. Collecting User Behavior Data

Now hook these models into your existing views to capture user actions automatically.

Tracking Search Queries

In your search view, save the query whenever an authenticated user searches:

from django.shortcuts import render
from .models import Blog, UserSearch

def search_blogs(request):
    query = request.GET.get("q", "")
    if query and request.user.is_authenticated:
        # Save the search term for logged-in users
        UserSearch.objects.create(user=request.user, query=query)
    
    # Your existing search logic to fetch matching blogs
    blogs = Blog.objects.filter(title__icontains=query) | Blog.objects.filter(content__icontains=query)
    return render(request, "search_results.html", {"blogs": blogs, "query": query})

Tracking Blog Reads

In your blog detail view, update or create a read record when a user views a blog:

from django.shortcuts import get_object_or_404
from .models import Blog, UserBlogRead

def blog_detail(request, blog_id):
    blog = get_object_or_404(Blog, id=blog_id)
    
    if request.user.is_authenticated:
        # Update read count if user has viewed this blog before, else create a new entry
        read_entry, created = UserBlogRead.objects.get_or_create(user=request.user, blog=blog)
        if not created:
            read_entry.read_count += 1
            read_entry.save()
    
    return render(request, "blog_detail.html", {"blog": blog})

Tracking Category Follows

Add a view to handle category follow/unfollow actions (link this to a button in your template):

from django.http import JsonResponse
from .models import Category, UserCategoryFollow

def toggle_category_follow(request, category_id):
    if not request.user.is_authenticated:
        return JsonResponse({"status": "error", "message": "Login required"}, status=401)
    
    category = get_object_or_404(Category, id=category_id)
    follow_entry, created = UserCategoryFollow.objects.get_or_create(user=request.user, category=category)
    
    if not created:
        follow_entry.delete()
        return JsonResponse({"status": "success", "action": "unfollowed"})
    else:
        return JsonResponse({"status": "success", "action": "followed"})

3. Building the Recommendation Logic

We’ll start with a simple, content-based recommendation system (effective for blogs and easy to iterate on). This prioritizes blogs from categories the user follows, plus similar blogs to those they’ve read.

Add this function to your app’s utils.py (or directly in your views if you prefer):

from django.db.models import Q, Count
from .models import Blog, UserCategoryFollow, UserBlogRead

def get_recommended_blogs(user, limit=5):
    if not user.is_authenticated:
        # For anonymous users, return popular blogs (most read)
        return Blog.objects.annotate(read_count=Count("read_by_users")).order_by("-read_count")[:limit]
    
    # Get categories the user follows
    followed_category_ids = user.followed_categories.values_list("id", flat=True)
    
    # Get blogs the user has already read (to avoid duplicate recommendations)
    read_blog_ids = user.read_blogs.values_list("blog__id", flat=True)
    
    # First, recommend blogs from followed categories (exclude read ones)
    recommended = Blog.objects.filter(
        category__id__in=followed_category_ids
    ).exclude(id__in=read_blog_ids)
    
    # If we don't have enough recommendations, add blogs similar to read ones (same category)
    if recommended.count() < limit:
        read_blog_category_ids = user.read_blogs.values_list("blog__category__id", flat=True)
        similar_blogs = Blog.objects.filter(
            category__id__in=read_blog_category_ids
        ).exclude(id__in=read_blog_ids).exclude(id__in=recommended.values_list("id", flat=True))
        recommended = recommended | similar_blogs
    
    # If still not enough, add popular blogs as a fallback
    if recommended.count() < limit:
        popular_blogs = Blog.objects.annotate(read_count=Count("read_by_users")).order_by("-read_count").exclude(id__in=read_blog_ids).exclude(id__in=recommended.values_list("id", flat=True))
        recommended = recommended | popular_blogs
    
    # Return distinct top N recommendations
    return recommended.distinct()[:limit]

4. Displaying Recommendations on the Homepage

In your homepage view, call the recommendation function and pass results to the template:

from django.shortcuts import render
from .utils import get_recommended_blogs

def homepage(request):
    recommended_blogs = get_recommended_blogs(request.user)
    # Your existing homepage logic (e.g., latest blogs)
    latest_blogs = Blog.objects.order_by("-published_date")[:10]
    return render(request, "homepage.html", {
        "latest_blogs": latest_blogs,
        "recommended_blogs": recommended_blogs
    })

Then render the "推荐博客" section in your homepage.html template:

<div class="recommended-blogs">
    <h2>推荐博客</h2>
    {% if recommended_blogs %}
        <div class="blog-list">
            {% for blog in recommended_blogs %}
                <div class="blog-card">
                    <h3><a href="{% url 'blog_detail' blog.id %}">{{ blog.title }}</a></h3>
                    <p>{{ blog.excerpt|truncatechars:100 }}</p>
                    <span class="category-tag">{{ blog.category.name }}</span>
                </div>
            {% endfor %}
        </div>
    {% else %}
        <p>暂无推荐内容,快去探索更多博客吧!</p>
    {% endif %}
</div>

5. Optimization Tips

  • Cache Recommendations: For authenticated users, cache results for 1-2 hours to reduce database load. Example:
    from django.core.cache import cache
    
    def get_recommended_blogs(user, limit=5):
        cache_key = f"recommendations_{user.id}"
        cached_recs = cache.get(cache_key)
        if cached_recs:
            return cached_recs
        
        # Existing recommendation logic...
        
        cache.set(cache_key, recommended, 60*60*2)  # Cache for 2 hours
        return recommended
    
  • Background Tasks: For high-traffic sites, use tools like Celery to update read counts asynchronously instead of on every request.
  • Advanced Algorithms: Once you have enough user data, expand to collaborative filtering (e.g., "Users who read this also read...") using simple count-based logic, or integrate lightweight ML libraries like scikit-learn for more complex models.

内容的提问来源于stack exchange,提问作者Mr. Nobody

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 23:17:35