I am trying to sell a basket with goods for an online store on django. The task is as follows: to store in the ID sessions of the goods and their quantity. If the goods are already in the basket, then the quantity is added to the old quantity (addition).

def post(self, request, **kwargs): post = request.POST item_id = int(post.get('id')) count = int(post.get('count')) if 'cart' not in request.session: request.session['cart'] = {} if item_id not in request.session['cart']: request.session['cart'][item_id] = count else: old = int(request.session['cart'][item_id]) request.session['cart'][item_id] = old + count print(request.session['cart']) return HttpResponse(json.dumps({'result': 'success'})) 

The problem is that when you add an existing product, one of the id is converted from a number to a string, because of which an existing product is added to the cart. It looks like this:

 {4: 1, u'4': 1} #4 - id товара, 1 - его количество 

What is the problem?

  • one
    Can you add something like print('before', request.session['cart']) before the line if item_id not in request.session['cart'] ? While at first glance I don’t see any mistakes (except, let's say, stylistic, but more about that later) - andreymal
  • one
    Well, or I may still assume that in some old version of the code you forgot to do an int(..) , then you fixed it, and forgot to clean the session, and this u'4' probably remained from the old version of the code - andreymal sep
  • @andreymal ('before', {}) {4: 1} [14/Sep/2017 13:22:09] "POST /ajax/addtocart/ HTTP/1.1" 200 20 ('before', {u'4': 1}) {4: 3, u'4': 1} - Eduard Design
  • one
    Yeah, I understand, now I will write the answer - andreymal

1 answer 1

This is such a session data storage feature.

To save data, you need those Python objects that you create (a dictionary with numbers) somehow converted into bytes for storing them in the database (or in cookies, depending on the settings). This is called serialization.

By default, Django serializes session data to JSON. However, JSON supports only string keys for dictionaries, so your number-key 4 when you save the session, is converted to the unicode string u'4' , which you can see in print in the next query.

There are two options for what to do:

  • deal with it. Just use the line item_id = post.get('id') (you would have to add validation of all the input data, but this is not on the topic of the question) and convert this line to a number only when it really does;

  • replace serializer with another one. Django out of the box also knows how to serialize objects using pickle, which has almost no restrictions, and key-numbers should remain numbers. To do this, write in the project settings (usually settings.py ):

     SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' 

I recommend in passing to read the documentation about the session , there are considered some security issues.