使用FileField编辑现有模型时进行Django表单验证

时间:2019-02-12 11:02:34

标签: python django

我是Django的新手,在编辑具有FileField的模型时,表单验证存在问题。

我的模型有两个FileField,一个是必需的,一个不是:

models.py

class Entrega(models.Model):
    """ People's submissions """

    tid = models.AutoField(_('Código de entrega'), primary_key=True)
    titulo = models.CharField(max_length=500)
    memoria = models.FileField(upload_to=user_upload_memoria_directory_path)
    anexos = models.FileField(null=True, blank=True, upload_to=user_upload_anexos_directory_path)

同一视图应该能够创建新的Entrega或编辑现有视图。

urls.py

urlpatterns = [
    ...
    path('entregas/<int:pk>/edit/', views.edit_or_create_Entrega, name='edit_create_entrega'),
    path('entregas/new/', views.edit_or_create_Entrega, name='edit_create_entrega'),
    ...
]

views.py(无效,请参见下文)

@login_required
def edit_or_create_Entrega(request, pk=None):
    """ Shows the form to create/edit Entrega's """
    if request.method == "POST":
        # create form instance and populate it with data from the request
        form = EntregaForm(request.POST, request.FILES)
        if form.is_valid():
            nueva_entrega = form.save()
            return HttpResponseRedirect(reverse('list_all_entregas'))
        else:
            return render(request, 'envio/base.html', {'avisos': _("Errors were found...")})
    else:
        if not pk:
            # if a GET (or any other method) and no pk is provided, create a blank form
            form = EntregaForm()
        else:
            # if GET (or any other method) and pk is provided, we'll fill the form with
            # entrega, if it exists and it belongs to the user
            e = get_object_or_404(Entrega,pk=pk)
            if not e.matricula.persona.user==request.user:
                return render(request, 'envio/base.html', {'avisos': _("You cannot edit other users submissions")})
            else:
                form = EntregaForm(instance=e)

    return render(request, 'envio/entrega_form.html', {'form': form})

views.py(新版本,可以使用,请参见下文)

@login_required
def edit_or_create_Entrega(request, pk=None):
    """ Shows the form to create/edit Entrega's """
    if request.method == "POST" and not pk:
        # create form instance and populate it with data from the request
        form = EntregaForm(request.POST, request.FILES)
        if form.is_valid():
            nueva_entrega = form.save()
            return HttpResponseRedirect(reverse('list_all_entregas'))
    elif request.method == "POST" and pk:
        e = get_object_or_404(Entrega,pk=pk)
        if not e.matricula.persona.user==request.user:
            return render(request, 'envio/base.html', {'avisos': _("Solo puedes editar tus propias Entregas")})
        else:
            form = EntregaForm(request.POST, request.FILES, instance=e)
            if form.is_valid():
                edit_entrega = form.save()
                return HttpResponseRedirect(reverse('list_all_entregas'))
    else:
        if not pk:
            # if a GET (or any other method) and no pk is provided, we'll create a blank form
            form = EntregaForm()
            matriculas = Matricula.objects.filter(persona__user=request.user)
            if not matriculas:
                return render(request,'envio/base.html', {'avisos': _("No hay matriculas disponibles")})
        else:
            # if GET (or any other method) and pk is provided, we'll fill the form with
            # entrega, if it exists and it belongs to the user
            e = get_object_or_404(Entrega,pk=pk)
            if not e.matricula.persona.user==request.user:
                return render(request, 'envio/base.html', {'avisos': _("Solo puedes editar tus propias Entregas")})
            else:
                form = EntregaForm(instance=e)

forms.py

class EntregaForm(ModelForm):
    """ Modela un formulario para realizar Entregas """

    class Meta:
        model = Entrega
        fields = ['titulo', ... , 'memoria', 'anexos']

不起作用,请参见下文,这就是发生的情况:

  • 我第一次去entregas/6/edit时,表格已经正确地预填了存储在数据库中的值。它甚至显示“当前” memoria值(并提供上传新文件的选项)
  • 如果我在某个字段(例如titulo)中进行了更改,并在不上传新的memoria文件的情况下提交了表单,则form.is_valid()返回false(实例未更新)。
  • 如果我在memoriatitle字段中进行更改,则会保存一个新的Entrega(不会更新现有的models.py)。

现在有了新版本,它可以工作,它可以更新现有的Entrega。

为了完整起见,我将使用处理@receiver(models.signals.post_delete, sender=Entrega) def auto_delete_file_on_delete(sender, instance, **kwargs): """ Deletes file from filesystem when corresponding 'Entrega' object is deleted. Refactor? Perhaps it would be better to use django-cleanup https://github.com/un1t/django-cleanup """ if instance.memoria: if os.path.isfile(instance.memoria.path): os.remove(instance.memoria.path) if instance.anexos: if os.path.isfile(instance.anexos.path): os.remove(instance.anexos.path) @receiver(models.signals.pre_save, sender=Entrega) def auto_delete_file_on_change(sender, instance, **kwargs): """ Deletes old file from filesystem when corresponding 'Entrega' object is updated with new file. This function assumes that EVERY entrega has a mandatory 'memoria' field!! Refactor? Perhaps it would be better to use django-cleanup https://github.com/un1t/django-cleanup """ if not instance.pk: return False try: old_memoria = Entrega.objects.get(pk=instance.pk).memoria except Entrega.DoesNotExist: return False new_memoria = instance.memoria if new_memoria and not old_memoria == new_memoria: if os.path.isfile(old_memoria.path): os.remove(old_memoria.path) old_anexos = None try: old_anexos = Entrega.objects.get(pk=instance.pk).anexos except Entrega.DoesNotExist: return False # if there were NO old_anexos, no need to do nothing... if not old_anexos: return True # if there were old_anexos, remove them... new_anexos = instance.anexos if new_anexos and not old_anexos == new_anexos: if os.path.isfile(old_anexos.path): os.remove(old_anexos.path) 中未使用的文件的两个函数来完成我的代码:

models.py

java.nio

1 个答案:

答案 0 :(得分:0)

您的代码中有一些错误。发出POST请求时,则必须检查pk值。如果有pk,则应更新模型,否则保存新实例。

if request.method == "POST":
    if pk and form.is_valid():
        // here update the model