5

我有一个服务器,它提供了几个应用程序。

请想象我是在 2 个或更多这些应用程序中注册的用户,并且在访问每个应用程序时我使用不同的登录信息。

现在,作为该用户,我使用具有不同选项卡的同一浏览器来访问这些应用程序...第一次记录(对于第一个应用程序)一切都按预期进行,但是当我访问第二个应用程序(作为第二个用户)时,该请求将访问同一个request.session对象。当我调用登录(来自 auth 框架)时,当前用户将与实际request.sessionrequest.session[SESSION_KEY] != user.id)中的用户进行比较,request.session.flush()并将被调用。

这意味着我将丢失request.session访问第一个应用程序的用户的所有内容,并且从那时起,同一用户request.session将被“标记”为第二个用户request.session

在这种情况下,我想要的是有一个函数/方法,允许request.session为第二个用户创建一个新的,而保持原来的状态。

第一个答案后编辑:首先感谢您的回答。为了避免过于有针对性的答案,我试图不详细说明,但现在我认为我应该这样做:

好的,我之前曾称其为“它”应用程序,但实际上,我的项目服务请求是为了提供相同的最终“产品”(例如游戏)。(我的项目中有几个 django 应用程序。每个应用程序都有特定的方向和后端取决于应用的业务考虑。)

如果我告诉我有不同的入口点 URL,使用正确的业务后端来处理请求并检索游戏,那将会更详细。

我的主 URL 是相同的(命名空间),我的项目只有一个设置文件。

在此处输入图像描述

4

2 回答 2

2

根据您是否准备好更改“用例”,您的问题可能有几个答案:

a)您不能更改用例:这是不可能的,因为一个 Django 会话绑定到一个浏览器会话,无论是多个浏览器窗口实例还是选项卡。

b)您可以更改用例:用户仍然可以使用多个浏览器(或配置文件(或 chrome/chromium 中的隐私浏览模式))来实现此目的,而无需对您的代码进行任何修改。

c)您可以在您的网站中实现“用户”切换功能,允许用户在不同窗口的同一会话中拥有多个活动配置文件,其目的类似于 github 组织切换功能或 facebook 页面/组织切换但你可以在多个选项卡中拥有多个用户的个人资料,这在 github 或 facebook 上并非如此。

要实现c)您需要将“SubProfile”模型实例附加到您的“用户”模型,并根据查询字符串参数在每个传入请求上激活正确的子配置文件,并在请求之间保留子配置文件信息。

1)我猜你已经有Subprofile一个带有外键的模型django.contrib.auth.models.User,你可能还有一个允许用户更改其子配置文件的视图。为了使子配置文件切换工作,它需要在当前选项卡会话中保留它正在使用的子配置文件中的信息,因为它需要在查询字符串中添加一个参数,因为它是绑定选项卡而不是用户的唯一位置-会议。例如“子配置文件=123”。您需要使用表单等正确验证子配置文件,视图如下所示:

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})

这个视图可以是每个游戏的第一页。

2)之后,您需要为当前选项卡检索用户的子配置文件。为此,我们将在中间件中使用查询字符串(如果您不知道它是什么,请查找SO与 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

这样,您可以在应用程序的每个视图SubProfilesubprofile访问request.user. 如果存在有效的查询字符串subprofile=123,用户将激活这些子配置文件,如果没有,则为默认子配置文件。

假设您的应用程序是具有Organization模型的应用程序,其中每个实例都有墙,用户可以使用子配置文件在其上发布消息,在墙上发布消息的功能具有以下签名post_on_organization_wall(subprofile, message, organization),使用此功能的视图将如下所示:

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模板标签,该标签检查请求查询字符串是否存在子配置文件键并将其添加到请求的 url。您可以重用Django 的 url 模板标签的代码

于 2012-09-24T19:50:44.277 回答
0

如果我正确理解您的问题,那么问题是您在应用程序之间共享会话,即使用户不同。您应该能够通过在 settings.py 中设置 SESSION_COOKIE_DOMAIN、SESSION_COOKIE_PATH 或 SESSION_COOKIE_NAME 来解决此问题,以确保您的应用程序不会破坏其他会话。

于 2012-09-24T14:53:06.267 回答