【问题标题】:Django updating or inserting duplicated rowsDjango 更新或插入重复的行
【发布时间】:2014-10-24 22:14:35
【问题描述】:

我创建了几个表单来编辑一些记录。当我保存表单时,我可以在数据库中看到应用程序更新了记录并插入了一个或两个记录。

我用来更新记录的所有表单都有这种奇怪的行为。我不知道错误是在表单定义中还是在视图定义中。

型号

class DetalleRecepcion(models.Model):
    id_proveedor = models.ForeignKey(Proveedor,db_column='id_proveedor',primary_key=True,      verbose_name='Proveedor')
    anio = models.IntegerField( null=False)
    mes = models.IntegerField(verbose_name='Mes')
    fecha_recepcion = models.DateField(verbose_name='Fecha Recepcion')
    usuario = models.CharField(max_length=15, blank=True)
    num_archivos = models.IntegerField(primary_key=True, verbose_name='No de archivos')

    class Meta:
        managed = False
        db_table = 'mpc_detalle_recepcion'

查看

@login_required(login_url='/login/')
def DetRecView(request):
    idp = request.GET.get('i')
    anio = request.GET.get('a')
    mes = request.GET.get('m')
    if request.method == 'POST':
       r = DetalleRecepcion.objects.get(id_proveedor=idp,anio=anio,mes=mes)
       form = DetRecForm(request.POST or None, instance =r)
       if form.is_valid():
          form.save()
          return HttpResponse('<script type="text/javascript">window.close()</script>')
    else:
       r = DetalleRecepcion.objects.get(id_proveedor=idp,anio=anio,mes=mes)
       r.usuario = request.user
       form = DetRecForm(instance=r)

    return render_to_response('detrec.html',
                              {'form':form},
                              context_instance=RequestContext(request))

表格

class DetRecForm(forms.ModelForm):
      fecha_recepcion = forms.DateField(widget=DateInput(),)
      def __init__(self,*args,**kwargs):
          super(DetRecForm,self).__init__(*args,**kwargs)
          self.helper = FormHelper(self)
          self.helper.layout = Layout(
           Field('id_proveedor',
                 'anio',
                 'mes',
                 'usuario',
                 readonly = True
                 ),
           Fieldset('',
                    'fecha_recepcion',
                    'num_archivos',
                    Submit('save','Grabar'),
                    HTML('<a class="btn btn-danger" id="cerrar">Cancelar</a>')
                    )
          )
      class Meta:
          model = DetalleRecepcion

我使用的是旧数据库,我检查了数据库的约束、过程、触发器,一切看起来都很好。 在表格旁边不要使用任何过程函数等。

只有当我从应用程序更新或插入时,我才能看到这种行为。

更新

urls.py
urlpatterns = patterns('',
    url(r'^recepcion/$','prov.views.DetRecView',name='recepcion'),
    url(r'^newdetrec/$','prov.views.NewDetRecView',name='newdetrec'),
    url(r'^master/$','prov.views.NewMasterView',name='master'),
    url(r'^conci/$', 'prov.views.ConciView',name='conci'),
    url(r'^carga/$', 'prov.views.CargaView',name='carga'),
    url(r'^gencert/$', 'prov.views.GenCertView',name='gencert'),
    url(r'^entcert/$', 'prov.views.EntCertView',name='entcert'),
    url(r'^aceptacert/$', 'prov.views.AceptaCertView',name='aceptacert'),
    url(r'^envconci/$', 'prov.views.EnvConciView',name='envconci'),
)

我的创建视图(对于同一模型)

  @login_required(login_url='/login/')
    @permission_required('prov.views.configView',login_url='/login/')
    def NewDetRecView(request):
        form = NewDetRecForm(request.POST or None)
        if request.method == 'POST':
           idp = request.POST['id_proveedor']
           a = request.POST['anio']
           m = request.POST['mes']
           id = Proveedor.objects.get(id_proveedor=idp)
           obj,created = DetalleRecepcion.objects.get_or_create(id_proveedor=id,anio=a,mes=m)
           obj.save()
           return HttpResponseRedirect('/monitor/')

           if not created:
              obj.id_proveedor = id
              obj.anio = a
              obj.mes = m
              obj.save()
              return HttpResponseRedirect('/monitor/')
        return render_to_response('newdetrec.html',
                              {'form':form})

我创建新记录的表单类:

