django 1.8: si el resultado de la consulta de entrada del formulario no coincide con la base de datos, muestre un mensaje de alerta en la misma página, en lugar de “Ninguno” o levante la página de excepción

Estoy agradecido con las respuestas a continuación, pero lamento no haber resuelto este problema, tal vez no las entendí correctamente. Por lo tanto pongo una recompensa por esto para una respuesta más clara.

Después de que el usuario ingrese alguna información en el formulario, esta información funciona como una consulta para filtrar la base de datos para obtener el resultado, si no hay un registro correspondiente en la base de datos, ¿cómo podría haber una alerta en la página actual o una página redirigida para alertar a los usuarios? “No hay datos correspondientes”.

introduzca la descripción de la imagen aquí

Tome un ejemplo como imagen: si el usuario ingresa “EU” e “India”, seguramente no hay un registro correspondiente en la base de datos. Y el formulario permite al usuario dejar los campos en blanco.

Solía ​​usar ValidationError elevado, si el resultado de la consulta no coincide con la base de datos, irá a una página amarilla de “Excepción” que no es fácil de usar. Quiero mostrar un mensaje de error en la página del formulario MISMO justo después de enviarlo:

vistas.py

from django.contrib import messages class InputFormView(FormView): template_name = 'entryform.html' form_class = EntryForm def get_success_url(self): params = { 'department': self.request.POST.get('company'), 'person': self.request.POST.get('region') } return ''.join([reverse('final'), '?', urllib.urlencode(params.items())]) class FinalView(ListView): context_object_name = 'XXX' template_name = 'XXX.html' model = Final def get_queryset(self): form = InputForm(self.request.GET) if form.is_valid(): department = form.cleaned_data['department'] person = form.cleaned_data['person'] if department !="" and person !="": if Final.objects.filter(department=department,person=person).exists(): queryset=Final.objects.filter(department=department,person=person) return queryset else: msg="no corresponding data exists!" form.add_error('department', msg) form.add_error('person', msg) elif department =="" and person !="": if Final.objects.filter(person=person).exists(): queryset=Final.objects.filter(person=person) return queryset else: msg="no corresponding data exists!" form.add_error('department', msg) form.add_error('person', msg) elif ........ else: #if form not valid messages.error(request, "Error") def get_context_data(self,**kwargs): query_set = self.get_queryset() if query_set is not None: context["sales"] = self.get_queryset().aggregate(Sum('sales')) 

html

  {% csrf_token %} {% csrf_token %} {{ formset.management_form }} {{ formset.errors }} {{ formset.non_field_errors }} {{ formset.non_form_errors }} {{ form.non_field_errors }} ......  
..........same for person.....

Si no uso el método ValidationError, se redireccionará a la página de resultados que muestra todo como “Ninguno”. Pero quiero mostrar un mensaje de alerta. Vi que había un ejemplo de ajax en línea, que es un poco complicado. ¿Hay alguna forma más fácil de realizarlo?

Gracias por adelantado.

Gracias.

¿Si entiendo correctamente, FinalView debería filtrar en los parámetros GET?

¿Realmente necesitas el formulario si ese es el caso? Parece que quieres presentar “¡no existe ningún dato correspondiente!” Si no se obtiene ningún resultado? ListView genérico rellena automáticamente self.object_list (o context_object_name) desde get_queryset, por lo que una simple comprobación object_list.exists () debería ser suficiente en el código o la plantilla para representar el mensaje de error …

Para hacer un filtro simple, le daré un ejemplo de una técnica que generalmente uso transformada para su ejemplo:

 class FinalView(ListView): def get_queryset(self): qs = super(FinalView, self).get_queryset() filter_fields = ('department', 'person') # the fields to filter on query_dict = {} # filter query for param in self.request.GET: # iterate all params if param in filter_fields: # is param a filter we want to use? value = self.request.GET.get(param) if value: # Have value? otherwise ignore query_dict[param] = value return qs.filter(**query_dict) # Execute filter def get_context_data(self, **kwargs): kwargs = super(FinalView, self).get_context_data(**kwargs) if self.object_list.exists(): # Did we get objects? (this can also be done directly in template) kwargs['error_msg'] = 'no corresponing data exist!' else: kwargs["sales"] = self.object_list.aggregate(Sum('sales')) # Re-populate form if we want that kwargs['form'] = InputForm(initial=self.request.GET) return kwargs 

