Home > Software engineering >  Appending to list replaces last item in Django middleware
Appending to list replaces last item in Django middleware

Time:03-14

I have a middleware I'm using to retain route history within my Django app to use with breadcrumbs, but for some reason the last item in the list keeps getting replaced rather than the item appending to the end of the list.

ROOT_ROUTE_PATH = '/labels/'

class RouteHistoryMiddleware(object):
    request = None
    history = None

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        self.request = request

        if 'history' not in request.session:
            request.session['history'] = []

        self.history = request.session['history']

        request.session['history'].append(request.path)

        if len(self.history) == 0:
            self.request.previous_route = ROOT_ROUTE_PATH
        elif len(self.history) == 1:
            self.request.previous_route = request.session['history'][-1]
        elif len(self.history) > 1:
            self.request.previous_route = request.session['history'][-2]
        
        return self.get_response(request)

Illustration of request.session['history'] mutation with above:

Open Page A

['/page_a/']

Open Page B

['/page_a/', '/page_b/']

Open Page C

['/page_a/', '/page_c/']

CodePudding user response:

Instead of appending path to session try appending to self.history then overwrite history with new array:

    ...
    self.history = request.session['history']

    self.history.append(request.path)
    request.session['history'] = self.history
    ...

You may need to change your if/else conditions after that

CodePudding user response:

The issue you're running into is that Django doesn't know you've modified the list, and so the data is getting written to the session inconsistently. From the documentation:

By default, Django only saves to the session database when the session has been modified – that is if any of its dictionary values have been assigned or deleted.

i.e, if you modify the list without reassigning it or deleting it, then it will not know the session has been modified. Again from the documentation:

we can tell the session object explicitly that it has been modified by setting the modified attribute on the session object.

So your original code should work if you add this line after modifying the list in place:

request.session.modified = True

(Replacing the list entirely, as suggested in the other answer, also works - I'm just trying to explain why your original code didn't work).

  • Related