简体   繁体   English

django 1.8-如果表单条目查询结果与数据库不匹配,则在同一页面上显示警告消息,而不是“无”或引发异常页面

[英]django 1.8- if form entry query result does't match database, display alert message on same page, instead of “None” or raise exception page

I am grateful to the answers below, but sorry I still didn't resolve this issue maybe I didn't understand them correctly. 我很感谢下面的答案,但很抱歉,我仍然没有解决这个问题,也许我没有正确理解它们。 Therefore I put a bounty for this for clearer answer. 因此,我为此付了一笔赏金,以便更清楚地回答。

After user entering some information in the form, these information works as a query to filter the database to get the result, if there is no corresponding record in the database, how could I have an alert displaying on the current page or redirected page alerting users "No corresponding data". 用户在表单中输入一些信息后,这些信息作为查询来过滤数据库以获得结果,如果数据库中没有相应的记录,我怎么能在当前页面上显示警报或重定向页面警告用户“没有相应的数据”。

在此输入图像描述

Take an example as picture: if user enters "EU" and "India", for sure there is no corresponding record in the database. 举例如图:如果用户输入“EU”和“India”,确定数据库中没有相应的记录。 And the form allows the user to leave the fields blank. 表单允许用户将字段留空。

I used to use raise ValidationError, if query result doesn't match database, it will go to a yellow "Exception" page which is not user-friendly. 我以前使用raise ValidationError,如果查询结果与数据库不匹配,它将转到黄色的“异常”页面,这不是用户友好的。 I want to display an error message on the SAME form page right after submitting it : 我想在提交后立即在SAME表单页面上显示错误消息:

views.py views.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 HTML

 <form method="post">{% csrf_token %}
        {% csrf_token %}
      {{ formset.management_form }}
      {{ formset.errors }}
      {{ formset.non_field_errors }}
      {{ formset.non_form_errors }}
      {{ form.non_field_errors }}     
     ......                   
        <!--select department-->
        <div class="field" >
            <label> Select department:
            {{ form.department }}
                {% for department in form.department.choices %}                    
                     <option value="department" name= "department" id="id_department">{{department}} </option>
                {% endfor %}
            </label>
        </div>     

..........same for person.....                    

        <!--submit-->
        <div class="button" id="btnShow"><input type="submit" value="Submit" /></div>

        </div>
 </form>

If I don't use the ValidationError method, it will redirect to result page showing everything as "None". 如果我不使用ValidationError方法,它将重定向到结果页面,显示所有内容为“无”。 But I want to display an alert message. 但我想显示一条警告信息。 I saw there was an ajax example online, which is a little bit complicated. 我看到网上有一个ajax示例,这有点复杂。 Is there any easier way to realize it? 有没有更简单的方法来实现它?

Thanks in advance. 提前致谢。

Thanks. 谢谢。

If you're stuck with django <1.7 you can use self._errors.add (thanks to @Sayse). 如果你坚持使用django <1.7,你可以使用self._errors.add (感谢@Sayse)。 If you're on django 1.7 or newer you can use Form.add_error() : 如果您使用的是django 1.7或更高版本,则可以使用Form.add_error()

This method allows adding errors to specific fields from within the Form.clean() method, or from outside the form altogether; 此方法允许从Form.clean()方法中或从表单外部向特定字段添加错误; for instance from a view. 例如从一个视图。

The field argument is the name of the field to which the errors should be added. field参数是应添加错误的字段的名称。 If its value is None the error will be treated as a non-field error as returned by Form.non_field_errors(). 如果其值为None,则将错误视为Form.non_field_errors()返回的非字段错误。

The error argument can be a simple string, or preferably an instance of ValidationError. error参数可以是一个简单的字符串,或者最好是ValidationError的一个实例。 See Raising ValidationError for best practices when defining form errors. 有关定义表单错误时的最佳做法,请参阅Raising ValidationError。

You should check if there is no corresponding record in the database in the clean method of the form or before you call form.is_valid() in the view, and attach the error to the field: 您应该在formclean方法中或在视图中调用form.is_valid()之前检查数据库中是否没有相应的记录,并将错误附加到字段:

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

PS: To turn of the "yellow exception page" turn off DEBUG in your settings. PS:要打开“黄色异常页面”, DEBUG在您的设置中关闭DEBUG

All this logic belongs inside the form itself. 所有这些逻辑都属于表单本身。 If you put it in the clean method, then the validation error will be caught by the existing Django logic and you can display the error in the template with {{ form.non_field_errors }} . 如果将它放在clean方法中,那么验证错误将被现有的Django逻辑捕获,您可以使用{{ form.non_field_errors }}在模板中显示错误。

