函数正在更新我的数据库Django

时间:2018-07-13 17:48:49

标签: django django-models django-views

我使此函数可以使用不同的urlsConf多次使用,现在Item模型中的每个元素都使用相同的数据进行更新。从上次正常运行时,我进行了一些更改。

主要更改1:将我的Items模型从抽象表更改为多表继承。

主要更改2:我将函数重构为可以多次使用(在此之前,我在多个地方重写了相同的函数。 我的功能只能更新项目Db上的一个元素。我找不到原因。

views.py 中的功能:

#=========================================================================== #
#   REUSABLE FUNTIONS TO GET CUANTITIES AND TOTALS
# =========================================================================== #

# Recibe un el nombre del link en formato x-incremento o x-decremento 
# y lo parte y guarda en una lista como incremento o decremento
# GETS THE CONTENT FROM URL LIKE THIS XX-incremento OR XX-decremento, REMOVE AND APPEND TO strlist WITHOUT xx_ ("incremento" or "decremento")

def split_s(get_link):
    l = get_link.split('-')
    strlist = []
    for i in l:
        strlist.append(i)
    return strlist[1]

# Actualiza el valor cantidad existente
# UPDATES EXISTING QUATITY DEPENDING THE URL INCREMENTS OR DECREMENTS 
def calcular_nueva_cantidad(ce, up, strlist):
    if strlist == 'incremento':
        total = ce + up
    elif strlist == 'decremento':
        total = -(ce - up)
    else:
        print(F'========> {strlist} no es valido  <=========')
    return total

# Calcula el nuevo valor de cantidad existente
# CALCULATES NEW EXISTING QUANTITY
def calcular_nuevo_total(nce, pu):
    return nce * pu

# crea el formulario para la actualizacion de cantidad existente
class updateForm(forms.Form):
    update = forms.IntegerField()

# MAIN FUNCTION THAT MAKES ALL THE CHANGES PER ITEM
def actualizar_cantidad(request, pk, model, reverselink ):
    # trae de la base de datos el valor de la cantidad_existente 
    cantidad_existente = model.objects.filter(pk=pk).values('cantidad_existente')
    c = cantidad_existente.values_list('cantidad_existente', flat=True)
    ce = c[0]
    # print(F'=========>{ce }<=========') 

    # trae de la base de datos el valor de la precio_unitario 
    precio_unitario = model.objects.filter(pk=pk).values('precio_unitario')
    p = precio_unitario.values_list('precio_unitario', flat=True)
    pu = p[0]
    # print(F'=========>{pu }<=========') 

    # Obteiene item id del tipo de cortador asi puede regresar a la pantalla del listado
    pp = model.objects.filter(pk=pk).values('tipo')
    ppp = pp.values_list('tipo', flat=True)
    pk = ppp[0]
    # print(F'=========>{pk }<=========') 

    # trae de la base de datos el valor de la total
    qs_total = model.objects.values('total')
    # print(F'=========>{qs_total }<=========') 

    if request.method =='POST':
        form = updateForm(request.POST)

        if form.is_valid():
            # captura valor del formulario y lo limpia
            up = form.cleaned_data['update']

            # Obtiene el name de urls para el link segun sea el caso
            get_link = split_s(resolve(request.path_info).url_name)
            #print(F'=========>{get_link }<=========') # Chek que regresa get_link

            # Calcula el nuevo valor de cantidad existente 
            nce = calcular_nueva_cantidad(up, ce, get_link)

            # Actualiza la nueva cantidad existente  
            cantidad_existente.update(cantidad_existente=nce)

            # Calcula el nuevo valor de cantidad existente 
            s_total = calcular_nuevo_total(nce, pu)
            # Actualiza la nueva cantidad existente 
            qs_total.update(total=s_total)


            return  HttpResponseRedirect(reverse(reverselink, args=(pk, )))
        else:
            # Redirect to fail page after POST
            return HttpResponse('')
    else:
        form = updateForm()
    return render(request, 'inventario/update.html', {'form':form})

# =========================================================================== #
#   END REUSABLE FUNTIONS TO GET CUANTITIES AND TOTALS
# =========================================================================== #

我的模型。py:

class Item(models.Model):
    description = models.CharField(max_length=30,)
    numero_parte = models.CharField(max_length=30)
    proveedor = models.ForeignKey(Proveedor, on_delete=models.CASCADE)
    cantidad_existente = models.PositiveIntegerField()
    update = models.PositiveIntegerField(blank=True, default=0)
    cantidad_minima = models.PositiveIntegerField()
    precio_unitario = models.DecimalField(max_digits=7, decimal_places=2)
    total = models.DecimalField(max_digits=7, decimal_places=2, blank=True)
    asignado_a = models.ForeignKey(Empleados, on_delete=models.CASCADE, blank=True, null=True)
    anaquel = models.CharField(max_length=2, choices=ANAQUEL, blank=True, null=True)
    posicion_en_x = models.CharField(max_length=2, blank=True, null=True)
    posicion_en_y = models.CharField(max_length=2, blank=True, null=True)
    activo = models.BooleanField()

    def save(self,*args,**kwargs):
        self.total = self.cantidad_existente * self.precio_unitario
        super().save(*args,**kwargs)


class Cortadores(Item):
    tipo = models.ForeignKey(Tipos_Cortadores,on_delete=models.CASCADE)
    material = models.ForeignKey(Materiales, on_delete=models.CASCADE)
    filos = models.CharField(max_length=5, choices=GABILANES)
    diametro = models.ForeignKey(Diametros, on_delete=models.CASCADE)
    longitud = models.ForeignKey(Longitud, on_delete=models.CASCADE)
    desbaste = models.CharField(max_length=1, choices=DESBASTE)

    class Meta:
        verbose_name_plural = "Cortadores"

    def get_absolute_url(self):
        return reverse('inventario:cortadores-list', kwargs={'id': self.tipo.id})

    def __str__(self):
        return '%s %s %s %s %s %s' % (  str(self.tipo), str(self.material), str(self.filos), str(self.diametro), 
                                        self.longitud, self.desbaste
                                        )


class Tornillos(Item):
    tipo =  models.ForeignKey(Tipo_Tornillo, on_delete=models.CASCADE)
    paso = models.ForeignKey(Paso_Tornillo, on_delete=models.CASCADE)
    material = models.ForeignKey(Materiales, on_delete=models.CASCADE)
    longitud = models.ForeignKey(Longitud, on_delete=models.CASCADE)

    class Meta:
        verbose_name_plural = "Tornillos"


    def get_absolute_url(self):
        return reverse('inventario:tornillos-list', kwargs={'id': self.tipo.id})

    def __str__(self):
        return '%s %s %s %s' % (str(self.tipo), str(self.paso), str(self.material), str(self.longitud))

我的ulrs.py

# http://<domain.com>/nuevos-articulos/herramientas-de-corte/categoria-cortadores/<id-cortador>/incrementa/
path('nuevos-articulos/herramientas-de-corte/categoria-cortadores/<int:pk>/inc/', 
    views.actualizar_cantidad, 
    # DICIONARIO PASA VARIABLE CON MODELO Y EL LINK PARA REVERSE 
    {'model':Cortadores, 'reverselink':'inventario:cortadores-list'}, 
    name='c-incremento' 
),

path('nuevos-articulos/herramientas-de-corte/categoria-cortadores/<int:pk>/dec/', 
    views.actualizar_cantidad, 
    # DICIONARIO PASA VARIABLE CON MODELO Y EL LINK PARA REVERSE 
    {'model':Cortadores, 'reverselink':'inventario:cortadores-list'}, 
    name='c-decremento'
),


# INCREMENTO O DECREMENTO DE TORNILLOS 
path('nuevos-articulos/herramientas-de-corte/categoria-tornillos/<int:pk>/inc/', 
    views.actualizar_cantidad, 
    # DICIONARIO PASA VARIABLE CON MODELO Y EL LINK PARA REVERSE 
    {'model':Tornillos, 'reverselink':'inventario:tornillos-list'}, 
    name='t-incremento' 
),
path('nuevos-articulos/herramientas-de-corte/categoria-tornillos/<int:pk>/dec/', 
    views.actualizar_cantidad, 
    # DICIONARIO PASA VARIABLE CON MODELO Y EL LINK PARA REVERSE 
    {'model':Tornillos, 'reverselink':'inventario:tornillos-list'}, 
    name='t-decremento'
),

2 个答案:

答案 0 :(得分:0)

由于此行(total的第44行),每个项目的所有对象都将使用相同的actualizar_cantidad更新:

qs_total.update(total=s_total)

您定义了qs_total = model.objects.values('total'),这意味着类model的每个对象,因此,当您调用update时,您将更新所有这些对象。

要解决此问题,请使用filter重新定义qs_total使其仅是您要更新的一个或多个对象,或者删除此行。

答案 1 :(得分:0)

关于您的问题qs_total.update(total=s_total)将更新总金额相同的每个对象(具体而言,仅更新一个对象,您必须传递一些唯一值作为id

在这行代码qs_total = model.objects.values('total')上,不要使用关键字“ model”,这是文本形式,因此您的类名以字符串形式dont表示它是该类的实例,您需要先获取它然后运行查询集

建议: 我以前做过类似的事情,希望对您有所帮助,或者也许您可以在主代码上进行一些改进

'''
    In this version accepts only integer or decimal fields
    Parameters:
    1 - Queryset
    2 - Column Name(String)
    3 - Filter(String):
            - Less Than Equal - "-<valor>" | Example: "-250"
            - Between - "<valor>~<valor>" | Example: "250~350"
            - Greater Than Equal - "+<valor>" | Example: "+15"            
    '''

    def dinamic_filter(queryset, column, filter):
        if '-' in filter:
                filter = filter.replace('-','')
                queryset = queryset.filter(**{'{column}__lte'.format(column=column):int(filter)})
        elif '~' in filter:
            values = filter.split('~')
            if values[0] and values[1]:
                less = valores[0]
                greater = valores[1]
                queryset = queryset.filter(**{'{column}__range'.format(column=column):(less, greater)})
            else:
                raise ValidationError('Wrong Value {filter} of column {column}'.format(filter=filter, column=column))
        elif '+' in filtro:
            filter = filter.replace('+','')
            queryset = queryset.filter(**{'{column}__gte'.format(column=column):int(filter)})

        return queryset

来源:https://github.com/Diegow3b/django-dinamic-queryset-filter