django文件上传-更新编辑模板后删除了图像 [英] django file upload - image deleted when edit template updated

查看:100
本文介绍了django文件上传-更新编辑模板后删除了图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用django允许用户上传图像以及用于描述图像标题的文本.

I am using django to allow a user to upload images along with text to describe the image title.

用户应该能够使用编辑模板编辑图像标题并更改图像文件.这确实可以工作-在某种程度上.

The user should be able to edit the image title and change the image file using the edit template. This does work - to some degree.

我可以在编辑模板中显示图像文件和图像标题以进行编辑.我遇到的问题是当我在文件上传输入中不包括图像文件(用户只想更改图像标题而不是图像文件)时,我拥有的代码确实更改了图像标题,但是图像文件被删除了从数据库中删除(物理映像文件未从文件系统中删除).

I can display the image file and the image title in the edit template for editing. The issue I have is when I do not include an image file in the file upload input (the user only wants to change the image title and not the image file), the code I have does change the image title but the image file is deleted from the database (the physical image file is not deleted from the file system).

我可以成功更新图像详细信息,但是用户必须在文件上传输入字段中包含新图像文件或相同的图像文件,图像标题才能成功更新图像详细信息.

I can successfully update the image details but the user must include a new image file or the same image file in the file upload input field for the image title the image details to be successfully updated.

似乎用户必须在文件上传输入字段中包含图片文件.我正在尝试让代码像django管理员一样工作,在该用户中,用户每次更改图像标题时都不必包括图像文件.

It seems the user must include an image file in the file upload input field. I am trying to get my code to work just like the django admin where the user does not have to include an image file each time the user changes the image title.

如何允许用户更新图像详细信息而不必每次用户想要更改图像标题时都重新上传图像文件?

这是我的models.py代码:

Here is my models.py code:

编辑#2-添加了FillableModelWithLanguageVersion&语言版本

# START: ATTACHMENT DETAILS MODEL.
def _get_document_upload_location(instance, filename):
    """
    Using a function instead of a lambda to make migrations happy. DO NOT remove or rename this function in the future, as it will break migrations.
    @param instance: model instance that owns the FileField we're generating the upload filename for.
    @param filename: Original file name assigned by django.
    """
    return 'attachments/%d/%s' % (instance.user.id, uuid.uuid4())

class AttachmentDetails(models.Model, FillableModelWithLanguageVersion):
    user = models.ForeignKey(User)
    language_version = models.ForeignKey('LanguageVersion')
    attachment_document = models.FileField(upload_to=_get_document_upload_location, null=True, blank=True)
    attachment_title = models.CharField(null=False, blank=False, max_length=250)
    attachment_timestamp_added = models.DateTimeField(auto_now_add=True, auto_now=False)
    attachment_timestamp_updated = models.DateTimeField(auto_now=True, auto_now_add=False)

    def __unicode__(self):
        return unicode(self.user)

    class Meta:
        verbose_name = ('Attachment Detail')
        verbose_name_plural = ('Attachment Details')

    @staticmethod
    def view_link():
        return reverse(settings.MENU_DETAIL_LINK_ATTACHMENT_DETAILS)

    @property
    def language_name(self):
        return LANGUAGES[self.language_version.language_code].name

    @property
    def language_name_english(self):
        return LANGUAGES[self.language_version.language_code].name_english

    @property
    def language_name_native(self):
        return LANGUAGES[self.language_version.language_code].name_native


# delete file when AttachmentDetails model is deleted


@receiver(post_delete,sender=AttachmentDetails,dispatch_uid='delete_attachment_details')
def delete_attachment_details(sender, **kwargs):
    attachment_details = kwargs['instance']
    attachment_details.attachment_document.delete(save=False)
# FINISH: ATTACHMENT DETAILS MODEL.

class FillableModelWithLanguageVersion(object):
    def fill(self, fields):
        self.language_version = LanguageVersion.objects.get(user=self.user, language_code=fields['language_code'])
        for field, value in fields.iteritems():
            if field == 'language_code':
                continue
            setattr(self, field, value)

class LanguageVersion(models.Model):
    """Language version selection for a user"""
    user = models.ForeignKey(User)
    language_code = models.CharField(max_length=32)
    language_code_disabled = models.BooleanField(default=False)
    language_version_timestamp_added = models.DateTimeField(auto_now_add=True, auto_now=False)
    language_version_timestamp_updated = models.DateTimeField(auto_now=True, auto_now_add=False)  # the date the language version is updated when the user changes their subscription type.

    def __unicode__(self):
        return unicode(self.language_code)

    class Meta:
        unique_together = ('user', 'language_code')
        verbose_name = ('Language Versions')
        verbose_name_plural = ('Language Versions')

