简体   繁体   中英

<ForeignKey> is not JSON serializable Django App

I am receiving the error is not JSON serializable when I attempt to do the below in my view. Could someone please assist - I am completely unfamiliar with what this means.

views.py

....
def PackingListView(request):
    if request.method == "POST":
        form = PackingListForm(request.POST)
        if form.is_valid():
            if 'preview' in request.POST:
                request.session['data'] = form.cleaned_data
                return redirect('myview')

            elif 'save' in request.POST:

                form.save()

                context = request.session['data'] = form.cleaned_data #get the from the form
                pdf = render_to_pdf('packlist_preview.html', context) #create the PDF
                filename = "YourPDF_Order{}.pdf" #name the PDF


                instance = PackingListDocuments.objects.create() #create a new instance in the model to contain the doc
                instance_key = instance.pk #get the pk of that new model object
                object = PackingListDocuments.objects.get(pk=instance_key) #get that object
                object.Reference_Number = form.cleaned_data.get('Reference_Number')
                object.PackingListDocument.save(filename, File(BytesIO(pdf.content))) #save the document to that object


                messages.success(request, "Success: Packing List Has Been Created!")
                return redirect('HomeView')

    else:
        form = PackingListForm()
        return render(request, 'packlist.html', {'form': form})

Reference_Number is a foreignkey to the Shipment model which I suppose is why I'm getting this error but I have no idea why or what I might do differently

models.py

class Shipment(models.Model):

    Reference_Number = models.CharField(max_length=100)
    Ultimate_Consignee = models.CharField(max_length=100)

class PackingListDocuments(models.Model):
    Reference_Number = models.ForeignKey(Shipment, null=True, default=None)
    PackingListDocument = models.FileField(upload_to='media')

forms.py

class PackingListForm(forms.ModelForm):
    class Meta:
        model = PackingList
        fields = ['Exporter', 'Consignee', 'Reference_Number', ...]

TRACEBACK

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/create/packing_list

Django Version: 1.11
Python Version: 2.7.10
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'Poseidon',
 'crispy_forms',
 'bootstrap_modal_forms']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/Library/Python/2.7/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/Library/Python/2.7/site-packages/django/utils/deprecation.py" in __call__
  142.             response = self.process_response(request, response)

File "/Library/Python/2.7/site-packages/django/contrib/sessions/middleware.py" in process_response
  58.                             request.session.save()

File "/Library/Python/2.7/site-packages/django/contrib/sessions/backends/db.py" in save
  83.         obj = self.create_model_instance(data)

File "/Library/Python/2.7/site-packages/django/contrib/sessions/backends/db.py" in create_model_instance
  69.             session_data=self.encode(data),

File "/Library/Python/2.7/site-packages/django/contrib/sessions/backends/base.py" in encode
  98.         serialized = self.serializer().dumps(session_dict)

File "/Library/Python/2.7/site-packages/django/core/signing.py" in dumps
  93.         return json.dumps(obj, separators=(',', ':')).encode('latin-1')

File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py" in dumps
  250.         sort_keys=sort_keys, **kw).encode(obj)

File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py" in encode
  207.         chunks = self.iterencode(o, _one_shot=True)

File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py" in iterencode
  270.         return _iterencode(o, 0)

File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py" in default
  184.         raise TypeError(repr(o) + " is not JSON serializable")

Exception Type: TypeError at /create/packing_list
Exception Value: <Shipment: 219002> is not JSON serializable

You're storing data in your session and to do that, Django needs to serialise the data, read this . You'll read that the default serializer used is the JSONSerializer .

Now form.cleaned_data isn't necessarily serialisable to JSON. Any foreign key submitted as integer ( id ) becomes the actual object in cleaned_data . Eg form.cleaned_data['Reference_Number'] is a Shipment instance, not its id .

So session['data'] = form.cleaned_data is raising this error.

You need to manually create the dictionary you want to store in the session to ensure it's serialisable.

Okay, I haven't worked on Django 1.11 in a while but it looks like there's some duplication and you can let the model form do more of the work for you. I can't test it but I think your view should be more like:

        elif 'save' in request.POST:
            # get a packing list doc from our form but don't save to the db yet
            packing_list_doc = form.save(commit=False)

            context = request.session['data'] = form.cleaned_data  # get the from the form

            pdf = render_to_pdf('packlist_preview.html', context)  # create the PDF

            # what's the point of this? we never use filename...
            filename = "YourPDF_Order{}.pdf"  # name the PDF

            # we already have our packing_list_doc so no need to create one or query one
            # also, the form should have already set the shipment/reference_number on our packing_list_doc

            # for the love of God, please rename PackingListDocument to packing_list_pdf or similar
            # PackingListDocuments.PackingListDocument is not an easy read
            packing_list_doc.PackingListDocument = File(BytesIO(pdf.content))
            packing_list_doc.save()  # because we did commit=False earlier

            messages.success(request, "Success: Packing List Has Been Created!")
            return redirect('HomeView')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM