0

models.py:

class Empresa(models.Model):
    logo = models.FileField(null=True)

forms.py:

class ConfiEmpresa(ModelForm):
    logo = forms.FileField(required=False)
    class Meta:
        model = Empresa

The html input code that the form field is rendering is the following one:

<input type="file" name="logo" id="id_logo">

views.py:

import base64

def configempresa(request):
    if request.method == "POST":
        form = ConfiEmpresa(request.POST, request.FILES)
        print(form.errors)  # I'm not having any form error here
        if form.is_valid():
            logo = form.cleaned_data.get('logo')
            print(logo)  # It's printing "None"
            logo = base64.encodebytes(logo)
            #...rest of the view

The error I'm getting:

TypeError at /Config/empresa/
expected bytes-like object, not NoneType

So in conclusion I'm trying to convert the jpg file that user is setting as 'logo' to base64 in order to store it in my DB and later decode it to get the image where I need it.

Of course I'm doing something wrong, I think it's in my view. How can I handle the value of the form field logo in order to convert it to base64?

I'm not storing the raw file in any folder.

Gonzalo Dambra
  • 891
  • 2
  • 19
  • 34
  • Are you sure your file is sent? If you inspect `request.FILES` is there anything in there? Also, have you used `
    ` as your form encoding type?
    – Geekfish Mar 26 '19 at 16:24
  • Also, given that your field is `required=False` it means that you allow NOT submitting a file, so you will need to handle the case where no logo is uploaded. – Geekfish Mar 26 '19 at 16:25
  • Thank you @Geekfish. Well, the enctype was part of the problem. It was on "application/x-www-form-urlencoded". Now it is not printing "None" anymore, but the error now is this one: "expected bytes-like object, not InMemoryUploadedFile" – Gonzalo Dambra Mar 27 '19 at 11:26
  • Also I wonder, are "logo = form.cleaned_data.get('logo')" and "logo = base64.encodebytes(logo)" properly? – Gonzalo Dambra Mar 27 '19 at 11:30
  • The clue is in the error message. You are trying to pass a `InMemoryUploadedFile` object (`logo`) into `base64.encodebytes`, which, as the name suggests, expects bytes. `InMemoryUploadedFile` is a wrapper around the actual file. You need to get the actual contents of the file. Something along the lines of `base64.encodebytes(logo.file.read())`. But I'm not sure of the exact way. You may need to lookup on how to do this exactly. – Geekfish Mar 27 '19 at 11:56
  • @Geekfish I think form.cleaned_data.get('logo') is the error here, since when I print it it's printing the name of the image file. No idea about how to get an image from form. – Gonzalo Dambra Mar 27 '19 at 13:02
  • What did you expect it to print? It will not print the file itself. The error suggests what I explained above. – Geekfish Mar 27 '19 at 13:04
  • @Geekfish no of course it won't print the file. But I thought it was weird to print the name itself like if it were sending a string "photo.jpg" – Gonzalo Dambra Mar 27 '19 at 13:20
  • Print does not print the exact variable, it prints a representation of a variable. If you want to see what a variable actually is, then you can do `print(type(logo))` and that will give you the variable type. – Geekfish Mar 27 '19 at 13:25

2 Answers2

1

Wouldn't it be better to save the logo in an ImageField?

If you want to save the base64 image you can always save it in a TextField as a string, if you only want to show the image later.

Geekfish
  • 2,173
  • 23
  • 28
DIOdev
  • 11
  • 2
0

The solution:

if form.is_valid():
            logo = form.cleaned_data.get('logo')
            print(logo)
            logo = base64.b64encode(logo.file.read())
Gonzalo Dambra
  • 891
  • 2
  • 19
  • 34