我有一台服务器,可以提供多个应用程序。
请想象我是在两个或多个这些应用程序中注册的用户,并且在访问每个应用程序时使用一个不同的登录信息。
现在,作为该用户,我使用具有不同选项卡的同一浏览器来访问这些应用程序...
第一次登录(对于第一个应用程序),一切都按预期进行,但是当我访问第二个应用程序(作为第二个用户)时,该请求将访问相同的request.session
对象。当我从auth框架调用登录名时,当前用户将与实际request.session
(request.session[SESSION_KEY] != user.id
)中的用户进行比较,并将调用request.session.flush()
。
这意味着我将为访问第一个应用程序的用户松开所有request.session
内容,并且该用户request.session
将被“标记”为从该点开始的第二个用户request.session
。
在这种情况下,我想要的是拥有一个函数/方法,该函数/方法允许为第二个用户创建一个新的request.session
,而将原来的保留为原样。
在第一个答案之后编辑:
首先,谢谢您的回答。
为了避免过于针对性的答案,我试图不做太多详细说明,但是现在我认为我应该这样做:
好的,我之前称为“it”应用程序,但实际上,我的项目服务于请求,以便提供相同的最终“产品”(例如游戏)。
(我的项目中有多个django应用程序。每个应用程序都有特定的方向和后端,具体取决于所应用的业务考虑因素。)
如果我告诉我我有不同的入口点URL,请使用正确的业务后端以处理请求并检索游戏,这将更加详细。
我的主要URL是相同的( namespace ),并且我的项目只有一个设置文件。
最佳答案
根据您是否已准备好更改“用例”,您的问题可能会有几个答案:
a)您不能更改用例:这是不可能的,因为一个Django session 绑定(bind)到一个浏览器 session ,无论是几个浏览器窗口实例还是选项卡。
b)您可以更改用例:用户仍然可以使用多个浏览器(或配置文件(或chrome/chromium中的私有(private)浏览模式))实现此目的,而无需对代码进行任何修改。
c)您可以在网站上实现“用户”切换功能,该功能允许用户在同一 session 中的不同窗口中拥有多个事件配置文件,其目的类似于github Organization-switch功能或facebook page/organization-switch但是您可以在多个选项卡中拥有多个用户的个人资料,而在github或facebook上却不是。
要实现,请执行以下操作:c),您需要在“用户”模型上附加一个“SubProfile”模型实例,并根据查询字符串参数在每个传入请求上激活正确的SubProfile,并在请求中保留子配置文件信息。
1)我想您已经有一个类似于Subprofile
的模型,该模型具有django.contrib.auth.models.User
的外键,您可能还拥有一个允许用户更改其子配置文件的 View 。为了使子配置文件切换正常工作,它需要将信息保留在当前选项卡 session 中所使用的子配置文件中,因为它需要在查询字符串中添加参数,因为它是绑定(bind)选项卡的唯一位置,而不是用户的位置- session 。例如“subprofile = 123”。您需要使用form等正确验证子配置文件,该 View 如下所示:
def select_subprofile(request):
if request.method == 'POST':
form = SubProfileSelectForm(request)
if form.is_valid():
subprofile = form.cleaned_data['subprofile']
url = '%s?subprofile' % (reverse('homepage'), subprofile)
return redirect(url) # the redirect is something like '/homepage?subprofile=123'
else:
form = SubProfileSelectForm()
return render(request, 'myapp/subprofile_select.html', {'form':form})
该 View 可以是每个游戏的首页。
2)之后,您需要检索当前选项卡的用户子配置文件。
为此,我们将在middleware中使用查询字符串(如果您不知道它是什么,请查找howtos on SO和example middlewares bundled with Django)可用于将当前
SubProfile
实例附加到request.user
。中间件将为每个传入请求将与在查询字符串中找到的当前子轮廓信息相对应的SubProfile实例附加到当前用户对象,中间件如下所示:class SubProfileMiddleware(object):
def process_request(self, request):
subprofile = request.GET.get('subprofile', None)
if subprofile:
# it's important to check for user here or malicious users will be
# able to use Subprofiles of other users
subprofile = Subprofile.objects.filter(user=request.user, id=subprofile)
# This can also be written
# subprofile = request.user.subprofile_set.filter(id=subprofile)
if not subprofile:
# this is a malicious user
raise Http403
else:
request.user.subprofile = subprofile
else:
# set default subprofile
request.user.subprofile = self.user.default_subprofile
这样,您可以在应用程序的每个 View 中访问
SubProfile
的subprofile
属性上的request.user
实例。如果存在有效的查询字符串subprofile=123
,则用户将激活这些子配置文件,否则将是默认的子配置文件。假设您的应用程序是一个具有
Organization
模型的应用程序,每个模型都有实例墙,用户可以在该实例上使用子配置文件发布消息,在墙上发布消息的功能具有以下签名post_on_organization_wall(subprofile, message, organization)
,使用该功能的 View 将如下所示这:def organization_wall_post(request, organization):
organization = Organization.objects.get_object_or_404(organization)
if request.method == 'POST':
form = MessageForm(request.POST)
if form.is_valid():
post_on_organization_wall(request.user.subprofile, message, organisation)
else:
form = MessageForm()
return render(request, 'organisation/wall_post.html', {'form': form})
3)现在,您需要在请求中保留子配置文件信息。最简单的方法是将对
{% url %}
的所有调用替换为您自己的url
模板标记,该标记会检查子配置文件 key 的请求查询字符串是否存在并将其添加到请求的url中。您可以重用the code of Django's url template tag。