Search code examples
pythondjangoimagedjango-modelsfile-upload

Django How to generate and save image when entity made with CreateView?


I'm currently developing a django aplication. With one of my models I need to generate a barcode and save it as an image and upload it in one of the models field.

I tried to generate the image in the save function of the model as shown bellow. The image is generated and saved to the correct folder, but when I look at the entitys they always have the default image saved with them.

models.py:

class ItemEntity(models.Model):
sub_type = models.ForeignKey(ItemSubType, on_delete= models.PROTECT)
location = models.ForeignKey(WarehouseBin, on_delete= models.PROTECT)
supplyer = models.ForeignKey(ItemSupplyers, on_delete= models.PROTECT)
quantity = models.IntegerField()
unit = models.ForeignKey(Units, on_delete= models.PROTECT)
creation_date = models.DateTimeField(default= timezone.now)
expiration_date = models.DateTimeField()
time_of_consumption = models.DateTimeField(null= True)    
barcode = models.ImageField(default='default_barcode.jpg', upload_to= 'media/barcodes')

def __str__(self):
    return self.sub_type.name + " " +  str(self.quantity) + " " + str(self.unit) 

def save(self):
    super().save()
    
    datas=self.pk,self.location,self.sub_type # Datas to give to my barcode generator code
    self.img = Image.new('RGB',(1,1))   # Declaring an empty image variable
    BarcodeGenerator(datas,self) # Barcode generator the barcode it generates is put intu self.img variable

    self.img.save("/home/makiverem/projects/pina/media/media/barcodes/"+str(self.pk)+".jpg") # Saving the image to media/media/barcodes
    #I MISS SOMETHING FROM HERE I THINK
    self.barcode=self.img #Making the models barcode field equal to self.img

views.py:

class ItemEntityCreateView(CreateView):
model=ItemEntity
form_class = ItemEntityForm


def get_form_kwargs(self, *args, **kwargs):
    kwargs = super(ItemEntityCreateView, self).get_form_kwargs(*args, **kwargs)
    return kwargs

def get_initial(self):
        return {
            "sub_type": self.kwargs.get('pk'),
            #"unit": self.kwargs.get('pk') #kérdés mi lenne a jobb megoldás itt urlben több argumentumot átadni?
        }
        
def get_success_url(self):
    return reverse('whouse_itemsubtype_detail', kwargs={'pk' : self.object.sub_type.id})

def form_valid(self,form):
    if form.is_valid():
        messages.success(request= self.request, message='Sikeres Módosítás.')
        form.save()
        return super().form_valid(form)
    else:
        messages.error(request= self.request, message='Sikertelen Módosítás.')
        return super().form_invalid(form) 

forms.py:

class ItemEntityForm(ModelForm):

def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            if self.instance.pk == None:
                self.fields['location'].queryset = WarehouseBin.objects.all().exclude(id__in=ItemEntity.objects.all().prefetch_related('location').values_list('location'))
            else:
                self.fields['location'].queryset = WarehouseBin.objects.all().exclude(id__in=ItemEntity.objects.all().prefetch_related('location').values_list('location'))|(WarehouseBin.objects.all().filter(id= ItemEntity.objects.all().get(pk=self.instance.pk).location.id))
                
class Meta:    

    model = ItemEntity
    fields = ('sub_type', 'location', 'supplyer', 'quantity', 'unit', 'expiration_date') #

    

    labels = {
        'sub_type': 'Példány altípusa:',
        'location': 'Hely:',
        'supplyer': 'Beszállító',
        'quantity': 'Mennyiség:',
        'unit': 'Egység:',
        'expiration_date': 'Szavatossági idő:',
    }  

    widgets= {
        'expiration_date' : DateInput(attrs={'type': 'date'})
    }

Thank you for the support.


Solution

  • After @nigel239 answer I changed the code to the following and now it works as intended.

    datas=ItemEntity.objects.latest('id').id+1,self.location,self.sub_type # Datas to give to my barcode generator code
        self.img = Image.new('RGB',(1,1))   # Declaring an empty image variable
        BarcodeGenerator(datas,self) # Barcode generator the barcode it generates is put intu self.img variable
    
        img_io = BytesIO()
        self.img.save(img_io, format='WEBP') # Saving the image to media/media/barcodes
    
        self.barcode=ContentFile(img_io.getvalue(),str(ItemEntity.objects.latest('id').id+1)+".jpg")
    
        super().save()
    

    Thank you for your help!