No sé si se ajusta a sus necesidades. Pero es una solución alternativa.

Elaboración de formularios en django: los formularios en django se utilizan (entre otras cosas) para validar los datos de entrada y crear los tipos de python apropiados a partir de los campos. (Es decir, IntegerField será un entero, etc.) Roles para formularios

En este caso, los datos se utilizan para filtrar un queryset. Los datos en sí mismos son válidos, pero no el resultado que utiliza los datos.

Los “roles” para el ListView y el formulario son importantes: la vista filtra el conjunto de consultas, el formulario django valida los datos de entrada.

La vista debe controlarse si no estamos contentos con el resultado después de ejecutar el filtro, la forma django debe controlar si los datos de entrada son incorrectos. (Es decir, formato incorrecto, campos vacíos o departamento no debe estar vacío si la persona está llena, etc.).

Sobre la base de la pregunta, sabemos que la entrada a FinalView será de cadenas o estará vacía. (El self.request.GET es siempre cadenas o está vacío), ¿la necesidad de un formulario django aquí podría complicar las cosas?

Toda esta lógica pertenece dentro de la propia forma. Si lo pone en el método de clean , la lógica de Django existente {{ form.non_field_errors }} el error de validación y puede mostrar el error en la plantilla con {{ form.non_field_errors }} .

Si estás atascado con django <1.7, puedes usar self._errors.add (gracias a @Sayse). Si estás en django 1.7 o más reciente puedes usar Form.add_error() :

Este método permite agregar errores a campos específicos desde dentro del método Form.clean (), o desde fuera del formulario; por ejemplo, desde una vista.

El argumento del campo es el nombre del campo al que se deben agregar los errores. Si su valor es Ninguno, el error se tratará como un error no de campo como lo devuelve Form.non_field_errors ().

El argumento de error puede ser una cadena simple, o preferiblemente una instancia de ValidationError. Consulte Levantamiento del error de validación para conocer las mejores prácticas al definir errores de formulario.

Debe verificar si no hay un registro correspondiente en la base de datos en el método de clean del form o antes de llamar a form.is_valid() en la vista, y adjunte el error al campo:

 form.addError("region", ValidationError('No corresponding data exists')) 

PD: Para desactivar la “página de excepción amarilla”, desactive DEBUG en su configuración.

¿Por qué no algo como esto?

vistas.py

 if form.is_valid(): region = form.cleaned_data['region'] start_date=form.cleaned_data['start_date'] end_date=form.cleaned_data['end_date'] .... queryset=Result.objects.filter(region=region,date__range=[start_date,end_date]) try: result = Result.objects.get(region=region,supply_chain=supply_chain) except Result.DoesNotExist: result = None 

template.html

 {% if not result %} No corresponding data exists {% else %} {# display data #} {% endif %} 

Permítanme comenzar diciendo que esta respuesta solo reitera lo que Daniel Roseman y Sebastian Wozny dijeron en sus respuestas, así que lo aliento a que acepte uno de esos sobre esto.

Su get_queryset tiene un trabajo homónimo, y es recuperar el conjunto de consultas que utiliza su formulario para que no tenga que hacer ningún tipo de manejo de errores.

Eso debe hacerse en el método clean del formulario.

 def clean(self): cleaned_data = super(MyForm, self).clean() region = cleaned_data.get('region') country = cleaned_data.get('country') if not Result.objects.filter(region=region, country=country).exists(): self.add_error(ValidationError('No corresponding data exists')) 

Ahora, qué ocurrirá, si su formulario no es válido, puede regresar a la misma plantilla con este formulario y contendrá errores sobre los campos que no son válidos.