Harish Yadav
Harish Yadav

Reputation: 11

FieldError at /cart/checkout/

Exception Value:

Cannot resolve keyword 'active' into field.

Choices are: billing_profile, billing_profile_id, brand, country, default, exp_month, exp_year, id, last4, stripe_id.

When i click on checkout button it show me that error.i already have a lot of models which are related to each other,i check all of them but i did not got any error so can you please verify them.


billing models.py

from django.conf import settings
from django.db import models
from django.db.models.signals import post_save,pre_save
from accounts.models import GuestEmail
import stripe

User=settings.AUTH_USER_MODEL


STRIP_SECRET_KEY= getattr(settings,"STRIP_SECRET_KEY","sk_test_I2eGCibhrZeFd9N0ipx9ac4I")
#STRIP_PUB_KEY=getattr(settings,"STRIP_PUB_KEY","pk_test_nvw3qh6iGMtKSGHMW5MHVwQD")
stripe.api_key=STRIP_SECRET_KEY

class BillingProfileManager(models.Manager):
    def new_or_get(self,request):
        user=request.user
        guest_email_id=request.session.get('guest_email_id')
        created=False
        obj=None
        if user.is_authenticated:
            obj,created= self.model.objects.get_or_create(
                                    user=user, email=user.email)

        elif guest_email_id is not None:
            guest_email_obj = GuestEmail.objects.get(id=guest_email_id)
            obj, created = self.model.objects.get_or_create(
                                    email=guest_email_obj.email)
        else:
            pass
        return obj,created

class BillingProfile(models.Model):
    user=models.OneToOneField(User,null=True,blank=True,on_delete=models.CASCADE)
    email=models.EmailField()
    active=models.BooleanField(default=True)
    update = models.DateTimeField(auto_now=True)
    timestamp=models.DateTimeField(auto_now_add=True)
    customer_id=models.CharField(max_length=120,null=True,blank=True)

    objects=BillingProfileManager()

    def __str__(self):
        return self.email

    def charge(self,order_obj,card=None):
        return Charge.objects.do(self,order_obj,card)

    def get_cards(self):
        return self.card_set.all()

    @property
    def has_card(self):
        card_qs=self.get_cards()
        return  card_qs.exists()

    @property
    def default_card(self):
        default_cards=self.get_cards().filter(default=True)
        if default_cards.exists():
            return self.default_cards.first()
        return None

def billing_profile_created_receiver(sender,instance,*args,**kwargs):
    if not instance.customer_id and instance.email:
        print("ACTUAL AIL REQUEST SEND")
        customer=stripe.Customer.create(
            email=instance.email
        )
        print (customer)
        instance.customer_id=customer.id

pre_save.connect(billing_profile_created_receiver,sender=BillingProfile)

class CardManager(models.Manager):
    def all(self, *args, **kwargs): # ModelKlass.objects.all() --> ModelKlass.objects.filter(active=True)
       return self.get_queryset().filter(active=True)

    def add_new(self, billing_profile, token):
        if token:
            customer = stripe.Customer.retrieve(billing_profile.customer_id)
            stripe_card_response = customer.sources.create(source=token)
            new_card = self.model(
                    billing_profile=billing_profile,
                    stripe_id = stripe_card_response.id,
                    brand = stripe_card_response.brand,
                    country = stripe_card_response.country,
                    exp_month = stripe_card_response.exp_month,
                    exp_year = stripe_card_response.exp_year,
                    last4 = stripe_card_response.last4
                )
            new_card.save()
            return new_card
        return None

def user_created_receiver(sender,instance,created,*args,**kwargs):
    if created and instance.email:
        BillingProfile.objects.get_or_create(user=instance,email=instance.email)
post_save.connect(user_created_receiver,sender=User)

class ChargeManager(models.Manager):
    def do(self, billing_profile, order_obj, card=None): # Charge.objects.do()
        card_obj = card
        if card_obj is None:
            cards = billing_profile.card_set.filter(default=True) # card_obj.billing_profile
            if cards.exists():
                card_obj = cards.first()
        if card_obj is None:
            return False, "No cards available"
        c = stripe.Charge.create(
              amount = int(order_obj.total * 100), # 39.19 --> 3919
              currency = "usd",
              customer =  billing_profile.customer_id,
              source = card_obj.stripe_id,
              metadata={"order_id":order_obj.order_id},
            )
        new_charge_obj = self.model(
                billing_profile = billing_profile,
                stripe_id = c.id,
                paid = c.paid,
                refunded = c.refunded,
                outcome = c.outcome,
                outcome_type = c.outcome['type'],
                seller_message = c.outcome.get('seller_message'),
                risk_level = c.outcome.get('risk_level'),
        )
        new_charge_obj.save()
        return new_charge_obj.paid, new_charge_obj.seller_message


