在 Django 中获取 AttributeError

Getting AttributeError in Django

我在我的 Django 应用程序中使用 Stripe 处理付款。 每当我尝试填写虚拟卡凭据并提交时,都会出现以下错误。

AttributeError, 'Payment' object has no attribute 'save'

我不知道如何在 'views.py' 中保存付款对象。

我已经成功地在我的应用程序中应用了迁移并且已经迁移了它,但是我仍然收到这个错误。

以下是我的views.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

您在 views.py 中使用付款 class 名称并且此付款 class 在 models.py 中也是相同的。 Django 在获取 Payment 对象时感到困惑。请更改 class 名称以便正常工作。

您的视图和模型同名,这就是名称冲突的原因。

将您的视图更改为 PaymentView(或任何其他名称):

class PaymentView(LoginRequiredMixin, View):
    # rest of the code