如何无需重新登录即可更新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
相关产品推荐
相关产品推荐

