I have a django e-commerce application where people can place an order on any product of their choice and as well checkout their cart. I am at the point of checkout where a user selects his shipping address.
I have a shipping app to handle the shipping address and I have an order app to handle the order and checkout. After implementing my codes
I could not checkout a user who was supposed to be redirected to his PayPal account(for now) and after creating shipping address for different users in the admin
- I also noticed that on the checkout page, it loads every shipping address instead of the customer's address (with the user logged in of course).
- I also noticed that when a user selects 'create new address radio button', it does not bring an address page for the user to create another shipping address. My code is written below
shipping models.py
class AbstractAddress(models.Model): MR, MISS, MRS, MS, DR = ('Mr', 'Miss', 'Mrs', 'Ms', 'Dr') TITLE_CHOICES = ( (MR, _("Mr")), (MISS, _("Miss")), (MRS, _("Mrs")), (MS, _("Ms")), (DR, _("Dr")), ) title = models.CharField( pgettext_lazy(u"Treatment Pronouns for the customer", u"Title"), max_length=64, choices=TITLE_CHOICES, blank=True) first_name = models.CharField(_("First name"), max_length=255, blank=True) last_name = models.CharField(_("Last name"), max_length=255, blank=True) line1 = models.CharField(_("First line of address"), max_length=255) line2 = models.CharField( _("Second line of address"), max_length=255, blank=True) line3 = models.CharField( _("Third line of address"), max_length=255, blank=True) line4 = models.CharField(_("City"), max_length=255, blank=True) LGA = models.CharField(max_length=50) state = models.CharField(_("State"), max_length=255, blank=True) def __str__(self): return self.summary class Meta: abstract = False verbose_name = _('Address') verbose_name_plural = _('Addresses') class AbstractShippingAddress(AbstractAddress): phone_number = PhoneNumberField( _("Phone number"), blank=True, help_text=_(“handle phone call”)) class Meta: abstract = False app_label = 'orders' verbose_name = _("Shipping address") verbose_name_plural = _("Shipping addresses") class AbstractUserAddress(AbstractShippingAddress): user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='addresses', verbose_name=_("User")) #: Whether this address is the default for shipping is_default_for_shipping = models.BooleanField( _("Default shipping address?"), default=False) #: Whether this address should be the default for billing. is_default_for_billing = models.BooleanField( _("Default billing address?"), default=False) hash = models.CharField(_("Address Hash"), max_length=255, db_index=True, editable=False) date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
shipping forms.py
class AbstractAddressForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(AbstractAddressForm, self).__init__(*args, **kwargs) field_names = (set(self.fields) & set(settings.REQUIRED_ADDRESS_FIELDS)) for field_name in field_names: self.fields[field_name].required = True class UserAddressForm(PhoneNumberMixin, AbstractAddressForm): class Meta: model = AbstractUserAddress fields = [ 'title', 'first_name', 'last_name', 'line1', 'line2', 'line3', 'line4', 'state', 'LGA', 'phone_number', ] def __init__(self, user, *args, **kwargs): super(UserAddressForm, self).__init__(*args, **kwargs) self.instance.user = user
orders models.py
class Order(models.Model): SUBMITTED = 1 PROCESSED = 2 SHIPPED = 3 CANCELLED = 4 shipping_address = models.ForeignKey( AbstractAddress, null=True, blank=True, verbose_name=_("Shipping Address"), on_delete=models.SET_NULL) user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='user_account') created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) paid = models.BooleanField(default=False) coupon = models.ForeignKey(Coupon, related_name='orders', null=True, blank=True) discount = models.IntegerField(default=0, validators=[MinValueValidator(0), MaxValueValidator(100)]) ORDER_STATUSES = ( (SUBMITTED, 'Submitted'), (PROCESSED, 'Processed'), (SHIPPED, 'Shipped'), (CANCELLED, 'Cancelled'),) status = models.IntegerField(choices=ORDER_STATUSES, default=SUBMITTED) class Meta: ordering = ('-created',) def __str__(self): return 'Order {}'.format(self.id) def get_total_cost(self): total_cost = sum(item.get_cost() for item in self.items.all()) return total_cost - total_cost * (self.discount / Decimal('100')) class OrderItem(models.Model): order = models.ForeignKey(Order, related_name='items') product = models.ForeignKey(Product, related_name='order_items') price = models.DecimalField(max_digits=10, decimal_places=2) quantity = models.PositiveIntegerField(default=1) def __str__(self): return '{}'.format(self.id) def get_cost(self): return self.price * self.quantity
orders form.py
class OrderCreateForm(forms.ModelForm): SAME_SHIPPING, NEW_ADDRESS = 'same', 'new' CHOICES = ( (SAME_SHIPPING, 'Use shipping address'), (NEW_ADDRESS, 'Enter a new address'), ) same_shipping = forms.ChoiceField( widget=forms.RadioSelect, choices=CHOICES, initial=SAME_SHIPPING) class Meta(forms.ModelForm): model = Order exclude = ('paid', 'coupon', 'discount', 'status',) def __init__(self, shipping_address, data=None, *args, **kwargs): self.shipping_address = shipping_address super(OrderCreateForm, self).__init__(data, *args, **kwargs) if shipping_address is None: self.fields['same_shipping'].choices = ( (self.NEW_ADDRESS, 'Enter a new address'),) self.fields['same_shipping'].initial = self.NEW_ADDRESS if data and data.get('same_shipping', None) == self.SAME_SHIPPING: for field in self.fields: if field != 'same_shipping': self.fields[field].required = False def _post_clean(self): if self.cleaned_data.get('same_as_shipping') == self.SAME_AS_SHIPPING: return super(ModelForm, self)._post_clean() def save(self, commit=True): if self.cleaned_data.get('same_shipping') == self.SAME_SHIPPING: shipping_addr = ShippingAddress() self.shipping_address.populate_alternative_model(shipping_addr) if commit: shipping_addr.save() return shipping_addr return super(ModelForm, self).save(commit)
orders views.py
def order_create(request): cart = Cart(request) if request.method == 'POST': form = OrderCreateForm(request.POST) if form.is_valid(): order = form.save() for item in cart: OrderItem.objects.create( order=order, product=item['product'], price=item['price'], quantity=item['quantity'] ) cart.clear() order_created.delay(order.id) # set the order in the session request.session['order_id'] = order.id return redirect(reverse('payment:process')) context = { 'order': order, } template = 'order/created.html' return render(request, template, context) else: form = OrderCreateForm(User) context = { 'cart': cart, 'form': form, } template = 'order/create.html' return render(request, template, context)
0 comments:
Post a Comment