Read imageField attribute before send it

I have a model, which has 3 ImageField. When loading a new entry into the database, it may have some blank images, so the value is None. When the client request the model data entry, I get in the server side:

ValueError: The ‘picture2’ attribute has no file associated with it.

The problem is in the imageField.read() when there is not a file to read. How can I solve it without check with if statment if there is or not a file?

class item (models.Model):

    certificate=models.ImageField(default=None) 
    provider = models.ForeignKey(serviceProvider, on_delete=models.CASCADE, null=True)
    radius = models.FloatField(default=None)
    description= models.TextField(blank = True)
    hour_init = models.TimeField()
    hour_end = models.TimeField()
    picture1=models.ImageField(default=None, blank=True)    
    picture2=models.ImageField(default=None,blank=True) 
    picture3=models.ImageField(default=None, blank=True)    

This is the view.py function:

def addRubro (request):
    if request.method == 'POST': 
        if request.POST.get("tipo")=="2":
            proveedores=serviceProvider.objects.filter(user=request.POST.get("user"))
            if not proveedores:
                return HttpResponse("Bad")
            else:
                rubros=item.objects.filter(provider=proveedores.first())
                if len(rubros)<2:
                    new = item()
                    new.provider=proveedores.first()
                    new.radius=request.POST.get("radius")
                    new.description=request.POST.get("description")
                    new.hour_init=request.POST.get("hour_init")
                    new.hour_end=request.POST.get("hour_end") 
                    new.certificate=request.FILES.get("certificate")    
                    new.picture1=request.FILES.get("picture1")
                    new.picture2=request.FILES.get("picture2")
                    new.picture3=request.FILES.get("picture3")
                    new.save()  
                    return HttpResponse("Item loaded")

I have a model, which has 3 ImageField. When loading a new entry into the database, it may have some blank images, so the value is None. When the client request the model data entry, I get in the server side:

ValueError: The ‘picture2’ attribute has no file associated with it.

How can I avoid it?

class item (models.Model):

    certificate=models.ImageField(default=None) 
    provider = models.ForeignKey(serviceProvider, on_delete=models.CASCADE, null=True)
    radius = models.FloatField(default=None)
    description= models.TextField(blank = True)
    hour_init = models.TimeField()
    hour_end = models.TimeField()
    picture1=models.ImageField(default=None, blank=True)    
    picture2=models.ImageField(default=None,blank=True) 
    picture3=models.ImageField(default=None, blank=True)    

This is the view function:

def addRubro (request):
    if request.method == 'POST': 
        if request.POST.get("tipo")=="2":
            proveedores=serviceProvider.objects.filter(user=request.POST.get("user"))
            if not proveedores:
                return HttpResponse("Bad")
            else:
                rubros=item.objects.filter(provider=proveedores.first())
                if len(rubros)<2:
                    new = item()
                    new.provider=proveedores.first()
                    new.radius=request.POST.get("radius")
                    new.description=request.POST.get("description")
                    new.hour_init=request.POST.get("hour_init")
                    new.hour_end=request.POST.get("hour_end") 
                    new.certificate=request.FILES.get("certificate")    
                    new.picture1=request.FILES.get("picture1")
                    new.picture2=request.FILES.get("picture2")
                    new.picture3=request.FILES.get("picture3")
                    new.save()  
                    return HttpResponse("Item loaded")

You can see that many times, a single image is sent, so the picture2 and picutre3 will be None .

Then when I try to send model information back to the client, I do it using this function

def requestRubros(request, tipo,user,rubro):
    if tipo=="2":
        proveedores=serviceProvider.objects.filter(user=user)
        if proveedores:
            rubro=item.objects.filter(provider=proveedores.first()).filter(items=rubro)
            if rubro:

                data = [{"radius": str(rubro.first().radius),
                "description": rubro.first().description,},
                
                {
                "hour_init": str(rubro.first().hour_init), "hour_end": str(rubro.first().hour_end)},
                
                {"certificate": "data:image/png;base64,"+base64.b64encode(rubro.first().certificate.read()).decode('ascii'),
                "picture1": "data:image/png;base64,"+(base64.b64encode(rubro.first().picture1.read())).decode('ascii'),
                "picture2": "data:image/png;base64,"+base64.b64encode(rubro.first().picture2.read()).decode('ascii'),
                "picture3": "data:image/png;base64,"+base64.b64encode(rubro.first().picture3.read()).decode('ascii')}]

                return JsonResponse(data, safe=False)

            else:
                return HttpResponse ("Bad data")
        else: 
            return HttpResponse ("Bad data")

I don’t understand why using an if statement isn’t an acceptable solution. It seems like the quickest, easiest, and most clear solution to me.

(Now, had you structured your models where the images were in a separate table with a FK to the item model, you could just iterate over the related items. But, since you’ve done it this way, you really don’t have too many other choices other than some type of conditional assignment.)

1 Like

The problem is that with if-elif, I have to have many lines of code depending on all the possibilities, of which images are None. I have 24 different combinations

if (datos.certificate.read()!=None and datos.picture1.read()!= None and datos.picture2.read()!= None and datos.picture3.read()!=None) :
                    {"certificate": "data:image/png;base64,"+base64.b64encode(datos.certificate.read()).decode('ascii'),
                    "picture1": "data:image/png;base64,"+(base64.b64encode(datos.picture1.read())).decode('ascii'),
                    "picture2": "data:image/png;base64,"+base64.b64encode(datos.picture2.read()).decode('ascii'),
                    "picture3": "data:image/png;base64,"+base64.b64encode(datos.picture3.read()).decode('ascii')}]
                    
elif (datos.certificate.read()!=None and datos.picture1.read()!= None and datos.picture2.read()!= None and datos.picture3.read()==None) :
                    {"certificate": "data:image/png;base64,"+base64.b64encode(datos.certificate.read()).decode('ascii'),
                    "picture1": "data:image/png;base64,"+(base64.b64encode(datos.picture1.read())).decode('ascii'),
                    "picture2": "data:image/png;base64,"+base64.b64encode(datos.picture2.read()).decode('ascii')}]
                    
elif (datos.certificate.read()==None and datos.picture1.read()!= None and datos.picture2.read()== None and datos.picture3.read()==None) :
                    {"certificate": "data:image/png;base64,"+base64.b64encode(datos.certificate.read()).decode('ascii'),
                    "picture1": "data:image/png;base64,"+(base64.b64encode(datos.picture1.read())).decode('ascii')}]
                    
elif (datos.certificate.read()==None and datos.picture1.read()!= None and datos.picture2.read()== None and datos.picture3.read()==None) :
                    {"certificate": "data:image/png;base64,"+base64.b64encode(datos.certificate.read()).decode('ascii')}]
                    
elif (datos.certificate.read()==None and datos.picture1.read()!= None and datos.picture2.read()!= None and datos.picture3.read()!=None) :
                    {"picture1": "data:image/png;base64,"+(base64.b64encode(datos.picture1.read())).decode('ascii'),
                    "picture2": "data:image/png;base64,"+base64.b64encode(datos.picture2.read()).decode('ascii'),
                    "picture3": "data:image/png;base64,"+base64.b64encode(datos.picture3.read()).decode('ascii')}]
                    
                    //and it keep going

No, you can do it more granularly than that. It’s one test for each image and a decision as to whether or not to add it to the dictionary you’re building.
You’ll want to do something along the lines of:
images = {}
if “certificate image available”:
images[‘certificate’] = “certificate image”
if “image1 available”:
images[‘image1’] = “image1”

and so on. One condition for each image.

1 Like