Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set a custom field in a Django session model?

I have extended the session in Django per this. In short, I have added a field named account_id to hold the user id of the user which the session belongs to.

Everything works fine, except the custom field account_id I have added is not being set on login. To do so:

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

I have tried putting the following to CODE HERE. However, none of them worked:

  1. request.session.model.account_id = user.id

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

In each of these attempts, account_id is NULL in the data base.

What am I missing here?

like image 575
Utku Avatar asked Jan 30 '17 17:01

Utku


People also ask

How do I add a field to a Django model?

To answer your question, with the new migration introduced in Django 1.7, in order to add a new field to a model you can simply add that field to your model and initialize migrations with ./manage.py makemigrations and then run ./manage.py migrate and the new field will be added to your DB.

Is there a list field for Django models?

Mine is simpler to implement, and you can pass a list, dict, or anything that can be converted into json. In Django 1.10 and above, there's a new ArrayField field you can use.

How do I use file based sessions in Django?

If you want to use a database-backed session, you need to add 'django. contrib. sessions' to your INSTALLED_APPS setting. Once you have configured your installation, run manage.py migrate to install the single database table that stores session data.


2 Answers

If you want to give a custom name or create a custom field in the session table, you can follow the following step.

Define a custom session backend:

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

then in settings.py import your custom class

SESSION_ENGINE = "my_project.session_backend"

Define the custom model in models.py in the app say 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"

now run the following commands for migrations

python manage.py makemigrations
python manage.py migrate

Done :)

like image 79
Tarun Kumar Avatar answered Oct 09 '22 08:10

Tarun Kumar


You're missing the fact that CustomSession is a model; you need to save the instance, not set "modified" on it as you do in version 2.

session = CustomSession.objects.get(pk=session_key)
session.account_id = user.id
session.save()
like image 22
Daniel Roseman Avatar answered Oct 09 '22 09:10

Daniel Roseman