Thursday, December 14, 2017

including shipping in django e-commerce application

Leave a Comment

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 Answers

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment