Jason B
Jason B

Reputation: 365

Django TypeError not JSON serializable in request.session

I have a sort function on a project I'm working on, where users can create a sort query of all the assets they're working on. When they get the results of their query, I want them to be able to download a .csv of all the objects in the query.

However, when I try to store the query results in a session, I get an error that the results are not JSON serializable. If I don't try to store the query results then the sort runs fine, but then export button won't work since the query results haven't been stored.

In my views:

def sort(request, project_id=1):
    thisuser = request.user
    project = Project.objects.get(id=project_id)

    if Project.objects.filter(Q(created_by=thisuser) | Q(access__give_access_to=thisuser), id=project_id).exists():
        permission = 1
    else:
        permission = None

    if Asset.objects.filter(project__id=project_id, unique_id=1):
        assets = 1
    else:
        assets = None


    if request.POST:
        if request.POST.get('date_start') and request.POST.get('date_end'):
            date_start  = datetime.strptime(request.POST['date_start'], '%m/%d/%Y')
            date_end    = datetime.strptime(request.POST['date_end'], '%m/%d/%Y')
            q_date      = Q(date_produced__range=[date_start, date_end])
        else:
            q_date      = Q(date_produced__isnull=False) | Q(date_produced__isnull=True)

        text_fields = {
            'asset_type': request.POST.get('asset_type'),
            'description': request.POST.get('description'),
            'master_status': request.POST.get('master_status'),
            'location': request.POST.get('location'),
            'file_location': request.POST.get('file_location'),
            'footage_format': request.POST.get('footage_format'),
            'footage_region': request.POST.get('footage_region'),
            'footage_type': request.POST.get('footage_type'),
            'footage_fps': request.POST.get('footage_fps'),
            'footage_url': request.POST.get('footage_url'),
            'stills_credit': request.POST.get('stills_credit'),
            'stills_url': request.POST.get('stills_url'),
            'music_format': request.POST.get('music_format'),
            'music_credit': request.POST.get('music_credit'),
            'music_url': request.POST.get('music_url'),
            'license_type': request.POST.get('license_type'),
            'source': request.POST.get('source'),
            'source_contact': request.POST.get('source_contact'),
            'source_email': request.POST.get('source_email'),
            'source_id': request.POST.get('source_id'),
            'source_phone': request.POST.get('source_phone'),
            'source_fax': request.POST.get('source_fax'),
            'source_address': request.POST.get('source_address'),
            'credit_language': request.POST.get('source_language'),
            'cost': request.POST.get('cost'),
            'cost_model': request.POST.get('cost_model'),
            'total_cost': request.POST.get('total_cost'),
            'notes': request.POST.get('notes')
            }

        boolean_fields = {
            'used_in_film': request.POST.get('used_in_film'),
            'footage_blackandwhite': request.POST.get('footage_blackandwhite'),
            'footage_color': request.POST.get('footage_color'),
            'footage_sepia': request.POST.get('footage_sepia'),
            'stills_blackandwhite': request.POST.get('stills_blackandwhite'),
            'stills_color': request.POST.get('stills_color'),
            'stills_sepia': request.POST.get('stills_sepia'),
            'license_obtained': request.POST.get('license_obtained')
            }

        q_objects = Q()

        for field, value in text_fields.iteritems():
            if value:
                q_objects = Q(**{field+'__contains': value})

        q_boolean = Q()

        for field, value in boolean_fields.iteritems():
            if value:
                q_boolean |= Q(**{field: True})

        query_results = Asset.objects.filter(q_date, q_objects, q_boolean)

        list(query_results)

        request.session['query_results'] = list(query_results)

        args = {'query_results': query_results, 'thisuser': thisuser, 'project': project, 'assets': assets}
        args.update(csrf(request))

        args['query_results'] = query_results

        return render_to_response('sort_results.html', args)

    else:

        args = {'thisuser': thisuser, 'project': project, 'assets': assets}
        args.update(csrf(request))

        return render_to_response('sort.html', args)

This is the line: "request.session['query_results'] = list(query_results)" that causes it to fail. It also fails if it's "request.session['query_results'] = query_results"

Upvotes: 1

Views: 1738

Answers (1)

Eugene Soldatov
Eugene Soldatov

Reputation: 10135

The reason of this error is that you try to assign list on model instances to session. Model instance cannot be serialized to JSON. If you want to pass list of instances of Asset model to session you can do in that way:

query_results = Asset.objects.values('id','name').filter(q_date, q_objects, q_boolean)

You can list necessary model fields in values()

In that case you will have list of dictionaries, not instances. And this list may be assigned to session. But you cannot operate with this dictionaries like instances of class Assign, i.e. you cannot call class methods and so on.

Upvotes: 1

Related Questions