如何在 Django 会话模型中设置自定义字段?

Posted

技术标签:

【中文标题】如何在 Django 会话模型中设置自定义字段?【英文标题】:How to set a custom field in a Django session model? 【发布时间】:2017-06-15 23:33:33 【问题描述】:

我已经根据this 延长了 Django 中的会话。总之,我添加了一个名为account_id 的字段来保存会话所属用户的用户ID。

一切正常,除了我添加的自定义字段account_id 没有在登录时设置。这样做:

from django.contrib import auth
from MyApp.models import CustomSession

def login(request):
    username = request.POST['username']
    password = request.POST['password']
    user = auth.authenticate(username=username, password=password)
    if user is not None:
        try:
            auth.login(request, user)
            session_key = request.session.session_key
            # CODE HERE
            if session_key is not None:
                return HttpResponse(json.dumps('status': 'Success'))
            else:
                return HttpResponse(json.dumps('status': 'Fail'))

我已尝试将以下内容发送到CODE HERE。但是,它们都不起作用:

    request.session.model.account_id = user.id

    session = CustomSession.objects.get(pk=session_key)
    session.account_id = user.id
    session.modified = True
    
    request.session.account_id = user.id request.session[account_id] = user.id

在每次尝试中,account_id 在数据库中都是NULL

我在这里错过了什么?

【问题讨论】:

您想这样做的原因是什么?在大约 99.9% 的情况下,不需要以这种方式将会话与用户联系起来。 @trixn 我正在尝试轻松获取在线用户列表。 这将如何帮助您做到这一点? @DanielRoseman 我在用户断开连接时注销用户(用户使用 WebSockets 连接,所以我可以判断他们是否连接)。因此,在任何给定时间,会话表都会告诉我在线用户列表。 我不知道在扩展 Django 的 Session 类之后我必须将代码放在哪里。文档包含代码,但不包含要放置的位置。任何人都可以指导向数据库添加其他字段吗? 【参考方案1】:

您错过了 CustomSession 是一个模型的事实;您需要保存实例,而不是像在版本 2 中那样对其设置“修改”。

session = CustomSession.objects.get(pk=session_key)
session.account_id = user.id
session.save()

【讨论】:

不走运。这也不起作用。 account_id 仍然是 NULL 我的猜测是 Django 在退出 login 方法时会以某种方式重新保存会话,但是省略了 account_id【参考方案2】:

如果您想在会话表中提供自定义名称或创建自定义字段,您可以按照以下步骤操作。

定义自定义会话后端:

my_project
    my_project/
        settings.py
        session_backend.py
        ...
    user/
        models.py
        ...
from django.contrib.sessions.backends.db import SessionStore as DBStore
import user


class SessionStore(DBStore):

    @classmethod
    def get_model_class(cls):
        return user.models.MySession

    def create_model_instance(self, data):
        """
        overriding the function to save the changes to db using `session["user_id"] = user.id` .
        This will create the model instance with the custom field values. 
        When you add more field to the custom session model you have to update the function 
        to handle those fields as well.
        """
        obj = super().create_model_instance(data)
        try:
            user_id = data.get('user_id')
        except (ValueError, TypeError):
            user_id = None

        obj.user_id = user_id
        return obj

然后在settings.py 中导入您的自定义类

SESSION_ENGINE = "my_project.session_backend"

在应用程序的models.py 中定义自定义模型,例如user

from django.contrib.sessions.models import Session


class MySession(Session):
    # you can also add custom field if required like this user column which can be the FK to the user table 
    user = models.ForeignKey('user', on_delete=models.CASCADE) 

    class Meta:
        app_label = "user"
        db_table = "my_session"

现在运行以下命令进行迁移

python manage.py makemigrations
python manage.py migrate

完成:)

【讨论】:

谢谢,这行得通,但由于递归导入,我还必须将会话模型放在 session_backend.py 中

以上是关于如何在 Django 会话模型中设置自定义字段?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django 模板中设置自定义 forloop 起点

如何在 Django 中设置自定义中间件

如何在使用集合处理器在摄取节点管道中设置自定义索引时解析字段

在 django 中设置自定义用户注册表单的样式

如何在 Oracle SQL Developer 中设置自定义日期时间格式?

在 SelectList 中设置自定义文本字段