【问题标题】:Django: Catching Integrity Error and showing a customized message using templateDjango:捕获完整性错误并使用模板显示自定义消息
【发布时间】:2012-07-02 12:07:15
【问题描述】:

在我的 django 应用程序中,只有一种明显的情况会出现“IntegrityError”。
那么,我如何才能捕获该错误并使用模板显示消息?

【问题讨论】:

    标签: python django


    【解决方案1】:

    只需使用 try 和 catch。

    from django.db import IntegrityError
    from django.shortcuts import render_to_response
    
    try:
        # code that produces error
    except IntegrityError as e:
        return render_to_response("template.html", {"message": e.message})
    

    如果您愿意,可以使用模板中的消息。

    编辑

    感谢Jill-Jênn Vie,您应该使用e.__cause__as described here

    【讨论】:

    • 谢谢,我不明白为什么“从 MySQLdb 导入 IntegrityError”没有起作用。调用堆栈似乎表明是库引发了错误,但它以某种方式移动到了 django.db。 Grr.
    • 正如docs of v1.6 中指出的那样,e.__cause__ 是首选,根据PEP 3134
    • 如果你没有收到消息,试试这个:e.args
    • e.message 对我不起作用,但 e.args[1] 确实完成了这项工作
    • @blissini - 我已将链接更改为指向开发文档
    【解决方案2】:

    如果您使用带有CreateView mixin 的基于类的视图,您需要通过try 调用超类的form_valid,例如:

    from django.db import IntegrityError
    ...
    class KumquatCreateView(CreateView):
        model = Kumquat
        form_class = forms.KumquatForm
        ...
        def form_valid(self, form):
            ...
            try:
                return super(KumquatCreateView, self).form_valid(form)
            except IntegrityError:
                return HttpResponse("ERROR: Kumquat already exists!")
    

    当然,您可以使用模板、render_to_response 等来使输出更好。

    【讨论】:

      【解决方案3】:

      最简单的解决方案:编写一个实现 process_exception 的中间件,它只捕获 IntegrityError 并使用渲染的模板返回一个 HttpResponse,并确保此中间件位于默认错误处理中间件之后,因此在之前调用它(参见 https://docs.djangoproject.com/en/dev/topics/http/middleware/#process-exception 了解更多信息)。

      现在,如果我是你,我不会假设“只有一种明显的情况会出现“IntegrityError””,所以我强烈建议你在你的文件中记录异常(并发送电子邮件警报)中间件。

      【讨论】:

      • 将其放入中间件不仅会捕获应用程序中的错误,还会捕获项目中的所有应用程序。
      • @ChrisWesseling:完全同意,这就是为什么我提到“我不会假设“只有一种明显的情况会出现“IntegrityError”””
      • 枪不会射人脚,人会射人脚。 :-)
      • 我不会称其为最简单的解决方案,但它是一个有用的替代方案。谢谢。
      【解决方案4】:

      我会用 ModelForm 来验证它。例如:

      你有模型:

      class Manufacturer(models.Model):
          name = models.CharField(default='', max_length=40, unique=True)
      

      和ModelForm:

      class ManufacturerForm(forms.ModelForm):
      
          def clean(self):
              cleaned_data = super(ManufacturerForm, self).clean()
              name = cleaned_data.get('name')
              if Manufacturer.objects.filter(name=name).exists():
                  raise forms.ValidationError('Category already exists')
      
          class Meta:
              model = Manufacturer
      

      在这种情况下,当您提交唯一的名称时。您将在 IntegrityError 之前收到验证错误。 “类别已存在”消息将显示在模板中的表单中

      【讨论】:

        【解决方案5】:

        我是这样做的

        from django.db import IntegrityError
        from django.shortcuts import render
        
        from .models import Person
        from .forms import PersonForm
        
        class PersonView(View):
        
        def get(self, request):
            pd = PersonForm()
            return render(request, "app1/my_form.html", context={ 'form': pd })
        
        
        
        def post(self, request):
            pd = PersonForm(request.POST)
        
        
            if pd.is_valid():
                name = pd.cleaned_data['name']
                age = pd.cleaned_data['age']
                height = pd.cleaned_data['height']
        
                p = Person()
                p.name = name
                p.age = age
                p.height = height
                try:
                    p.save()
                except IntegrityError as e:
                    e = 'this data already exists in the database'
                    return render(request, "app1/my_form.html", context={ 'form': pd, 'e': e})
        
                context = {
                'person': {
                    'name': name,
                    'age': age,
                    'height': height,
                },
                'form': pd
                }
        
            else:
                print("Form is invalid")
                context = { 'form': pd }
        
            return render(request, "app1/my_form.html", context=context)
        

        在模板中,我可以访问错误为 {{ e }}

        【讨论】:

          【解决方案6】:

          只需导入 IntegrityError

          from django.db import IntegrityError
          

          并在 try/Except 中使用它

          try:
              //Do what is needed to be done
           except IntegrityError as e:
              //return what is supposed to be returned
          

          感谢@Soren,我刚刚编辑了我的答案

          【讨论】:

          • 那不告诉怎么做。
          猜你喜欢
          • 2019-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-02
          • 1970-01-01
          • 2014-11-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多