【发布时间】:2020-04-19 20:40:37
【问题描述】:
我正在使用 Stripe 在我的 Django 应用中处理付款。 每当我尝试填写虚拟卡凭据并提交时,都会出现以下错误。
AttributeError, 'Payment' 对象没有属性 'save'
我不知道如何将付款对象保存在“views.py”中。
我已成功在我的应用中应用迁移并已迁移它,但我仍然收到此错误。
以下是我的观点.py
from django.conf import settings
from django.shortcuts import render, get_object_or_404
from django.views.generic import ListView, DetailView, View
from django.utils import timezone
from django.shortcuts import redirect
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import login_required
import stripe
from django.contrib import messages
# token = stripe.api_key
stripe.api_key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
# `source` is obtained with Stripe.js; see https://stripe.com/docs/payments/accept-a-payment-charges#web-create-token
# stripe.api_key = settings.STRIPE_SECRET_KEY
# Create your views here.
from .models import Item, OrderItem, Order, BillingInformation, Payment
from .forms import CheckoutForm
# def home(request):
# context = {
# 'items': Item.objects.all()
# }
# return render(request,'home.html',context)
class HomeView(ListView):
model = Item
template_name = 'home.html'
class ItemDetails(DetailView):
model = Item
template_name = 'product.html'
@login_required
def add_to_cart(request, slug):
item = get_object_or_404(Item, slug=slug)
order_item, created = OrderItem.objects.get_or_create(
order_item=item,
user=request.user,
is_ordered=False
)
order_qs = Order.objects.filter(user=request.user, is_ordered=False)
if order_qs.exists():
order = order_qs[0]
print(order)
if order.order_items.filter(order_item__slug=item.slug).exists():
order_item.item_quantity += 1
order_item.save()
else:
order.order_items.add(order_item)
else:
date_of_order = timezone.now()
order = Order.objects.create(user=request.user,date_of_order= date_of_order)
order.order_items.add(order_item)
return redirect("core:order-summary")
@login_required
def remove_from_cart(request, slug):
item = get_object_or_404(Item,slug=slug)
order_qs = Order.objects.filter(user=request.user, is_ordered=False)
if order_qs.exists():
order = order_qs[0]
if order.order_items.filter(order_item__slug=item.slug).exists():
order_item = OrderItem.objects.filter(
order_item=item,
user=request.user,
is_ordered=False
)[0]
order.order_items.filter(order_item__slug=item.slug).delete()
else:
return redirect("core:product",slug=slug)
else:
return redirect("core:product",slug=slug)
return redirect("core:product",slug=slug)
@login_required
def remove_single_item_from_cart(request, slug):
item = get_object_or_404(Item,slug=slug)
order_qs = Order.objects.filter(user=request.user, is_ordered=False)
if order_qs.exists():
order = order_qs[0]
if order.order_items.filter(order_item__slug=item.slug).exists():
order_item = OrderItem.objects.filter(
order_item=item,
user=request.user,
is_ordered=False
)[0]
if order_item.item_quantity > 1:
order_item.item_quantity -= 1
order_item.save()
else:
order.order_items.filter(order_item__slug=item.slug).delete()
else:
return redirect("core:order-summary")
else:
return redirect("core:order-summary")
return redirect("core:order-summary")
class OrderSummary(LoginRequiredMixin,View):
def get(self, *args, **kwargs):
order = Order.objects.get(user=self.request.user, is_ordered=False)
context = {'object':order}
return render(self.request,'order-summary.html',context)
class CheckoutView(LoginRequiredMixin,View):
def get(self,*args,**kwargs):
form = CheckoutForm
context = {'form':form}
return render(self.request,'checkout.html',context)
def post(self, *args, **kwargs):
form = CheckoutForm(self.request.POST or None)
order = Order.objects.get(user=self.request.user, is_ordered=False)
if form.is_valid():
street = form.cleaned_data.get('street')
city = form.cleaned_data.get('city')
state = form.cleaned_data.get('state')
landmark = form.cleaned_data.get('landmark')
shipping_same_as_billing = form.cleaned_data.get('shipping_same_as_billing')
save_info = form.cleaned_data.get('save_info')
payment_info = form.cleaned_data.get('payment_info')
billing_address = BillingInformation(
user = self.request.user,
street = street,
city = city,
state = state,
landmark = landmark,
shipping_same_as_billing = shipping_same_as_billing,
save_info = save_info,
payment_info = payment_info
)
billing_address.save()
order.billing_address = billing_address
order.save()
return redirect('core:order-summary')
class Payment(LoginRequiredMixin, View):
def get(self,*args,**kwargs):
order = Order.objects.get(user=self.request.user, is_ordered=False)
context = {
'order':order
}
return render(self.request,'payment.html',context)
def post(self,*args,**kwargs):
order = Order.objects.get(user=self.request.user,is_ordered=False)
# token = self.request.POST.get('stripeToken')
order_amount = int(order.get_cart_total())
try:
charge = stripe.Charge.create(
amount=order_amount,
currency="inr",
source = self.request.POST.get('stripeToken')
)
payment = Payment()
payment.stripe_charge_id = charge['id']
payment.amount = order_amount
payment.user = self.request.user
payment.save()
order.is_ordered = True
order.payment = payment
order.save()
messages.success(self.request,"YaYY!! Your order has been successfully placed")
return render(self.request,'order_placed.html')
except stripe.error.CardError as e:
# Problem with the card
messages.error(self.request,"Card error")
return redirect("/")
# pass
except stripe.error.RateLimitError as e:
# Too many requests made to the API too quickly
messages.error(self.request,"Rate limit error")
# pass
return redirect("/")
except stripe.error.InvalidRequestError as e:
print(e)
# Invalid parameters were supplied to Stripe API
# pass
messages.error(self.request,"Invalid request error")
return redirect("/")
except stripe.error.AuthenticationError as e:
# Authentication Error: Authentication with Stripe API failed (maybe you changed API keys recently)
# pass
messages.error(self.request,"Authentication error")
return redirect("/")
except stripe.error.APIConnectionError as e:
# Network communication with Stripe failed
# pass
messages.error(self.request,"API connection error")
return redirect("/")
except stripe.error.StripeError as e:
# Stripe Error
# pass
messages.error(self.request,"Stripe error")
return redirect("/")
以下是我的models.py
from django.db import models
from django.conf import settings
from django.shortcuts import reverse
# Create your models here.
CATEGORY_CHOICES = (
('S','Shirt'),
('SW','Sports Wear'),
('OW','Out Wear'),
)
LABEL_CHOICES = (
('P','primary'),
('S','success'),
('D','danger'),
)
PAYMENT_METHOD = (
('S','Stripe'),
('P',"PayPal"),
)
class Item(models.Model):
item_name = models.CharField(max_length=200)
item_price = models.FloatField()
item_discounted_price = models.FloatField(null=True,blank=True)
item_description = models.TextField()
item_category = models.CharField(choices=CATEGORY_CHOICES, default='S', max_length=2)
item_label = models.CharField(choices=LABEL_CHOICES, default='P', max_length=1)
item_discount = models.PositiveIntegerField(null=True,blank=True)
item_image = models.CharField(max_length=500,default='http://leeford.in/wp-content/uploads/2017/09/image-not-found.jpg')
slug = models.SlugField(default='test-product')
class Meta:
db_table = 'Item'
def __str__(self):
return self.item_name
def get_absolute_url(self):
return reverse('core:product', kwargs={
'slug':self.slug
})
def get_add_to_cart_url(self):
return reverse('core:add-to-cart', kwargs={
'slug':self.slug
})
def get_remove_from_cart_url(self):
return reverse('core:remove-from-cart', kwargs={
'slug':self.slug
})
def get_item_price(self):
if self.item_discounted_price:
return self.item_discounted_price
else:
return self.item_price
class OrderItem(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete = models.CASCADE, blank=True, null=True)
order_item = models.ForeignKey(Item, on_delete = models.CASCADE)
item_quantity = models.PositiveIntegerField(default=1)
is_ordered = models.BooleanField(default=False)
class Meta:
db_table = 'Order Item'
def __str__(self):
return str(self.item_quantity) + " " + self.order_item.item_name
def get_total_item_price(self):
return self.item_quantity * self.order_item.get_item_price()
def get_total_savings(self):
if self.order_item.item_discounted_price:
return (self.order_item.item_price - self.order_item.item_discounted_price)*self.item_quantity
else:
return 0
class BillingInformation(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete = models.CASCADE)
street = models.CharField(max_length=300)
city = models.CharField(max_length=50)
pin_code = models.CharField(max_length=6)
state = models.CharField(max_length=100)
landmark = models.CharField(max_length=500)
shipping_same_as_billing = models.BooleanField(default=False)
save_info = models.BooleanField(default=False)
payment_info = models.CharField(choices=PAYMENT_METHOD,max_length=1)
def __str__(self):
return self.street+ " " + self.city+ " " + self.state
class Payment(models.Model):
stripe_charge_id = models.CharField(max_length=50)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL,blank=True, null=True)
amount = models.FloatField(default=0)
time_stamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user.username
class Order(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete = models.CASCADE)
order_items = models.ManyToManyField(OrderItem)
date_of_order = models.DateTimeField()
is_ordered = models.BooleanField(default=False)
billing_address = models.ForeignKey(BillingInformation,on_delete=models.PROTECT,blank=True,null=True)
payment = models.ForeignKey(Payment,on_delete=models.SET_NULL,null=True)
class Meta:
db_table = 'Order'
def __str__(self):
return self.user.username
def get_cart_total(self):
price = 0
for i in self.order_items.all():
price += i.get_total_item_price()
return price
以下是错误
AttributeError at /payment/stripe/ 'Payment' object has no attribute 'save'
Request Method: POST Request
URL: http://localhost:8000/payment/stripe/
Django Version: 2.2.4
Exception Type: AttributeError Exception Value: 'Payment' object has no attribute 'save'
Exception Location: C:\Users\hrshk\Desktop\ecomm\core\views.py in post, line 178
【问题讨论】:
-
您的视图
class Payment(LoginRequiredMixin, View):和模型名称相同,请尝试将您的视图名称更改为class PaymentView(LoginRequiredMixin, View): -
@NalinDobhal:如果您可以将您的评论变成答案,那么 Harsh Kushwah 可以批准它并关闭此问题。
标签: python django django-models django-views django-orm