电子商务中没有反向匹配

No Reverse Match in Ecommerce

当转到 url "http://localhost:8000/compras/finalizando/" 时,引发以下错误:

“'pagseguro_view' 的反转,未找到参数“('',)'。尝试了 1 个模式:['compras/finalizando/(?P[0-9]+)/pagseguro/\Z']”

我不明白是什么导致了这个错误,有人可以帮忙吗?

我的checkout/urls.py:

     from django.urls import path
        
        from .import views
        
        urlpatterns = [
            path('carrinho/adicionar/<slug>', views.create_cartitem,name='create_cartitem'),
            path('carrinho/', views.cart_item, name='cart_item'),
            path('finalizando/', views.checkout, name='checkout'),

            path('finalizando/<int:pk>/pagseguro/', views.pagseguro_view,   name='pagseguro_view'),

            path('meus-pedidos/', views.order_list, name='order_list'),
            path('meus-pedidos/<int:pk>/', views.order_detail, name='order_detail'),
        ]

我的checkout/views.py:

from pagseguro import PagSeguro
from django.shortcuts import get_object_or_404, redirect
from django.views.generic import (
    RedirectView, TemplateView, ListView, DetailView
    )
from django.forms import modelformset_factory
from django.contrib import messages
from django.urls import reverse_lazy, reverse
from django.contrib.auth.mixins import LoginRequiredMixin

from catalog.models import Product

from .models import CartItem, Order


class CreateCartItemView(RedirectView):

    def get_redirect_url(self, *args, **kwargs):
        product = get_object_or_404(Product, slug=self.kwargs['slug'])
        if self.request.session.session_key is None:
            self.request.session.save()
        cart_item, created = CartItem.objects.add_item(
            self.request.session.session_key, product
        )
        if created:
            messages.success(self.request, 'Produto adicionado com sucesso')
        else:
            messages.success(self.request, 'Produto atualizado com sucesso')
        return reverse_lazy('checkout:cart_item')

class CartItemView(TemplateView):

    template_name = 'checkout/cart.html'

    def get_formset(self, clear=False):
        CartItemFormSet = modelformset_factory(
            CartItem, fields=('quantity',), can_delete=True, extra=0
        )
        session_key = self.request.session.session_key
        if session_key:
            if clear:
                formset = CartItemFormSet(
                    queryset=CartItem.objects.filter(cart_key=session_key)
                )
            else:
                formset = CartItemFormSet(
                    queryset=CartItem.objects.filter(cart_key=session_key),
                    data=self.request.POST or None
                )
        else:
            formset = CartItemFormSet(queryset=CartItem.objects.none())
        return formset

    def get_context_data(self, **kwargs):
        context = super(CartItemView, self).get_context_data(**kwargs)
        context['formset'] = self.get_formset()
        return context

    def post(self, request, *args, **kwargs):
        formset = self.get_formset()
        context = self.get_context_data(**kwargs)
        if formset.is_valid():
            formset.save()
            messages.success(request, 'Carrinho atualizado com sucesso')
            context['formset'] = self.get_formset(clear=True)
        return self.render_to_response(context)

class CheckoutView(LoginRequiredMixin, TemplateView):

    template_name = 'checkout/checkout.html'

    def get(self, request, *args, **kwargs):
        session_key = request.session.session_key
        if session_key and CartItem.objects.filter(cart_key=session_key).exists():
            cart_items = CartItem.objects.filter(cart_key=session_key)
            order = Order.objects.create_order(
                user=request.user, cart_items=cart_items
            )
        else:
            messages.info(request, 'Não há itens no carrinho de compras')
            return redirect('checkout:cart_item')
        return super(CheckoutView, self).get(request, *args, **kwargs)


class OrderListView(LoginRequiredMixin, ListView):

    template_name = 'checkout/order_list.html'
    paginate_by = 10

    def get_queryset(self):
        return Order.objects.filter(user=self.request.user)

class OrderDetailView(LoginRequiredMixin, DetailView):

    template_name = 'checkout/order_detail.html'

    def get_queryset(self):
        return Order.objects.filter(user=self.request.user)

