Здравствуйте, я пытаюсь создать приложение для электронной коммерции с помощью Django. У меня есть класс корзины покупок, который работает с сеансом, это мой класс корзины:
from django.conf import settings
from shop.models import Product, ProductColor
from django.shortcuts import get_object_or_404
from django.utils import timezone
class Cart:
def __init__(self, request_or_session_data):
if hasattr(request_or_session_data, 'session'): # Check if it's a request
self.session = request_or_session_data.session
else:
# If it's session data, use it directly
self.session = request_or_session_data
cart = self.session.get(settings.CART_SESSION_ID)
if not cart:
cart = self.session[settings.CART_SESSION_ID] = {}
self.cart = cart
self.total_discount = None
self.discount_code = None
self.have_discount_code = self.session.get("have_discount_code", False)
self.discount_code_amount = self.session.get("discount_code_amount", 0)
self.last_updated = self.session.get("last_updated")
if hasattr(request_or_session_data, 'user') and request_or_session_data.user.is_authenticated:
self.user = request_or_session_data.user
def add(self, product, color_id, quantity=1, override_quantity=False):
product_id = str(product.id)
color = get_object_or_404(ProductColor, id=color_id)
cart_key = f"{product_id}_{color_id}"
if cart_key not in self.cart:
self.cart[cart_key] = {
'color_id': str(color.id),
'quantity': 0,
'price': str(product.price),
'discount': str(product.discount),
'discount_price': str(product.get_discounted_price()),
}
if override_quantity:
self.cart[cart_key]['quantity'] = quantity
else:
self.cart[cart_key]['quantity'] += quantity
self.total_discount = self.get_total_discount()
self.save()
def mark_session_modified(self):
# Mark session as modified if `self.session` is a Django session object
if hasattr(self.session, 'modified'):
self.session.modified = True
def save(self):
# mark the session as "modified" to make sure it gets saved
self.last_updated = timezone.now()
self.session[settings.CART_SESSION_ID] = self.cart
self.session['have_discount_code'] = self.have_discount_code
self.session['discount_code_amount'] = self.discount_code_amount
self.session['last_updated'] = self.last_updated.isoformat()
if hasattr(self, 'user') and self.user:
self.session["user_id"] = self.user.id
self.mark_session_modified()
def remove(self, product, color_id=None):
product_id = str(product.id)
if color_id:
cart_key = f"{product_id}_{color_id}"
if cart_key in self.cart:
del self.cart[cart_key]
else:
# If no color_id is provided, remove all items related to the product_id
keys_to_remove = [key for key in self.cart if key.startswith(product_id)]
for key in keys_to_remove:
del self.cart[key]
if len(self.cart) == 0:
self.clear() # Call the clear method to remove discount codes and other data
else:
self.total_discount = self.get_total_discount() # Update total discount
self.save()
def __iter__(self):
cart = self.cart.copy()
product_ids = {key.split('_')[0] for key in cart.keys()} # Extract product IDs
products = Product.objects.filter(id__in=product_ids)
for product in products:
for key in cart.keys():
if key.startswith(str(product.id)):
item = cart[key]
item["product"] = product
# Extract color ID from the key
color_id = key.split('_')[1] if '_' in key else None
# Get the corresponding ProductColor instance
if color_id:
try:
product_color = ProductColor.objects.get(id=color_id, product=product)
item["color_name"] = product_color.color # Use the color from ColorChoices
except ProductColor.DoesNotExist:
item["color_name"] = "Unknown Color"
else:
item["color_name"] = "No Color"
item["color_id"] = str(color_id)
item["product_id"] = str(product.id)
item["price"] = int(item["price"])
item["discount_price"] = int(item["discount_price"])
if item["discount"] == "0":
item["total_price"] = item["price"] * item["quantity"]
else:
item["total_price"] = item["discount_price"] * item["quantity"]
yield item
def __len__(self):
return sum(item['quantity'] for item in self.cart.values())
def get_total_price(self):
total_price = 0
for item in self:
total_price += item["total_price"]
if self.have_discount_code:
discount_factor = self.discount_code_amount / 100
total_price = int(total_price * (1 - discount_factor))
return total_price
def add_coupon(self, amount, code):
self.discount_code_amount = amount
self.have_discount_code = True
self.discount_code = code
self.save()
def get_total_discount(self):
total_discount = 0
for item in self.cart.values():
if item["discount"] != "0":
discount = int(item["price"]) - int(item["discount_price"])
total_discount += discount * item["quantity"]
return total_discount
@property
def total_get_price_of_discount(self):
total_price = 0
for item in self:
total_price += item["total_price"]
price = self.get_total_price()
return total_price - price
def clear(self):
# remove cart from session
del self.session[settings.CART_SESSION_ID]
self.have_discount_code = False
self.discount_code = None
self.discount_code_amount = 0
self.total_discount = None
self.save()
каждый раз, когда пользователи добавляют товар в корзину, я уменьшаю количество товаров, и у меня есть задача проверить, простаивает ли их корзина более 30 минут, сначала отправьте пользователю SMS и напомните им о корзине покупок, и через 1 час очистите корзину и добавьте количество обратно в продукты. Проблема заключается в том, что в задаче я пытаюсь зациклиться на всех сеансах и изменить этот сеанс с помощью session_data["sms_sent"] = True после этого он снова отправит смс, а когда пройдет более 1 часа, он добавит количество обратно в базу данных, но не очистит корзину из сеанса
это задача, которую я использую:< /p>
@shared_task
def clear_abandoned_carts():
expired_time = timezone.now() - CART_EXPIRATION_TIME
warning_time = timezone.now() - SEND_WARNING_TIME
for session in Session.objects.filter(expire_date__gte=timezone.now()):
data = session.get_decoded()
last_updated_str = data.get("last_updated")
cart = data.get(settings.CART_SESSION_ID)
print("sms_sent flag before:", data.get("sms_sent")) # Safe access
if cart and last_updated_str:
last_updated = timezone.datetime.fromisoformat(last_updated_str)
if last_updated < expired_time:
# Clear cart if expired
for key, item in cart.items():
color_id = item["color_id"]
quantity = item["quantity"]
try:
remove_from_cart(color_id, int(quantity))
except ProductColor.DoesNotExist:
pass # Handle as needed
# Clear session data
session_data = session.get_decoded()
session_data.pop(settings.CART_SESSION_ID, None)
session_data.pop("last_updated", None)
session_data.pop("have_discount_code", None)
session_data.pop("discount_code_amount", None)
session_data.pop("sms_sent", None)
session_data["modified"] = True
session.save()
cart_instance = Cart(data)
cart_instance.clear()
elif last_updated < warning_time:
# Check if the SMS warning was already sent
if not data.get("sms_sent"): # Proceed only if SMS hasn't been sent
user_id = data.get("user_id")
if user_id:
try:
user = CustomUser.objects.get(id=user_id)
if user.phone_number:
phone_number = user.phone_number
send_cart_warning(int(phone_number)) # Send SMS
# Mark SMS as sent in session data
session_data = session.get_decoded()
session_data["sms_sent"] = True # Safely update session
session_data["modified"] = True
session.modified = True
session.save()
print("sms_sent flag after:", session_data.get("sms_sent")) # Safe access
except CustomUser.DoesNotExist:
pass
в консоли, когда оно отправляет сообщение, это print("sms_sent flag after:", session_data.get("sms_sent")) дает мне True, но когда оно запускается снова, это print(" флаг sms_sent перед:", data.get("sms_sent")) дайте мне Нет, ребята, помогите мне решить эту проблему, пожалуйста
Здравствуйте, я пытаюсь создать приложение для электронной коммерции с помощью Django. У меня есть класс корзины покупок, который работает с сеансом, это мой класс корзины: [code]from django.conf import settings from shop.models import Product, ProductColor from django.shortcuts import get_object_or_404 from django.utils import timezone
class Cart: def __init__(self, request_or_session_data): if hasattr(request_or_session_data, 'session'): # Check if it's a request self.session = request_or_session_data.session else: # If it's session data, use it directly self.session = request_or_session_data cart = self.session.get(settings.CART_SESSION_ID) if not cart: cart = self.session[settings.CART_SESSION_ID] = {} self.cart = cart self.total_discount = None self.discount_code = None self.have_discount_code = self.session.get("have_discount_code", False) self.discount_code_amount = self.session.get("discount_code_amount", 0) self.last_updated = self.session.get("last_updated") if hasattr(request_or_session_data, 'user') and request_or_session_data.user.is_authenticated: self.user = request_or_session_data.user
def mark_session_modified(self): # Mark session as modified if `self.session` is a Django session object if hasattr(self.session, 'modified'): self.session.modified = True
def save(self): # mark the session as "modified" to make sure it gets saved self.last_updated = timezone.now() self.session[settings.CART_SESSION_ID] = self.cart self.session['have_discount_code'] = self.have_discount_code self.session['discount_code_amount'] = self.discount_code_amount self.session['last_updated'] = self.last_updated.isoformat() if hasattr(self, 'user') and self.user: self.session["user_id"] = self.user.id self.mark_session_modified()
def remove(self, product, color_id=None): product_id = str(product.id) if color_id: cart_key = f"{product_id}_{color_id}" if cart_key in self.cart: del self.cart[cart_key] else: # If no color_id is provided, remove all items related to the product_id keys_to_remove = [key for key in self.cart if key.startswith(product_id)] for key in keys_to_remove: del self.cart[key]
if len(self.cart) == 0: self.clear() # Call the clear method to remove discount codes and other data
else: self.total_discount = self.get_total_discount() # Update total discount self.save()
def __iter__(self): cart = self.cart.copy() product_ids = {key.split('_')[0] for key in cart.keys()} # Extract product IDs products = Product.objects.filter(id__in=product_ids)
for product in products: for key in cart.keys(): if key.startswith(str(product.id)): item = cart[key] item["product"] = product
# Extract color ID from the key color_id = key.split('_')[1] if '_' in key else None
# Get the corresponding ProductColor instance if color_id: try: product_color = ProductColor.objects.get(id=color_id, product=product) item["color_name"] = product_color.color # Use the color from ColorChoices except ProductColor.DoesNotExist: item["color_name"] = "Unknown Color" else: item["color_name"] = "No Color"
def get_total_discount(self): total_discount = 0 for item in self.cart.values(): if item["discount"] != "0": discount = int(item["price"]) - int(item["discount_price"]) total_discount += discount * item["quantity"] return total_discount
@property def total_get_price_of_discount(self): total_price = 0 for item in self: total_price += item["total_price"] price = self.get_total_price()
return total_price - price
def clear(self): # remove cart from session del self.session[settings.CART_SESSION_ID] self.have_discount_code = False self.discount_code = None self.discount_code_amount = 0 self.total_discount = None self.save() [/code] каждый раз, когда пользователи добавляют товар в корзину, я уменьшаю количество товаров, и у меня есть задача проверить, простаивает ли их корзина более 30 минут, сначала отправьте пользователю SMS и напомните им о корзине покупок, и через 1 час очистите корзину и добавьте количество обратно в продукты. Проблема заключается в том, что в задаче я пытаюсь зациклиться на всех сеансах и изменить этот сеанс с помощью session_data["sms_sent"] = True после этого он снова отправит смс, а когда пройдет более 1 часа, он добавит количество обратно в базу данных, но не очистит корзину из сеанса это задача, которую я использую:< /p> [code]@shared_task def clear_abandoned_carts(): expired_time = timezone.now() - CART_EXPIRATION_TIME warning_time = timezone.now() - SEND_WARNING_TIME
for session in Session.objects.filter(expire_date__gte=timezone.now()): data = session.get_decoded() last_updated_str = data.get("last_updated") cart = data.get(settings.CART_SESSION_ID) print("sms_sent flag before:", data.get("sms_sent")) # Safe access
if cart and last_updated_str: last_updated = timezone.datetime.fromisoformat(last_updated_str)
if last_updated < expired_time: # Clear cart if expired for key, item in cart.items(): color_id = item["color_id"] quantity = item["quantity"] try: remove_from_cart(color_id, int(quantity)) except ProductColor.DoesNotExist: pass # Handle as needed
elif last_updated < warning_time: # Check if the SMS warning was already sent if not data.get("sms_sent"): # Proceed only if SMS hasn't been sent user_id = data.get("user_id") if user_id: try: user = CustomUser.objects.get(id=user_id) if user.phone_number: phone_number = user.phone_number send_cart_warning(int(phone_number)) # Send SMS
# Mark SMS as sent in session data session_data = session.get_decoded() session_data["sms_sent"] = True # Safely update session session_data["modified"] = True session.modified = True session.save()
print("sms_sent flag after:", session_data.get("sms_sent")) # Safe access
except CustomUser.DoesNotExist: pass [/code] в консоли, когда оно отправляет сообщение, это print("sms_sent flag after:", session_data.get("sms_sent")) дает мне True, но когда оно запускается снова, это print(" флаг sms_sent перед:", data.get("sms_sent")) дайте мне Нет, ребята, помогите мне решить эту проблему, пожалуйста