class Charge(models.Model):
    billing_profile         = models.ForeignKey(BillingProfile,on_delete=models.CASCADE)
    stripe_id               = models.CharField(max_length=120)
    paid                    = models.BooleanField(default=False)
    refunded                = models.BooleanField(default=False)
    outcome                 = models.TextField(null=True, blank=True)
    outcome_type            = models.CharField(max_length=120, null=True, blank=True)
    seller_message          = models.CharField(max_length=120, null=True, blank=True)
    risk_level              = models.CharField(max_length=120, null=True, blank=True)

    objects = ChargeManager()

class Card(models.Model):
    billing_profile=models.ForeignKey(BillingProfile,on_delete=models.CASCADE)
    stripe_id=models.CharField(max_length=120)
    brand=models.CharField(max_length=120,null=True,blank=True)
    country = models.CharField(max_length=12, null=True, blank=True)
    exp_month=models.IntegerField(null=True,blank=True)
    exp_year=models.IntegerField(null=True,blank=True)
    last4=models.CharField(max_length=4,null=True,blank=True)
    default=models.BooleanField(default=True)

    objects = CardManager()

    def __str__(self):
        return "{} {}".format(self.brand, self.last4)

checkout.html

{% extends "base.html" %}
{% block content %}

{% if not billing_profile%}
<div class="row text-center">
<div class="col-12 col-md-6">
    <p class="lead">Login</p>
    {% include 'accounts/snippets/form.html' with form=login_form next_url=request.build_absolute_uri %}
</div>
<div class="col-12 col-md-6">
    Continue as Guest
    {% url "guest_register" as guest_register_url %}
    {% include 'accounts/snippets/form.html' with form=guest_form next_url=request.build_absolute_uri action_url=guest_register_url %}
    </div>
</div>

{% else %}

    {% if not object.shipping_address %}

        <div class="row">
            <div class="col-12">
                <p class="lead">Shipping Address</p>
                <hr/>
            </div>
            <div class="col-6">

                {% url "checkout_address_create" as checkout_address_create %}
                {% include 'addresses/form.html' with form=address_form next_url=request.build_absolute_uri action_url=checkout_address_create address_type='shipping' %}'


            </div>
            <div class="col-6">
                {% url 'checkout_address_reuse' as checkout_address_reuse %}
             {% include 'addresses/prev_addresses.html' with address_qs=address_qs next_url=request.build_absolute_uri address_type='shipping' action_url=checkout_address_reuse %}
            </div>
            </div>
    {% elif not object.billing_address %}

    <div class="row">
        <div class="col-12">
            <p class="lead">Billing Address</p>
            <hr/>
            </div>
    <div class="col-md-6">
        {% url "checkout_address_create" as checkout_address_create %}
        {% include 'addresses/form.html' with form=address_form next_url=request.build_absolute_uri action_url=checkout_address_create address_type='billing' %}
        </div>
            <div class="col-6">
           {% url 'checkout_address_reuse' as checkout_address_reuse %}
            {% include 'addresses/prev_addresses.html' with address_qs=address_qs next_url=request.build_absolute_uri address_type='billing' action_url=checkout_address_reuse %}
            </div>
            </div>

    {% else%}
            {% if not has_card %}
                <!-- enter credit card here -->
                <div class='stripe-payment-form' data-token='{{ publish_key }}' data-next-url='{{ request.build_absolute_uri }}' data-btn-title='Add Payment Method'></div>

            {% else %}
                <h1>Finalize Checkout</h1>
                <p>Cart Item:{% for product in object.cart.products.all %}{{ product}}{% if not forloop.last %},{% endif %},{% endfor %}</p>
                <p>Shipping Address:{{object.shipping_address.get_address}}</p>
                <p>Billing Address:{{object.shipping_address.get_address}}</p>
                <p>Cart Total:{{object.cart.total}}</p>
                <p>Shipping Total:{{object.shipping_total}}</p>
                <p>Order Total:{{object.total}}</p>
                <form class="form" method="POST" action="">{% csrf_token %}
                 <button type="submit btn btn-success">Checkout</button>
                </form>
            {% endif %}
    {% endif %}

{% endif %}

{% endblock %}

Upvotes: 1

Views: 158

Answers (2)

Tms91
Tms91

Reputation: 4194

That is likely to happen because you are trying to filter a queryset by an attribute its model does not have.

The model missing this attribute is the one having the attributes are shown to you by the traceback:

billing_profile, billing_profile_id, brand, country, default, exp_month, exp_year, id, last4, stripe_id.

that is, model Card.

Add something like:

active = models.BooleanField(default=True)

to Card model, then makemigrations, migrate, and it should work.

Upvotes: 0

rtindru
rtindru

Reputation: 5337

The problem appears to be in your CardManager declaration.

class CardManager(models.Manager):
    def all(self, *args, **kwargs):
       return self.get_queryset().filter(active=True)

active is not a field on the Card model, but rather on the BillingProfile FK from the Card model.

Change this to:

class CardManager(models.Manager):
    def all(self, *args, **kwargs):
       return self.get_queryset().filter(billing_profile__active=True)

Upvotes: 1

Related Questions