class NewDetRecForm(forms.ModelForm):
      def __init__(self,*args,**kwargs):
       super(NewDetRecForm,self).__init__(*args,**kwargs)
       self.helper = FormHelper(self)
       self.helper.layout.append(Submit('save','Grabar'))
       self.helper.layout = Layout(
        Fieldset('',
                 'id_proveedor',
                 'anio',
                 'mes',
                 Submit('save','Grabar'),
                )
       )
      def clean(self):
        cleaned_data = super(NewDetRecForm, self).clean()

        id_proveedor = self.cleaned_data['id_proveedor']
        #num_archivos = self.cleaned_data['num_archivos']
        anio = self.cleaned_data['anio']
        mes = self.cleaned_data['mes']

        qs = self.Meta.model.objects.filter(id_proveedor=id_proveedor, anio=anio, mes=mes)
        if self.instance:
            qs = qs.exclude(pk = self.instance.pk)
        if qs.count() > 0:
            raise forms.ValidationError(u'Registro ya existente')

        return cleaned_data
      class Meta:
        model = DetalleRecepcion

DetRecForm 用于更新

DetRecView 用于更新

NewDetRecForm 用于创建

NewDetRecView 用于创建

更新 2

传参的javascript函数

<script type="text/javascript">
  $(document).ready ( function () {
    $(document).on ("click", "#recepcion", function (event) {
        event.preventDefault();
        var tbl = document.getElementById("myTable");
        var idpro = $(this).parents('tr:first').find('td:first').text();
        var anio = $(this).closest('tr').children(":eq(1)").text();
        var mes = $(this).closest('tr').children(":eq(2)").text();
        var argu = "?i="+idpro+"&a="+anio+"&m="+mes;
        //window.location = "/recepcion/"+argu;
        var url = "/recepcion/"+argu;
        window.open(url,'_blank')
    });
});
</script>

我知道这不是将参数传递给模板的正确方法。 我开始学习 AJAX 来传递数据,但同时我使用这个可怕的功能

【问题讨论】:

  • 你能显示你的urls吗?
  • 当必须更新对象时,您应该将instance 设置为您的form_class,而不是在必须创建对象时
  • 我粘贴了部分网址。我开始学习DJANGO,我犯了很多新手错误。如何在 form_class 中设置实例。

标签: django django-forms django-views


【解决方案1】:
url(r'^recepcion/add/$','prov.views.DetRecView',name='recepcion_add'),  # create object
url(r'^recepcion/edit/(?P<pk>\d+)/$','prov.views.DetRecView',name='recepcion_edit'),  # update object

让我们在视图函数中看看你的情况:if request.method=='POST' 更好地使用if request.POST

所以当你有else - 这意味着request.GET 你得到一个DetalleRecepcion 的实例(将实例读取为某个类的对象)并将它传递给你的ModelForm。它是 update 对象方法(但您使用它来创建 对象),并且提供的查询必须给出一个对象(唯一)。

如果你想使用这个视图来createupdate你必须改变你的url(就像我上面做的那样)你必须定义条件:if request.kwargs.get('pk')你要更新对象else你要创建对象。

主要区别在于,如果是 update 情况,您必须为您的表单提供实例 r = DetalleRecepcion.objects.get(pk=request.kwargs['pk']),所以 DetRecForm(instance=r) (whenrequest.GET) 和 form = DetRecForm(request.POST, instance =r) (whenrequest.POST) .

如果你想为你的表单提供一些初始数据(当request.GET)使用DetRecForm(initial = {'id_proveedor': idp, 'anio': anio, 'mes': mes, 'usuario': request.user})

【讨论】:

  • 我只使用这个视图来更新记录,我创建了一个不同的视图来创建记录。用户必须更新记录,但只有管理员(我)可以创建新记录。我将更新帖子,您可以查看我的创建视图。创建或更新我插入了重复的行。谢谢你。
  • 您应该根据上面的建议更新您有问题的代码(以及为什么您使用get_or_create,如果您有表格form.save())。
  • 我会按照你的建议使用 get_or_create 因为我得到了 id_proveedor 已经存在的异常。这是一个遗留数据库,我遇到了一些关于主键和外键的问题。我将删除 .save() 行
  • 很抱歉打扰你,但我有一个问题要问你@madzohan。如何将参数从 HTML 表传递到模板。我认为我的问题是我如何将参数传递给编辑表单模板。在尝试将使用 django-tables2 呈现的 html 表中的值传递给编辑表单时,我遇到了很多错误。我终于用一个可怕的javascript函数做了这个。我粘贴了我用来在帖子中传递参数的函数。
  • django-tables2 将查询集渲染为模板上的 html 表,因此您首先在视图查询集中拥有的所有渲染数据。所以我不明白你的意思是“我如何将参数从 HTML 表传递到模板”,因为它已经存在了。你到底想做什么?
猜你喜欢
  • 2020-10-21
  • 1970-01-01
  • 2014-02-02
  • 1970-01-01
  • 2017-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-02
相关资源
最近更新 更多