Why not something like this? 为什么不这样的?

views.py views.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 template.html

{% if not result %} 
    <strong>No corresponding data exists</strong>
{% else %}
    {# display data #}
{% endif %}

Let me just start by saying that this answer is only reiterating what Daniel Roseman and Sebastian Wozny said in their answers so I'd encourage you to accept one of those over this. 首先我要说的是,这个答案只是重申Daniel Roseman和Sebastian Wozny在答案中所说的内容,所以我鼓励你接受其中的一个。

Your get_queryset has one self-titled job, and that is to retrieve the queryset your form uses so it has no business doing any error handling at all. 你的get_queryset有一个自我标题的作业,那就是检索你的表单使用的查询集,这样它就没有任何业务可以进行任何错误处理。

That should be done in the form's clean method 这应该以表单的clean方法完成

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'))

Now what will happen, if your form isn't valid, you can then return to the same template with this form and it will contain errors about the fields that aren't valid. 现在会发生什么,如果您的表单无效,您可以使用此表单返回到相同的模板,它将包含有关无效字段的错误。

If I understand correctly the FinalView should just filter on the GET parameters? 如果我理解正确,FinalView应该只过滤GET参数?

Do you really need the form if that's the case? 如果是这样的话,你真的需要表格吗? I it seem like you want to present "no corresponding data exists!" 我似乎想要呈现“没有相应的数据存在!” if no result is yielded? 如果没有结果? generic Listview automatically populates self.object_list (or the context_object_name) from get_queryset so a simple check object_list.exists() should be enough in code or template to render the error msg... 通用Listview自动从get_queryset填充self.object_list(或context_object_name),因此在代码或模板中应该有一个简单的检查object_list.exists()来渲染错误消息...

To do a simple filter I'll provide an example of a technique I usually use transformed for your example: 要做一个简单的过滤器,我将提供一个我通常使用的技术示例:

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

Don't know if it fits your requirements. 不知道它是否符合您的要求。 But is an alternative solution. 但是是另一种解决方案。

Elaboration of forms in django: The forms in django is used (among other things)to validate input data and create the appropriate python types from the fields. 在django中详细说明表单:使用django中的表单(以及其他内容)来验证输入数据并从字段中创建适当的python类型。 (Ie IntegerField will be an integer etc). (即IntegerField将是一个整数等)。 Roles for forms 表格的角色

In this case the data is used to filter a queryset. 在这种情况下,数据用于过滤查询集。 The data it self is valid but not the result using the data. 它自己的数据是有效的,但不是使用数据的结果。

The "roles" for the ListView and form are important: The view filters the queryset, the django form validates input data. ListView和表单的“角色”很重要:视图过滤查询集,django表单验证输入数据。

The view should handle if we're not happy with the result after executing the filter, the django form should handle if the input data is bad. 如果我们对执行过滤器后的结果不满意,视图应该处理,如果输入数据不好,django表单应该处理。 (Ie bad format, empty fields or department must no be empty if person is filled etc). (即格式不好,空字段或部门如果填满人员,则不得为空)。

Based on the question we know the input to FinalView will be strings or empty. 根据我们知道的问题,FinalView的输入将是字符串或空。 (The self.request.GET is always strings or empty), the need of a django form here might just complicate things? (self.request.GET总是字符串或空的),这里需要一个django表单可能会让事情复杂化?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Django 1.8-土耳其字母引起异常 - Django 1.8- Turkish Letters Cause Exception Django 1.8-堆栈跟踪引用文件不存在 - Django 1.8- Stack trace referencing file that doesn't exist 为什么 Django Admin model 页面在成功迁移后引发 FieldDoesNotExist 异常? - Why does Django Admin model page raise FieldDoesNotExist exception after a successful migration? 在提交页面 Django 之前显示警告消息 - Show An Alert message Before Submitting the Page Django Python:引发exception_class(消息,屏幕,堆栈跟踪)selenium.common.exceptions.UnexpectedAlertPresentException:警报文本:无消息: - Python: raise exception_class(message, screen, stacktrace) selenium.common.exceptions.UnexpectedAlertPresentException: Alert Text: None Message: 在 Django 表单中将数据库条目显示为选项 - Display Database entry as option in a Django Form 与Django在同一页面中的三种形式 - Three Form In Same Page With Django Django:如何在不重新加载页面的情况下提交表单并在同一页面上接收结果 - Django: How to submit the form and receive the result on the same page without reloading the page django表单未显示在页面上 - django The form does not show on the page 如何在新页面中显示 django 搜索结果 - how to display django search result in new page
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM