图像字段表单未验证



这个视图有两个窗体

def anunciocreateview(request):
anuncio_form = AnuncioForm(request.POST or None)
producto_form = ProductoForm(request.POST or None)
if request.method == "POST":
if all([anuncio_form.is_valid(), producto_form.is_valid(), imagen_form.is_valid()]):
anuncio = anuncio_form.save(commit=False)
anuncio.anunciante = request.user
anuncio.save()
producto = producto_form.save(commit=False)
producto.anuncio = anuncio
producto.save()
return HttpResponse(status=204, headers={'HX-Trigger' : 'eventsListChanged'})
else:
anuncio_form = AnuncioForm()
producto_form = ProductoForm()
context = {
'anuncio_form' : anuncio_form,
'producto_form' : producto_form,
}
return render(request, 'buyandsell/formulario.html', context)

This view works OKAY;它允许用户创建具有正确关系的两个模型的实例。我正在尝试为产品的形象添加另一种形式。我试着添加这个:

def anunciocreateview(request):
anuncio_form = AnuncioForm(request.POST or None)
producto_form = ProductoForm(request.POST or None)
imagen_form = ImagenForm(request.POST, request.FILES)
if request.method == "POST":
if all([anuncio_form.is_valid(), producto_form.is_valid(), imagen_form.is_valid()]):
anuncio = anuncio_form.save(commit=False)
anuncio.anunciante = request.user
anuncio.save()
producto = producto_form.save(commit=False)
producto.anuncio = anuncio
producto.save()
imagen = imagen_form.request.FILES.get('imagen')
if imagen:
Imagen.objects.create(producto=producto, imagen=imagen)
return HttpResponse(status=204, headers={'HX-Trigger' : 'eventsListChanged'})
else:
print(request.FILES)
else:
anuncio_form = AnuncioForm()
producto_form = ProductoForm()
imagen_form = ImagenForm()
context = {
'anuncio_form' : anuncio_form,
'producto_form' : producto_form,
'imagen_form' : imagen_form
}
return render(request, 'buyandsell/formulario.html', context)

但是会发生这样的情况:1-'Image upload'表单字段显示错误'This field is required'在渲染表单的时刻。2-如果上传图片并点击提交,重定向不会发生,因为imagen_form没有被标记为有效。控制台没有弹出任何错误(我正在处理html请求)。

如果在实例化表单时省略'request.FILES',则表单呈现时的错误会消失,但无论如何都不会上传图像或表单。

我错过了什么?


供参考,这里是HTML文件:

<form class="row g-3" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Create new listing</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="{{ anuncio_form.titulo.auto_id }}">{{ anuncio_form.titulo.label }}</label>
{% render_field anuncio_form.titulo|add_error_class:"is-invalid" class="form-control" %}
</div>
<div class="mb-3">
<label for="{{ anuncio_form.envio.auto_id }}">{{ anuncio_form.envio.label }}</label>
{% translate "Select available delivery options" as input_place_holder %}
{% render_field anuncio_form.envio|add_error_class:"is-invalid" class="form-control" placeholder=input_place_holder %}
</div>
<h5>Product:</h5>
<div class="mb-3">
<label for="{{ producto_form.nombre.auto_id }}">{{ producto_form.nombre.label }}</label>
{% translate "Name of your product" as input_place_holder %}
{% render_field producto_form.nombre|add_error_class:"is-invalid" class=" form-control" placeholder=input_place_holder %}               
</div>
<div class="mb-3">
<label for="{{ producto_form.descripcion.auto_id }}">{{ producto_form.descripcion.label }}</label>
{% translate "Give a detailed description of your product" as input_place_holder %}
{% render_field producto_form.descripcion|add_error_class:"is-invalid" class=" form-control" placeholder=input_place_holder %}              
</div>
<div class="row g-3">
<div class="col-md-6">
<div class="mb-3">
<label for="{{ producto_form.estado.auto_id }}">{{ producto_form.estado.label }}</label>
{% render_field producto_form.estado|add_error_class:"is-invalid" class=" form-control" %}              
</div> 
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="{{ producto_form.cantidad.auto_id }}">{{ producto_form.cantidad.label }}</label>
{% render_field producto_form.cantidad|add_error_class:"is-invalid" class=" form-control" %}                
</div> 
</div>
</div>
<div class="row g-3">
<div class="col-md-6">
<div class="mb-3">
<label for="{{ producto_form.precio_unitario.auto_id }}">{{ producto_form.precio_unitario.label }}</label>
{% render_field producto_form.precio_unitario|add_error_class:"is-invalid" class=" form-control" %}                 
</div> 
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="{{ producto_form.disponibilidad.auto_id }}">{{ producto_form.disponibilidad.label }}</label>
{% render_field producto_form.disponibilidad|add_error_class:"is-invalid" class=" form-control" %}              
</div> 
</div>
</div>
<h5>Images:</h5>
<div class="mb-3">
<label for="{{ imagen_form.imagen.auto_id }}">{{ imagen_form.imagen.label }}</label>
{% render_field imagen_form.imagen|add_error_class:"is-invalid" class=" form-control" %}                
</div>
<div id="productforms"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-tertiary" hx-get="{% url 'buyandsell:create-product' %}" hx-target="#productforms" hx-swap="beforeend">Add new product</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary" hx-post="{% url 'buyandsell:createview' %}">Submit</button>
</div>
</div>
</form>

编辑:

forms.py for ImagenForm:

class ImagenForm(ModelForm):
class Meta:
model = Imagen
fields = ['imagen']

models.py for Imagen模型:

class Imagen(models.Model):
producto = models.ForeignKey(Producto, on_delete=models.CASCADE, related_name='imagen', blank=True, null=True)
imagen = models.ImageField(upload_to='marketplace/')
def __str__(self):
return f"Imagen de {self.producto}"
def save(self, *args, **kwargs):
self.image = resize_image(self.image, size=(350, 350))
super().save(*args, **kwargs)

如果不是POST请求,不要用request.POST初始化表单

修复你的问题:

  • 移动if request.method == "POST"下的第一个init块
  • else块向左移动一个标签,使其变为elseif request.method == "POST",而不是当前版本的elseif .is_valid()
if request.method == "POST":
anuncio_form = AnuncioForm(request.POST or None)
producto_form = ProductoForm(request.POST or None)
imagen_form = ImagenForm(request.POST, request.FILES)
if all([anuncio_form.is_valid(), producto_form.is_valid(), imagen_form.is_valid()]):
...
else:
anuncio_form = AnuncioForm()
producto_form = ProductoForm()
imagen_form = ImagenForm()

现在您只在POST请求上使用request.POST,而不是显示空表单。如果一个表单在POST上是无效的,那么它将显示错误(如果模板是正确完成的),而不是再次显示空表单。

用一个视图/模板处理多个表单,看看这些答案:one two three

乌利希期刊指南

HTMX-请求还需要在form元素属性中设置hx-encoding="multipart/form-data"。类似问题html docs

最新更新