如何为Django FileField编写文件 - 防止重复文件

时间:2013-10-16 14:11:08

标签: python django file-upload

我有以下代码将base64编码的屏幕截图保存为.png。

class SupportTicketForm(forms.ModelForm):

    class Meta:
        model = SupportTicket
        fields = ('message',
                  'created_by',
                  'modified_by')

    def __init__(self, *args, **kwargs):
        try:
            self.img_data_base64 = kwargs.pop('img_data_base64')
        except KeyError, e:
            raise ImproperlyConfigured('SupportTicket was not properly instantiated. The following keyword argument is missing: %s:' %(e))
        super(SupportTicketForm, self).__init__(*args, **kwargs)

    def save(self, force_insert=False, force_update=False, commit=True):
        ticket = super(SupportTicketForm, self).save(commit=False)
        date_now = datetime.utcnow().replace(tzinfo=utc)
        #dummy-name will be set to unique name in upload handler in models.py
        filename = "dummy-name.png"
        fh = open(filename, 'w+b')
        img_file = File(fh)
        img_file.write(self.img_data_base64.decode('base64'))
        ticket.ticket_img.save(filename, img_file)
        fh.close()
        if commit:
            ticket.save()
        return ticket

该模型如下所示:

def support_ticket_path_handler(instance, filename):
    year = datetime.now().year
    month = datetime.now().month
    ext = filename.split('.')[-1]
    #rename filename - create random + unique filename
    filename = "%s.%s" % (uuid.uuid4(), ext)
    path_return = "support/tickets/{year}/{month}/{file}".format(year=year,
                                                                 month=month,
                                                                 file=filename)
    return path_return

support_ticket_storage = FileSystemStorage()
class SupportTicket(models.Model):
    """user created support tickets"""
    INITIAL_STATUS = 0
    IN_PROGRESS_STATUS = 1
    RESOLVED_STATUS = 2
    DEFAULT_STATUS_CHOICES = (
        (INITIAL_STATUS, 'New Ticket'),
        (IN_PROGRESS_STATUS, 'In Progress'),
        (RESOLVED_STATUS, 'Resolved'),
    )

    message = models.CharField(max_length=100, default="")
    ticket_img  = models.FileField(storage=support_ticket_storage,
                                   upload_to=support_ticket_path_handler,
                                   blank=False)

我的问题是表单save()方法中的代码在磁盘上创建了两个文件。一个名为"dummy-name.png"的文件和一个名为support_ticket_path_handler中定义的文件,而我只需要第二个文件。

由于我需要Django File对象的python图像文件句柄,我不明白如何防止创建第一个图像。一个选项是之后删除第一张图片,但这对我来说看起来不太干净。

1 个答案:

答案 0 :(得分:2)

改为使用StringIO

from StringIO import StringIO
import base64

data = StringIO(base64.decodestring(self.img_data_base64))
img_file = File(data)
ticket.ticket_img.save(filename, img_file)

StringIO将您的数据视为文件,同时将其保留在内存中。