Estoy aprendiendo a desarrollar un sitio web de comercio electrónico, tengo un modelo de cupón con used y max_value, que se ocupan de la cantidad máxima de cupones disponibles para usar, quiero implementar eso en mis vistas, de modo que si el cupón se canjea más que el max_value(número de cupones), entonces debería mostrar un mensaje de error. Todo lo que he intentado con mi conocimiento limitado está dando como resultado errores.
¿Cómo puedo incrementar el 'usado' en las vistas?
Esto es de una manera mucho más comprensible:
los usuarios (vendedores) pueden crear cupones. el código es el alfanumérico (que debería ser único, necesito intentar resolverlo). El cupón puede ser utilizado por cualquier persona solo una vez. max_value lo establece el usuario que lo crea, y cada vez que alguien usa cupones, el 'usado' debería agregarse automáticamente. supongamos que hay 10 cupones, cada vez que un cliente usa un cupón, el 'usado' debe incrementarse en 1 hasta que alcance max_value. si alcanza max_value, el cupón no debería ser válido. Esto es lo que estoy tratando de lograr.
puntos de vista
class AddCouponView(View, LoginRequiredMixin): def post(self, *args, **kwargs): now = timezone.now() form = CouponForm(self.request.POST or None) if form.is_valid(): try: code = form.cleaned_data.get('code') order = Order.objects.get(user=self.request.user, complete=False) coupon_qs = Coupon.objects.filter(code__iexact=code, valid_from__lte=now, valid_to__gte=now) order_coupon = Order.objects.filter(coupon=coupon_qs.first(), user=self.request.user) if order_coupon: messages.error(self.request, 'You can\'t use same coupon again') return redirect('store:checkout') if coupon_qs: order.coupon = coupon_qs[0] order.save() messages.success(self.request, "Successfully added coupon") return redirect('store:checkout') else: messages.success(self.request, "Coupon Does not Exists") return redirect('store:checkout') except ObjectDoesNotExist: messages.info(self.request, "You do not have an active order") return redirect('store:checkout')modelo
class Coupon(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True) code = models.CharField(max_length=15) amount = models.FloatField() valid_from = models.DateTimeField(null=True) valid_to = models.DateTimeField(null=True) max_value = models.IntegerField(validators=[MaxValueValidator(100)], verbose_name='Coupon Quantity', null=True) # No. of coupon used = models.IntegerField(default=0)Gracias
Si entendí bien, tal vez puedas probar así:
from django.db.models import F ... if form.is_valid(): code = form.cleaned_data.get('code') order = Order.objects.get(user=self.request.user, complete=False) coupon = Coupon.objects.filter(code__iexact=code, valid_from__lte=now, valid_to__gte=now).exclude(order__user=self.request.user,max_value__lte=F('used')).first() if not coupon: messages.error(self.request, 'You can\'t use same coupon again, or coupon does not exist') return redirect('store:checkout') else: try: coupon.used += 1 coupon.save() order.coupon = coupon order.save() messages.success(self.request, "Successfully added coupon") except: messages.error(self.request, "Max level exceeded for coupon") return redirect('store:checkout') Explicación: Estoy consultando si un cupón es válido y tiene el código exacto. Excluyo cualquier cupón que ya haya sido utilizado por el usuario utilizando una relación inversa entre el Pedido y el Cupón. Si tiene algún nombre relacionado definido en el modelo de Order , la consulta inversa será exclude(<related_name>__user=self.request.user) . También estoy excluyendo cualquier cupón que tenga un valor de used igual a max_value . Luego, tomo el primer valor del conjunto de consultas y lo uso en el objeto Order . Finalmente, estoy agregando +1 al atributo used de Coupon .
Puede agregar una constraint en el modelo para que no exceda max_value :
from django.db.models import Q, F class Coupon(models.Model): ... class Meta: constraints = [ models.CheckConstraint(check=Q(used__lte=F('max_value')), name="constrain-max-limit") ]