这是我的views.py代码:

Here is my views.py code:

def attachment_details_edit(request, attachment_details_id):
    try:
        attachment_details = AttachmentDetails.objects.get(pk=attachment_details_id, user=request.user)
    except AttachmentDetails.DoesNotExist:
        return redirect(settings.MENU_DETAIL_LINK_ATTACHMENT_DETAILS)
    language_versions = LanguageVersion.objects.filter(user=request.user).select_related('language_version')
    available_languages = get_available_language_details(language_versions, request.user.userprofile.language_preference)
    attachment_details_num = request.user.attachmentdetails_set.count()
    language_code = attachment_details.language_version.language_code
    language_code_disabled = attachment_details.language_version.language_code_disabled
    language_preference = request.user.userprofile.language_preference
    if language_code_disabled:
        return redirect(settings.MENU_DETAIL_LINK_ATTACHMENT_DETAILS)
    if request.method == 'GET':
        language_code = attachment_details.language_version.language_code
        form = AttachmentDetailsForm(
                available_languages,
                language_preference=request.user.userprofile.language_preference,
                file_required=True,
                initial=dict(
                    model_to_dict(attachment_details),
                    language_code=language_code
                )
        )
    elif request.method == 'POST':
        form = AttachmentDetailsForm(
            available_languages,
            language_preference,
            False,  # file_required
            request.POST,
            request.FILES
        )
        if form.is_valid():
            cd = form.cleaned_data
            if cd['attachment_document'] is not None:
                #  delete the existing uploaded attachment when user updates the existing attachment with a replacement attachment.
                print 'removing previously uploaded file'
                attachment_details.attachment_document.delete(save=False)
            attachment_details.fill(cd)
            attachment_details.save()
            messages.success(request, _('successfully updated.'))
            return redirect(settings.MENU_DETAIL_LINK_ATTACHMENT_DETAILS)

我有一篇相关的帖子 修改

这是我的forms.py代码:

Here is my forms.py code:

class AttachmentDetailsForm(forms.ModelForm):

    required_css_class = 'required'

    def __init__(self, available_languages, language_preference, file_required, *args, **kwargs):
        """
        available_languages should be a valid choices list
        """
        super(AttachmentDetailsForm, self).__init__(*args, **kwargs)
        self.fields['language_code'] = forms.ChoiceField(choices=available_languages, initial=language_preference, label=_('Language'),)
        self.fields['attachment_document'] = forms.FileField(label=_('Attachment'), required=file_required)

    class Meta:
        model = AttachmentDetails

        fields = (
            'attachment_title',
        )

        labels = {
            'attachment_title': _('Attachment Title'),
        }

    def clean_attachment_document(self):

        if self.cleaned_data['attachment_document'] is not None:

            file_name = self.cleaned_data['attachment_document'].name.lower()
            extension = file_name.split('.')[-1]

            if extension not in settings.ALLOWED_ATTACHMENT_EXTENSIONS:
                raise forms.ValidationError(_("Only file types .bmp, .gif, .jpg, .jpeg are permitted."))

            # use the following if condition when the file size of the attachment is to be measured in MB - MB calculation.
            #if self.cleaned_data['attachment_document'].size > settings.MAX_ATTACHMENT_FILE_SIZE_MB * 1024 * 1024:
            #    raise forms.ValidationError('Maximum permitted attachment size is: %d MB.' % settings.MAX_ATTACHMENT_FILE_SIZE_MB)

            # use the following if condition when the file size of the attachment is to be measured in kB - kB calculation.
            if self.cleaned_data['attachment_document'].size > settings.MAX_ATTACHMENT_FILE_SIZE_KB * 1024:
                raise forms.ValidationError('Maximum permitted attachment size is: %d kB.' % settings.MAX_ATTACHMENT_FILE_SIZE_KB)

        return self.cleaned_data['attachment_document']

推荐答案

您的问题来自模型的fill方法.它总是设置attachment_document.为了防止这种情况,请尝试以下操作:

Your problem comes from the fill method of your model. It always sets attachment_document. In order to prevent that - try this:

    if form.is_valid():
        cd = form.cleaned_data
        attachment_document = cd.pop('attachment_document')
        if attachment_document:
            #  delete the existing uploaded attachment when user updates the existing attachment with a replacement attachment.
            print 'removing previously uploaded file'
            attachment_details.attachment_document.delete(save=False)
            attachment_details.attachment_document = attachment_document
        attachment_details.fill(cd)
        attachment_details.save()
        messages.success(request, _('successfully updated.'))
        return redirect(settings.MENU_DETAIL_LINK_ATTACHMENT_DETAILS)

这篇关于django文件上传-更新编辑模板后删除了图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