在ModelForm中是唯一的,如何返回带有错误消息的表单?

时间:2013-04-12 11:07:12

标签: database django django-models django-forms django-views

我发现了一些关于this onethis other one或多或少相同情况的帖子,但我无法适应我的情况。 我想要的是,如果用户尝试创建另一个与他自己已经存储在db中的名称相同的模型,则返回我的表单并发出警告。 我想使用Django内置的设施here,但我需要一些建议来改变我的代码:请问你帮我吗? 我的代码如下:

  • models.py

    class ShapeFile(models.Model):
        name = models.CharField(max_length=100)
        srid = models.ForeignKey(SpatialRefSys)
        model_definition = models.OneToOneField(ModelDefinition)
        user = models.ForeignKey(User)
        color_table = models.ManyToManyField(ColorTable)
        file = models.FileField(upload_to=get_upload_path)
        class Meta:
            unique_together = ('name', 'user')
    
  • forms.py

    class UploadForm(ModelForm):
        class Meta:
            model = ShapeFile
            fields = ('name','srid','file','color_table')
            widgets = {'srid': TextInput()}
    
  • views.py

    @login_required
    def index(request):
        if request.method == 'POST':
            form = UploadForm(request.POST, request.FILES)
            if form.is_valid():
                req = request.POST
                sridVal = form.cleaned_data['srid'].pk
                shpVal = form.cleaned_data['name']
    
                # The final table name is something like 'mutant_celeryPy2_123_salzburg_lc'
                end_table_name = request.user.username + "_" + shpVal + '_lc'
    
                # Creates a table, otherwise return the retrieved one
                model_def, created = ModelDefinition.objects.get_or_create(
                    app_label='celeryPy2',
                    object_name=end_table_name,
                    defaults=dict(
                       bases=(BaseDefinition(base=GeoModel),),
                       fields=(GeometryFieldDefinition(name='the_geom', srid=sridVal),
                               SmallIntegerFieldDefinition(name='cat'),)
                    )
                )
                obj = form.save(commit=False)
                obj.user = request.user
                obj.model_definition = model_def
                obj.save()
                messages.success(request, 'Shapefile upload succesful!')
                return HttpResponse('Stored!')
            else:
                print "Upload shapefile form is invalid!!!"
        else:
            form = UploadForm()
    
        return render_to_response('celeryPy2/index.html',
                                  {'form': form,},
                                  context_instance=RequestContext(request))
    

如果我以user1身份登录并填写表单,请假设名称为'myshape',当我提交时,我会收到“存储!”消息:一切正常,模型user1_myshape_lc已创建。 如果我使用相同的user1重新登录并尝试存储其他数据,其字段名称设置为'myshape',就像之前一样,我正确地获得了异常:

    Exception Type: IntegrityError at /celeryPy2/main
    Exception Value: duplicate key value violates unique constraint "celeryPy2_shapefile_model_definition_id_key"
    DETAIL:  Key (model_definition_id)=(154) already exists.

如何使用警告取回我的表单而不是获取Django异常错误消息? 谢谢。

2 个答案:

答案 0 :(得分:1)

模型表单验证应该处理此问题并引发验证错误。但是您已从表单中排除user字段,这是unique_together约束的一部分,因此无法验证。参考validate_unique

您可以尝试更改视图代码,在已发布的数据中添加user字段,然后实例化该表单。

或者更好的方法是在表单中添加隐藏的用户字段,以便在request.POST中可用,并且验证可以根据需要运行。

答案 1 :(得分:0)

感谢Rohan,我发现隐藏的字段解决方案是最好的:现在我正确地找回了我的表单,并显示错误消息:Shape file with this Name and User already exists。 这是我修改过的代码,可以让事情顺利进行:

  • <强> forms.py

    class UploadForm(ModelForm):
        class Meta:
            model = ShapeFile
            fields = ('name','user','srid','file','color_table')
            widgets = {'srid': TextInput(), 'user': HiddenInput()}
    
  • <强> views.py

    @login_required
    def index(request):
        if request.method == 'POST':
            form = UploadForm(request.POST, request.FILES)
            if form.is_valid():
                req = request.POST
                sridVal = form.cleaned_data['srid'].pk
                shpVal = form.cleaned_data['name']
    
                # The final table name is something like 'mutant_celeryPy2_123_salzburg_lc'
                end_table_name = request.user.username + "_" + shpVal + '_lc'
    
                # Creates a table, otherwise return the retrieved one
                model_def, created = ModelDefinition.objects.get_or_create(
                    app_label='celeryPy2',
                    object_name=end_table_name,
                    defaults=dict(
                       bases=(BaseDefinition(base=GeoModel),),
                       fields=(GeometryFieldDefinition(name='the_geom', srid=sridVal),
                               SmallIntegerFieldDefinition(name='cat'),)
                    )
                )
                obj = form.save(commit=False)
                obj.model_definition = model_def
                obj.save()
                messages.success(request, 'Shapefile upload succesful!')
                return HttpResponse('Stored!')
            else:
                print "Upload shapefile form is invalid!!!"
        else:
            form = UploadForm(initial={'user': request.user})
    
        return render_to_response('celeryPy2/index.html',
                                  {'form': form,},
                                  context_instance=RequestContext(request))