在Django中,会话变量丢失了

3
在一个应该支持多公司的系统中,我使用context_processors.py加载公司选项,从侧边栏中进行选择。用户可以随时更改公司。
当用户选择公司时,选项会被记录在会话变量中。
但是,在用户更改页面时,会话变量的信息会丢失。
我做错了什么或者没有做好?有更好的方法来解决这个问题吗?
相关的代码片段如下:
context_processors.py
from apps.client.models import Client

def units (request):
    # Dictionary with business options
    clients = Client.objects.values ​​(
        "client_id",
        "company_id__name",
    )
    clients_list = []
    for client in clients:
        clients_list.append (
            {
                'client_id': client ['client_id'],
                'name': client ['company_id__name']
            }
        )
    return {'clients_list': clients_list}

base.html

# System base page.
# Displays the list of business options.
<select class = "form-control select2">
<option value = "{{request.session.unit_id}}"> {{request.session.unit_id}} </option>
{% for client in clients_list%}
<option value = "{{client.client_id}}"
{% if request.session.unit_id == client.client_id%}
selected
{% endif%}>
{{client.client_id}}
</option>
{% endfor%}
</select>
...


# Whenever a company is selected ...
<script>
$ ("# select_unit"). click (function () {
    var option_id = $ (this) .val ();
    var url = "{% url 'home: set_unit'%}";
    $ .ajax ({
        type: "GET",
        url: url,
        data: {'unit_id': option_id},
        success: function () {}
    });
});
</script>

view.py

# View that registers the variable in the session.
def set_unit (request):
    unit_id = request.GET.get ("unit_id")
    request.session ['unit_id'] = unit_id

settings.py

MIDDLEWARE = [
    'apps.core.middleware.AppMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django_globals.middleware.Global',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'apps.home.context_processors.units',
            ],
        },
    }
]

你的 set_unit 视图没有返回任何东西?我认为这可能是个问题。它叫什么名字? - dirkgroten
设置单元始终正确地提供会话。事实证明,当切换页面时,会话不再显示用户选择的值。 - Antonio José
我不明白,一个视图必须始终返回HttpResponse。而你的视图却没有返回。 - dirkgroten
set_unit 视图只需要选定公司和会话变量中的箭头。页面不应该被重定向,它应该停留在原地。请记住,公司选择的 select 是一个侧边栏组件,因此不应该进行页面重定向。问题正是出在这里:选择公司后,用户访问系统的任何页面 - 此时定义的会话变量会丢失。 - Antonio José
你需要解释一下在哪里以及如何调用你的 set_unit 视图。Django 只会在请求周期结束时,在中间件中保存会话。如果在此之前出现异常(这将发生,因为你的视图没有返回任何内容),会话将不会被保存。所以请回答我的第一个问题,而不是说你做得对。显然你做得不对,否则它就能正常工作了,不是吗? - dirkgroten
显示剩余2条评论
2个回答

1

您设置会话变量的视图需要返回一个响应。由于您正在使用Ajax调用它,因此使用简单的{'status': 'ok'}字典的JsonResponse就可以了。在set_unit的末尾添加这行代码:

return JsonResponse({'status': 'ok'})

如果您查看浏览器开发工具的网络选项卡或控制台,您将会看到当前您的请求生成了一个错误,因为视图不应该返回None。这就是会话没有保存和会话变量新状态未持久化的原因。

1
我认为问题在于你没有设置会话已被修改,在更改会话值后。
request.session.modified = True

另一个选项是在您的settings.py中添加:
SESSION_SAVE_EVERY_REQUEST=True

3
如果你只是更改简单的键值对,你不需要设置会话已修改,Django会自动检测这些更改。具体请参见文档 - dirkgroten
我不知道那个。谢谢! - Caio Kretzer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接