我是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
(实例未更新)。memoria
和title
字段中进行更改,则会保存一个新的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
答案 0 :(得分:0)
您的代码中有一些错误。发出POST请求时,则必须检查pk
值。如果有pk,则应更新模型,否则保存新实例。
if request.method == "POST":
if pk and form.is_valid():
// here update the model