Django: 反向 'verify-payment' 没有找到参数 '('',)'。尝试了 1 种模式:['course/u/(?P<ref>[^/]+)/$']
Django: Reverse for 'verify-payment' with arguments '('',)' not found. 1 pattern(s) tried: ['course/u/(?P<ref>[^/]+)/$']
我写了一个视图来验证付款但是当我点击付款按钮时我得到这个错误说 Reverse for 'verify-payment' with arguments '('',)' not found. 1 pattern(s) tried: ['course/u/(?P<ref>[^/]+)/$']
我知道这是一个 url 配置错误,我没有传递正确的参数,但我不知道要传递什么,我已经尝试过 payment.ref
views.py
@login_required
def course_checkout(request, slug):
course = Course.objects.get(slug=slug)
user = request.user
action = request.GET.get('action')
order = None
payment = None
error = None
try:
user_course = UserCourse.objects.get(user=user, course=course)
error = "Congratulations! You are Already Enrolled In This Course"
except:
pass
amount = None
if error is None:
amount = int((course.price - (course.price * course.discount * 0.01)) * 100)
if amount == 0:
userCourse = UserCourse(user=user, course=course)
userCourse.save()
return redirect('course:course-content', course.slug) # change this to redirect to my courses page with a button to start course because this course is free
if action == 'create_payment':
currency = "NGN"
notes = {
"email": user.email,
"name": user.username
}
reciept = f"DexxaEd-{int(time())}"
order = client.order.create(
{
'reciept' : reciept,
'notes' : notes,
'amount' : amount,
'currency' : currency,
'paystack_public_key' : settings.PAYSTACK_PUBLIC_KEY,
}
)
payment = Payment()
payment.user = user
payment.course = course
payment.order_id = order.get('id')
payment.save()
context = {
"course":course,
"order":order,
"payment":payment,
"user":user,
"error":error,
}
return render(request, "course/course-checkout.html", context)
def verify_payment(request: HttpRequest, ref: str) -> HttpResponse:
payment = get_object_or_404(Payment, ref=ref)
verified = payment.verify_payment()
return redirect("userauths:profile")
models.py
class Payment(models.Model):
order_id = models.CharField(max_length = 50 , null = False)
payment_id = models.CharField(max_length = 50)
user_course = models.ForeignKey(UserCourse , null = True , blank = True , on_delete=models.CASCADE)
user = models.ForeignKey(User , on_delete=models.CASCADE)
course = models.ForeignKey(Course , on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)
status = models.BooleanField(default=False)
email = models.EmailField()
ref = models.CharField(max_length=200)
verified = models.BooleanField(default=False)
def __str__(self):
return f"Payment: {self.course.price}"
def save(self ,*args, **kwargs):
while not self.ref:
ref = secrets.token_urlsafe(50)
objects_with_similar_ref = Payment.objects.filter(ref=ref)
if not objects_with_similar_ref:
self.ref = ref
super().save(*args, **kwargs)
def amount_value(self) -> int:
return self.course.price * 100
def verify_payment(self):
paystack = PayStack()
status, result = paystack,verify_payment(self.ref, self.course.price)
if status:
if result['course.price'] / 100 == self.course.price:
# if result['amount'] / 100 == self.course.price:
self.verified = True
self.save()
if self.verified:
return True
return False
urls.py
path('u/<str:ref>/', views.verify_payment, name = 'verify-payment'),
课程-checkout.html
{{ course.price }}
<button id="django-paystack-button" onclick="payWithPayStack()" class="chck-btn22">Make Payment</button>
<script>
function payWithPaystack() {
let currency = "USD";
let plan = "";
let ref = "{{payment.ref}}";
let obj = {
key: "{{ paystack_public_key }}",
email: "{{ request.user.email }}",
amount: "{{course.price_value}}",
ref: ref,
callback: function (response) {
window.location.href = "{% url 'course:verify-payment' payment.ref %}";
},
};
if (Boolean(currency)) {
obj.currency = currency.toUpperCase();
}
if (Boolean(plan)) {
obj.plan = plan;
}
var handler = PaystackPop.setup(obj);
handler.openIframe();
}
</script>
问题不在于您的 url 配置,也不在于 payment.ref,而在于您的 course_checkout 页面中的逻辑。问题是即使付款是 None,用户也可以登陆 course-checkout.html 页面,这就是导致错误的原因,因为 url 期待非空 <str:ref>
。我的期望是,如果这不是您想要的,我深表歉意,用户应该进入 course-checkout 页面的唯一时间是 (1) 用户尚未注册该课程,或 (2)该课程是免费的。否则,应将用户带到 course-checkout 页面(无需检查 if action == 'create_payment':
,因为如果 (1) 或 (2) 为假,这是唯一的其他选项,正如我所见).我没有测试下面的代码,但我认为这可能是实现它的方法:
def course_checkout(request, slug):
course = Course.objects.get(slug=slug)
user = request.user
action = request.GET.get('action')
order = None
payment = None
error = None
try:
user_course = UserCourse.objects.get(user=user, course=course)
except:
pass
# User is already registered for course, so go to the course page
if user_course:
return redirect('course:course-content', course.slug)
amount = int((course.price - (course.price * course.discount * 0.01)) * 100)
# Redirect to my courses page with a button to start course because this course is free
if amount == 0:
userCourse = UserCourse(user=user, course=course)
userCourse.save()
return redirect('course:course-content', course.slug)
# User is not registered for the course, and the amount is NOT 0, so send
# to the checkout page
currency = "NGN"
notes = {
"email": user.email,
"name": user.username
}
reciept = f"DexxaEd-{int(time())}"
order = client.order.create(
{
'reciept' : reciept,
'notes' : notes,
'amount' : amount,
'currency' : currency,
'paystack_public_key' : settings.PAYSTACK_PUBLIC_KEY,
}
)
payment = Payment()
payment.user = user
payment.course = course
payment.order_id = order.get('id')
payment.save()
context = {
"course":course,
"order":order,
"payment":payment,
"user":user,
"error":error,
}
return render(request, "course/course-checkout.html", context)
我写了一个视图来验证付款但是当我点击付款按钮时我得到这个错误说 Reverse for 'verify-payment' with arguments '('',)' not found. 1 pattern(s) tried: ['course/u/(?P<ref>[^/]+)/$']
我知道这是一个 url 配置错误,我没有传递正确的参数,但我不知道要传递什么,我已经尝试过 payment.ref
views.py
@login_required
def course_checkout(request, slug):
course = Course.objects.get(slug=slug)
user = request.user
action = request.GET.get('action')
order = None
payment = None
error = None
try:
user_course = UserCourse.objects.get(user=user, course=course)
error = "Congratulations! You are Already Enrolled In This Course"
except:
pass
amount = None
if error is None:
amount = int((course.price - (course.price * course.discount * 0.01)) * 100)
if amount == 0:
userCourse = UserCourse(user=user, course=course)
userCourse.save()
return redirect('course:course-content', course.slug) # change this to redirect to my courses page with a button to start course because this course is free
if action == 'create_payment':
currency = "NGN"
notes = {
"email": user.email,
"name": user.username
}
reciept = f"DexxaEd-{int(time())}"
order = client.order.create(
{
'reciept' : reciept,
'notes' : notes,
'amount' : amount,
'currency' : currency,
'paystack_public_key' : settings.PAYSTACK_PUBLIC_KEY,
}
)
payment = Payment()
payment.user = user
payment.course = course
payment.order_id = order.get('id')
payment.save()
context = {
"course":course,
"order":order,
"payment":payment,
"user":user,
"error":error,
}
return render(request, "course/course-checkout.html", context)
def verify_payment(request: HttpRequest, ref: str) -> HttpResponse:
payment = get_object_or_404(Payment, ref=ref)
verified = payment.verify_payment()
return redirect("userauths:profile")
models.py
class Payment(models.Model):
order_id = models.CharField(max_length = 50 , null = False)
payment_id = models.CharField(max_length = 50)
user_course = models.ForeignKey(UserCourse , null = True , blank = True , on_delete=models.CASCADE)
user = models.ForeignKey(User , on_delete=models.CASCADE)
course = models.ForeignKey(Course , on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)
status = models.BooleanField(default=False)
email = models.EmailField()
ref = models.CharField(max_length=200)
verified = models.BooleanField(default=False)
def __str__(self):
return f"Payment: {self.course.price}"
def save(self ,*args, **kwargs):
while not self.ref:
ref = secrets.token_urlsafe(50)
objects_with_similar_ref = Payment.objects.filter(ref=ref)
if not objects_with_similar_ref:
self.ref = ref
super().save(*args, **kwargs)
def amount_value(self) -> int:
return self.course.price * 100
def verify_payment(self):
paystack = PayStack()
status, result = paystack,verify_payment(self.ref, self.course.price)
if status:
if result['course.price'] / 100 == self.course.price:
# if result['amount'] / 100 == self.course.price:
self.verified = True
self.save()
if self.verified:
return True
return False
urls.py
path('u/<str:ref>/', views.verify_payment, name = 'verify-payment'),
课程-checkout.html
{{ course.price }}
<button id="django-paystack-button" onclick="payWithPayStack()" class="chck-btn22">Make Payment</button>
<script>
function payWithPaystack() {
let currency = "USD";
let plan = "";
let ref = "{{payment.ref}}";
let obj = {
key: "{{ paystack_public_key }}",
email: "{{ request.user.email }}",
amount: "{{course.price_value}}",
ref: ref,
callback: function (response) {
window.location.href = "{% url 'course:verify-payment' payment.ref %}";
},
};
if (Boolean(currency)) {
obj.currency = currency.toUpperCase();
}
if (Boolean(plan)) {
obj.plan = plan;
}
var handler = PaystackPop.setup(obj);
handler.openIframe();
}
</script>
问题不在于您的 url 配置,也不在于 payment.ref,而在于您的 course_checkout 页面中的逻辑。问题是即使付款是 None,用户也可以登陆 course-checkout.html 页面,这就是导致错误的原因,因为 url 期待非空 <str:ref>
。我的期望是,如果这不是您想要的,我深表歉意,用户应该进入 course-checkout 页面的唯一时间是 (1) 用户尚未注册该课程,或 (2)该课程是免费的。否则,应将用户带到 course-checkout 页面(无需检查 if action == 'create_payment':
,因为如果 (1) 或 (2) 为假,这是唯一的其他选项,正如我所见).我没有测试下面的代码,但我认为这可能是实现它的方法:
def course_checkout(request, slug):
course = Course.objects.get(slug=slug)
user = request.user
action = request.GET.get('action')
order = None
payment = None
error = None
try:
user_course = UserCourse.objects.get(user=user, course=course)
except:
pass
# User is already registered for course, so go to the course page
if user_course:
return redirect('course:course-content', course.slug)
amount = int((course.price - (course.price * course.discount * 0.01)) * 100)
# Redirect to my courses page with a button to start course because this course is free
if amount == 0:
userCourse = UserCourse(user=user, course=course)
userCourse.save()
return redirect('course:course-content', course.slug)
# User is not registered for the course, and the amount is NOT 0, so send
# to the checkout page
currency = "NGN"
notes = {
"email": user.email,
"name": user.username
}
reciept = f"DexxaEd-{int(time())}"
order = client.order.create(
{
'reciept' : reciept,
'notes' : notes,
'amount' : amount,
'currency' : currency,
'paystack_public_key' : settings.PAYSTACK_PUBLIC_KEY,
}
)
payment = Payment()
payment.user = user
payment.course = course
payment.order_id = order.get('id')
payment.save()
context = {
"course":course,
"order":order,
"payment":payment,
"user":user,
"error":error,
}
return render(request, "course/course-checkout.html", context)