Last active
June 30, 2018 04:13
-
-
Save MilanRgm/02b71d10da642788c06b088032446904 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pdb | |
import datetime | |
from carts.models import Cart, CartItem | |
from products.models import Variation | |
CART_ID = 'cart-id' | |
class Cart(object): | |
def __init__(self, request): | |
""" | |
Initialize the cart | |
""" | |
self.session = request.session | |
# get the current session from request.session.get(CART_ID) | |
cart = self.session.get(CART_ID) | |
if not cart: # cart is not present in the session | |
# save an empty cart in the session | |
# but we expect our cart dictionary to use product ids as keys | |
# and a dictionary with quantity and price as value for each key | |
# by that we can gurantee same product is not added twice | |
cart = self.session[CART_ID] = {} | |
else: | |
try: | |
cart = CartItem.objects.get(id=cart) | |
except CartItem.DoesNotExist: | |
cart = self.session[CART_ID] = {} | |
self.cart = cart | |
def __iter__(self): | |
""" | |
Iterate over the items in the cart and get the products from the database | |
""" | |
product_ids = self.cart.keys() | |
# get the product objects and add them to the cart | |
products = Variation.objects.filter(id__in=product_ids) | |
for product in products: | |
self.cart[str(product.id)]['product'] = product | |
for item in self.cart.values(): | |
item['price'] = Decimal(item['price']) | |
item['total_price'] = item['price'] * item['quantity'] | |
yield item | |
def __len__(self): | |
""" | |
Count all the items in the cart | |
""" | |
return sum(item['quantity'] for item in self.cart.values()) | |
def get_total_price(self): | |
return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values()) | |
def clear(self): | |
# empty cart | |
self.session[CART_ID] = {} | |
self.session.modified = True | |
def new(self, request): | |
cart = Cart(timestamp=datetime.datetime.now()) | |
cart.save() | |
request.session[CART_ID] = cart.id | |
return cart | |
def add(self, product, quantity=1, update_quantity=False): | |
""" | |
Add a product to the cart or update its quantity for True | |
or the new quantity needs to be added to the existing quantity | |
if it is False. We use the product id as a key and convert it to string | |
because django uses JSON to serialize session data. | |
""" | |
product_id = str(product.id) | |
try: | |
product = Variation.objects.get(id=product.id) | |
except Variation.DoesNotExist: | |
raise ValidationError("Variation does not exist") | |
if product_id not in self.cart: | |
# cart_item = CartItem.objects.create() | |
self.cart[product_id] = { | |
'quantity': 0, | |
'price': str(product.price) | |
} | |
if update_quantity: | |
cart_item = CartItem.objects.create( | |
cart=self.cart, | |
items=product, | |
quantity=quantity) | |
self.cart[product_id]['quantity'] = quantity | |
else: | |
cart_item = CartItem.objects.get(cart=self.cart) | |
cart_item.quantity += quantity | |
self.cart[product_id]['quantity'] += quantity | |
self.save() | |
def save(self): | |
# update the session cart | |
self.session[CART_ID] = self.cart | |
# mark the session as modified to make sure it is saved | |
self.session.modified = True | |
def remove(self, product): | |
""" | |
Remove a product from the cart | |
""" | |
product_id = str(product.id) | |
if product_id in self.cart: | |
del self.cart[product_id] | |
self.save() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Cart(models.Model): | |
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.CASCADE) | |
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False) | |
updated = models.DateTimeField(auto_now_add=False, auto_now=True) | |
subtotal = models.DecimalField(max_digits=50, decimal_places=2, default=0.00) | |
class CartItem(models.Model): | |
cart = models.ForeignKey(Cart, on_delete=models.CASCADE) | |
item = models.ForeignKey(Variation, on_delete=models.CASCADE) | |
quantity = models.PositiveIntegerField(default=1) | |
line_item_total = models.DecimalField(max_digits=10, decimal_places=2) | |
class CartSerializer(serializers.ModelSerializer): | |
item = VariationSerializer(many=True, read_only=True) | |
class Meta: | |
model = Cart | |
fields = ('item', 'user', 'timestamp', 'updated', 'subtotal', 'total', 'active',) | |
class CartItemSerializer(serializers.ModelSerializer): | |
class Meta: | |
model = CartItem | |
fields = '__all__' | |
class CartAPI(APIView): | |
serializer_class = serializers.CartItemSerializer | |
def get(self, request, format=None): | |
reply = {} | |
try: | |
carts = CartItem.objects.all() | |
reply['data'] = self.serializer_class(carts, many=True).data | |
except CartItem.DoesNotExist: | |
reply['data'] = [] | |
return Response(reply, status.HTTP_200_OK) | |
def post(self, request, format=None): | |
''' | |
{ | |
"product": 3, | |
"quantity": 4 | |
} | |
''' | |
reply = {} | |
cart = Cart(request) | |
serializer = self.serializer_class(data=request.data) | |
if serializer.is_valid(): | |
pdb.set_trace() | |
data = serializer.data | |
product_instance = data.get('product') | |
quantity = data.get('quantity') | |
cart_data = cart.add(product_instance, quantity) | |
reply['data'] = cart_data | |
return Response(reply, status.HTTP_200_OK) | |
return Response(serializer.errors) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment