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

如何无需重新登录即可更新Django的users_servizi_list视图?

问题描述

我开发了一个Django应用,功能如下:

  • 普通用户可在首页查看服务列表,点击服务查看详情后返回首页;
  • 用户可通过Django Admin完成注册与登录;
  • 新用户仅能看到服务列表,当用户查看某服务时,应用通过django-tracking2记录访问URL,并基于文本分析与相似度展示推荐内容。

当前问题:已登录用户查看新服务后,需退出再重新登录才能看到更新后的推荐,推测Django未重新加载users_servizi_list视图。


urls.py

from django.contrib import admin
from django.urls import path, include
from rs import views
from django.conf import settings
from django.conf.urls.static import static
from django.urls import re_path

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.index, name="index"),
    path('static', views.static, name='static'),
    path('users/index', views.users_servizi_list, name='user_index'),
    path('users/detail/<int:pk>/', views.user_dettaglio, name='user_dettaglio'),
    path('accounts/', include('django.contrib.auth.urls')),
    path('sign_out', views.sign_out, name='logout'),
    path('index', views.servizi_list, name='servizi'),
    path('detail/<int:pk>/', views.dettaglio, name='dettaglio'),
    re_path(r'^tracking/', include('tracking.urls')),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

views.py

from django.shortcuts import render
from django.http import HttpResponse
from django.conf import settings
from django.conf.urls.static import static
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.decorators import login_required
from .models import Services
from django.http import HttpResponse, HttpResponseRedirect
from django.template import loader
from tracking.models import Visitor, Pageview
from django_pandas.io import read_frame
from sentence_transformers import SentenceTransformer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.cluster import KMeans
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.decomposition import PCA
import pandas as pd
import numpy as np
import pickle


def login(request):
    return render(request, 'users/login.html')

@login_required
def sign_out(request):
    logout(request)
    messages.success(request,f'You have been logged out.')
    return redirect('index')   

@login_required
def user_index(request):
    return render(request, 'users/index.html')

def servizi_list(request):
    service_list = list(Services.objects.all())
    template = loader.get_template('index.html')
    
    context = {
        'servizi': service_list,
    }

    return HttpResponse(template.render(context, request))


def dettaglio(request, pk: int):
    query_service = Services.objects.filter(id=pk)
    
    template = loader.get_template('detail.html')
    
    context = {
        'servizio': query_service,
    }
    
    return HttpResponse(template.render(context, request))

@login_required
def user_dettaglio(request, pk: int):
    query_service = Services.objects.filter(id=pk)
    
    template = loader.get_template('users/detail.html')
    
    context = {
        'servizio': query_service,
    }
    
    return HttpResponse(template.render(context, request))

############# recommendation engine  ###############
def give_recommendations(index, data, cos_sim_data, print_recommendation = False,print_recommendation_plots= False,print_genres=False): 
  index_recomm = cos_sim_data.loc[index].sort_values(ascending=False).index.tolist()[1:6]
  index_recomm = [int(x) for x in index_recomm]
  
  service_recomm =  data['servizio'].loc[index_recomm].values
  id_recomm =  data['id'].loc[index_recomm].values

  result = {'Service': service_recomm, 'Index':index_recomm}
   
  return id_recomm 


def rs_engine(user_id):
    session_key = Visitor.objects.filter(user_id=user_id).filter(end_time__isnull=False).order_by('-end_time')   
    
    if not session_key:  
        return [-1]
    else:
        for sss_kv in session_key:
            url_visited = Pageview.objects.filter(visitor_id=sss_kv).order_by('-view_time')
            print('url vis: ', url_visited)
            
            for u in url_visited:
                print('url visitato: ', u.referer)
                target = u.referer
                target_id = target.split('/')
                service_target = target_id[-2]
                check_service = service_target.isnumeric()
                if check_service == True:
                    serviceTarget = int(service_target)
                    #print('service tag Identificato: ', serviceTarget)
                    break
                else:
                    pass 
                
            if check_service == True:
                serviceTarget = int(service_target)
                break
            else:
                return [-1]

           
    services = Services.objects.all()
    data = read_frame(services)

    X = []

    for el in data.descrizione:
        X.append(str(el))
        
    model = SentenceTransformer('all-MiniLM-L6-v2')
    #embeddings = model.encode(X, show_progress_bar=True)
    #print('emb batches: ', type(embeddings), embeddings[0:10]) 
    
    
    #Store sentences & embeddings on disc
    #with open('../rsRegionePuglia/static/embeddings.pkl', "wb") as fOut:
    #    pickle.dump({'sentences': X, 'embeddings': embeddings}, fOut, protocol=pickle.HIGHEST_PROTOCOL)

    #Load sentences & embeddings from disc
    with open('../rsRegionePuglia/static/embeddings.pkl', "rb") as fIn:
        stored_data = pickle.load(fIn)
        stored_sentences = stored_data['sentences']
        stored_embeddings = stored_data['embeddings']
    
    #print('emb loaded: ', type(stored_embeddings), stored_embeddings[0:10])
    
    x = np.array(X)

    #cos_sim_data = pd.DataFrame(cosine_similarity(embeddings))
    # salva la cos sim in un file csv
    #cos_sim_data.to_csv('../rsRegionePuglia/static/cos_sim.csv', index=False)
    
    cos_sim_data = pd.read_csv('../rsRegionePuglia/static/cos_sim.csv')
    #print('target id: ', service_target)
    
    mapping = {}
    for i in range(0, len(services)):
        mapping[data.id[i]] = i
    
    service_start = mapping[serviceTarget]

    sugg = give_recommendations(service_start, data, cos_sim_data, True) #service_target
    return sugg
   

@login_required
def users_servizi_list(request):
    service_list = list(Services.objects.all())
    template = loader.get_template('users/index.html')
    
    current_user = request.user
    user_id = current_user.id

    rs = rs_engine(user_id)
    rs = rs[1:]

    if rs==[] or rs[0] == -1:
        context = {
            'servizi': service_list,
            'new_user': 1,
        }
        return HttpResponse(template.render(context, request))
    else:
        descr = []
        
        for id in rs:
            service = Services.objects.get(pk=id)
            descr.append(service.servizio)
        
        servizi = {}
        for i in range(1, len(rs)):
            servizi[rs[i]] = descr[i] 
        
        context = {
            'servizi': service_list,
            'recom': servizi,
            'new_user': 0,
        }
        
        current_user = request.user
        
        return HttpResponse(template.render(context, request))

index.html

{% extends "base.html" %}
{%load static%}

{%block blk%}

{% if new_user == 0 %}
Ti potrebbe interessare:


    {% for key, values in recom.items %}
        <a class="read-more" href="{% url 'user_dettaglio' pk=key %}">{{values}}</a>
    {% endfor %}

    {% for x in servizi %}
      {% include "users/service_card.html" %}
    {% endfor %}

{% else %}

    {% for x in servizi %}
      {% include "users/service_card.html" %}
    {% endfor %}

{%endif%}            

{%endblock%}

service_card.html

{%load static%}

<div class="container my-4">
    <div class="my-5">
      <div class="container">
        <div class="row">
          <div class="col-12 col-md-6 col-lg-4">
            <!--start card-->
            <div class="card-wrapper card-space">
              <div class="card card-bg card-big">
                <div class="card-body">
                  <div class="top-icon">
                    <svg class="icon">
                      <use href="{% static 'js/svg/sprites.svg#it-card' %}"></use>
                    </svg>
                  </div>
                  <h3 class="card-title h5 ">{{ x.categoria }}</h3>
                  <p class="card-text">{{ x.servizio }}</p>
                  <p class="card-text">{{ x.descrizione }}</p>
                  <p class="card-text">{{ x.tag }}</p>
                  
                  <a class="read-more" href="{% url 'user_dettaglio' pk=x.id %}">
                    <span class="text">Leggi di più</span>
                    <span class="visually-hidden">su Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
                      eiusmod tempor…</span>
                    <svg class="icon">
                      <use href="{% static '/svg/sprites.svg#it-arrow-right' %}"></use>
                    </svg>
                  </a>
                </div>
              </div>
            </div>
            <!--end card-->
          </div>
        </div>
      </div>
    </div>
    
    </div>
  </div>

解决方案思路

1. 修复会话数据获取逻辑

当前rs_engine只筛选了已结束的会话(end_time__isnull=False),但用户查看服务后,当前活跃会话的Pageview记录不会被纳入查询。修改session_key查询条件,包含所有会话并优先取最新的:

def rs_engine(user_id):
    # 去掉end_time筛选,按会话开始时间倒序,优先取最新会话
    session_key = Visitor.objects.filter(user_id=user_id).order_by('-start_time')
    # 后续逻辑...

2. 强制刷新首页

用户从详情页返回时,浏览器可能缓存旧页面。修改user_dettaglio视图,重定向到用户首页,确保重新调用users_servizi_list:

from django.urls import reverse

@login_required
def user_dettaglio(request, pk: int):
    query_service = Services.objects.filter(id=pk)
    # 先渲染详情页,再重定向到首页;若无需保留详情页状态,可直接return redirect('user_index')
    response = render(request, 'users/detail.html', {'servizio': query_service})
    return HttpResponseRedirect(reverse('user_index'))

3. 禁用视图缓存

添加never_cache装饰器,防止Django或浏览器缓存users_servizi_list的结果:

from django.views.decorators.cache import never_cache

@login_required
@never_cache
def users_servizi_list(request):
    # 原视图逻辑...

4. 优化访问记录提取逻辑

确保获取用户最后一次有效访问的服务ID,而不是找到第一个就终止循环:

def rs_engine(user_id):
    session_key = Visitor.objects.filter(user_id=user_id).order_by('-start_time')   
    serviceTarget = None
    
    if not session_key:  
        return [-1]
    
    for sss_kv in session_key:
        url_visited = Pageview.objects.filter(visitor_id=sss_kv).order_by('-view_time')
        for u in url_visited:
            target = u.referer
            if not target:
                continue
            target_id = target.split('/')
            if len(target_id) < 2:
                continue
            service_target = target_id[-2]
            if service_target.isnumeric():
                serviceTarget = int(service_target)
                break  # 找到最新的有效记录就退出
        if serviceTarget is not None:
            break
    
    if serviceTarget is None:
        return [-1]
    
    # 原推荐计算逻辑...

5. 手动触发会话结束(可选)

若需要确保会话数据及时写入数据库,可在用户查看服务后手动结束当前会话(不建议频繁操作,避免影响正常会话跟踪):

from django.utils import timezone

@login_required
def user_dettaglio(request, pk: int):
    query_service = Services.objects.filter(id=pk)
    # 手动结束当前活跃会话
    visitor = Visitor.objects.get(user=request.user, end_time__isnull=True)
    visitor.end_time = timezone.now()
    visitor.save()
    return render(request, 'users/detail.html', {'servizio': query_service})

内容的提问来源于stack exchange,提问作者Giuseppe Ricci

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 04:52:02