class PagSeguroView(LoginRequiredMixin, RedirectView):

    def get_redirect_url(self, *args, **kwargs):
        order_pk = self.kwargs['pk']
        order = get_object_or_404(
            Order.objects.filter(user=self.request.user), pk=order_pk
        )
        pg = order.pagseguro()
        pg.redirect_url = self.request.build_absolute_uri(
            reverse('checkout:order_detail', kwargs={'pk':order.pk})
        )
        #pg.notification_url = self.request.build_absolute_uri(
        #    reverse('checkout:pagseguro_notification')
        #)
        response = pg.checkout()
        return response.payment_url


create_cartitem = CreateCartItemView.as_view()
cart_item = CartItemView.as_view()
checkout = CheckoutView.as_view()
order_list = OrderListView.as_view()
order_detail = OrderDetailView.as_view()
pagseguro_view = PagSeguroView.as_view()

我的checkout/models.py:

from pagseguro import PagSeguro

from django.db import models
from django.conf import settings
from catalog.models import Product
from django.db.models import F



class CartItemManager(models.Manager):

    def add_item(self, cart_key, product):
        if self.filter(cart_key=cart_key, product=product).exists():
            created = False
            cart_item = self.get(cart_key=cart_key, product=product)
            cart_item.quantity = cart_item.quantity + 1
            cart_item.save()
        else:
            created = True
            cart_item = CartItem.objects.create(
                cart_key=cart_key, product=product, price=product.price
            )
        return cart_item, created


class CartItem(models.Model):

    cart_key = models.CharField(
        'Chave do Carrinho', max_length=40, db_index=True
    )
    product = models.ForeignKey('catalog.Product',on_delete=models.DO_NOTHING, verbose_name='Produto')
    quantity = models.PositiveIntegerField('Quantidade', default=1)
    price = models.DecimalField('Preço', decimal_places=2, max_digits=8)

    objects = CartItemManager()

    class Meta:
        verbose_name = 'Item do Carrinho'
        verbose_name_plural = 'Itens dos Carrinhos'
        unique_together = (('cart_key', 'product'),)

    def __str__(self):
        return '{} [{}]'.format(self.product, self.quantity)

class OrderManager(models.Manager):

    def create_order(self, user, cart_items):
        order = self.create(user=user)
        for cart_item in cart_items:
            order_item = OrderItem.objects.create(
                order=order, quantity=cart_item.quantity, product=cart_item.product,
                price=cart_item.price
            )
        return order

class Order(models.Model):

    STATUS_CHOICES = (
        (0, 'Aguardando Pagamento'),
        (1, 'Concluída'),
        (2, 'Preparando'),
        (3, 'Enviado'),
        (4, 'Finalizado'),
        (5, 'Cancelada'),
    )

    PAYMENT_OPTION_CHOICES = (
        ('pix', 'Pix'),
        ('pagseguro', 'PagSeguro'),
        ('paypal', 'Paypal'),
    )

    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name='Usuário')
    status = models.IntegerField(
        'Situação', choices=STATUS_CHOICES, default=0, blank=True
    )
    payment_option = models.CharField(
        'Opção de Pagamento', choices=PAYMENT_OPTION_CHOICES, max_length=20,
        default='deposit'
    )

    created = models.DateTimeField('Criado em', auto_now_add=True)
    modified = models.DateTimeField('Modificado em', auto_now=True)

    objects = OrderManager()

    class Meta:
        verbose_name = 'Pedido'
        verbose_name_plural = 'Pedidos'

    def __str__(self):
        return 'Pedido #{}'.format(self.pk)

    def products(self):
        products_ids = self.items.values_list('product')
        return Product.objects.filter(pk__in=products_ids)

    def total(self):
        aggregate_queryset = self.items.aggregate(
            total=models.Sum(
                models.F('price') * models.F('quantity'),
                output_field=models.DecimalField()
            )
        )
        return aggregate_queryset['total']

    def pagseguro_update_status(self, status):
        if status == '3':
            self.status = 1
        elif status == '7':
            self.status = 2
        self.save()

    def complete(self):
        self.status = 1
        self.save()

    def pagseguro(self):
        self.payment_option = 'pagseguro'
        self.save()
        pg = PagSeguro(
            email=settings.PAGSEGURO_EMAIL, token=settings.PAGSEGURO_TOKEN,
            config={'sandbox': settings.PAGSEGURO_SANDBOX}
        )
        pg.sender = {
            'email': self.user.email
        }
        pg.reference_prefix = ''
        pg.shipping = None
        pg.reference = self.pk
        for item in self.items.all():
            pg.items.append(
                {
                    'id': item.product.pk,
                    'description': item.product.name,
                    'quantity': item.quantity,
                    'amount': '%.2f' % item.price
                }
            )
        return pg
        
class OrderItem(models.Model):

    order = models.ForeignKey(Order, on_delete=models.CASCADE, verbose_name='Pedido', related_name='items')
    product = models.ForeignKey('catalog.Product', on_delete=models.DO_NOTHING, verbose_name='Produto')
    quantity = models.PositiveIntegerField('Quantidade', default=1)
    price = models.DecimalField('Preço', decimal_places=2, max_digits=8)

    class Meta:
        verbose_name = 'Item do pedido'
        verbose_name_plural = 'Itens dos pedidos'

    def __str__(self):
        return '[{}] {}'.format(self.order, self.product)


def post_save_cart_item(instance, **kwargs): # this function will be called when model CartItem be saved
    if instance.quantity < 1:
        instance.delete()


models.signals.post_save.connect(
    post_save_cart_item, sender=CartItem, dispatch_uid='post_save_cart_item'
)

我的checkout/templates/checkout/checkout.html:

{% extends "base.html" %}
{% load static %}

{% block title %}
Finalização da Compra
{% endblock %}

{% block content %}
<ol class="breadcrumb">
  <li><a href="{% url 'index' %}">Início</a></li>
  <li><a href="{% url 'checkout:cart_item' %}">Carrinho de Compras</a></li>
  <li class="active">Finalização da Compra</li>
</ol>
<div class="page-header">
    <h1>Escolha forma de pagamento</h1>
</div>
<div class="row">
    <div class="col-md-12">
        <p>
            Pedido #{{ order.pk }}
        </p>
    </div>
    <div class="col-md-2 col-md-offset-1">
        <a href="{% url 'checkout:pagseguro_view' order.pk %}" class="btn btn-success">
            <img style="height:100px; width: 100px;" src="{% static 'images/pagseguro.png' %}">
            >Pagar com Pagseguro
        </a>
    </div>
    <div class="col-md-2 col-md-offset-1">
        <a href="#" class="btn btn-success">
            <img style="height:100px; width: 100px;" src="{% static 'images/paypal.png' %}">
            >Pagar com Pagseguro
        </a>
    </div>
    <div class="col-md-2 col-md-offset-1">
        <a href="#" class="btn btn-success">
            <img style="height:100px; width: 100px;" src="{% static 'images/pix.png' %}">
            >Pagar com Pagseguro
        </a>
    </div>
</div>
{% endblock %}

不知道怎么回事,我觉得可能是id有问题

你能尝试在 checkout/templates/checkout/checkout 中更改此行吗?html:

href="{% url 'checkout:pagseguro_view' **order.pk** %}" class="btn btn-success"

href="{% url 'checkout:pagseguro_view' **pk=order.pk** %}" class="btn btn-success"

并尝试是否有错误更改。

urls.py改变你的路线,让pk结束。

path("finalizando/pagseguro/<int:pk>",views.pagseguro_view,name='pagseguro_view')

如果这不起作用,则意味着 pk 是空的。

由于 CheckoutView 是一个模板视图,您需要使用 get_context_dataorder 作为上下文变量发送。就像您在 CartItemView 中提到的表单集一样。

django-doc

您正在使用 checkout/templates/checkout/checkout.html 中的订单,但那里不可用。