Python:如何在django中"分叉"一个会话

sam*_*_pt 5 python authentication django session login

我有一台服务器可以提供多个应用程序.

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

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

这意味着我将丢失request.session访问第一个应用程序的用户的所有内容,并且该用户request.session将被"标记" request.session为该点的第二个用户.

在这种情况下,我想要的是有一个功能/方法,允许request.session为第二个用户创建一个新的,保留原始的原样.

在第一个答案后编辑:首先,谢谢你的答案.我试图不要过多地详细说明,以避免过于明确的答案,但现在我认为我应该这样做:

好吧,我以前称之为"it"应用程序,但事实上,我的项目提供请求以提供相同的最终"产品"(例如游戏).(我的项目中有几个django应用程序.每个应用程序具有特定的方向和后端,取决于应用的业务考虑因素.)

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

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

在此输入图像描述

ami*_*che 2

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

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

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

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

要实现c),您需要将“SubProfile”模型实例附加到“User”模型,并根据查询字符串参数在每个传入请求上激活正确的 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})
Run Code Online (Sandbox Code Playgroud)

该视图可以是每个游戏的首页。

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
Run Code Online (Sandbox Code Playgroud)

这样,您就可以在应用程序的每个视图中访问属性SubProfile上的实例。如果存在有效的查询字符串,则用户将使这些子配置文件处于活动状态,如果没有,则为默认子配置文件。subprofilerequest.usersubprofile=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})
Run Code Online (Sandbox Code Playgroud)

3)现在您需要跨请求保留子配置文件信息。最简单的方法是将 everycall 替换为{% url %}您自己的url模板标记,该标记检查请求查询字符串是否存在子配置文件密钥并将其添加到请求的 url 中。你可以复用Django的url模板标签的代码