Django实现无需入库存储的商品实时动态价格计算方案咨询
第一步:配置Django缓存(必做,避免重复爬取)
先在项目settings.py中添加缓存配置,小站点用默认本地内存缓存即可,用来存每日原材料价格,一天只爬一次:
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 'LOCATION': 'daily-price-cache', } }
第二步:优化原材料价格爬取函数
把爬取函数放到models.py顶部,加缓存逻辑、异常处理和类型转换,避免和模型Decimal字段计算出现精度问题:
from django.core.cache import cache from decimal import Decimal import requests from bs4 import BeautifulSoup def get_prixmatiere(): # 先读缓存,缓存有效期24小时=86400秒 cache_key = "daily_raw_material_price" cached_price = cache.get(cache_key) if cached_price: return cached_price # 缓存不存在才发起爬取 try: response = requests.get("https://www.exampl.com", timeout=10) response.raise_for_status() soup = BeautifulSoup(response.text, 'lxml') product_price = soup.find_all("td",{"class" : "price"})[0].text.replace('€', '').replace(' ', '') prixmatiere = float(product_price) / 4 * 3 / 1000 * 210 # 转成Decimal和模型字段类型匹配,保留两位小数 prixmatiere = Decimal(str(prixmatiere)).quantize(Decimal('0.00')) cache.set(cache_key, prixmatiere, 86400) return prixmatiere except: # 爬取失败返回默认值,可根据业务需求调整 fallback 逻辑 return Decimal('0.00')
第三步:给Product模型加动态价格属性
把计算方法放到Product类内部,加@property装饰器,前端可以直接调用属性获取价格,原有模型字段完全不用改:
class Product(models.Model): # 原有字段保持不变 prdct_name = models.CharField(max_length=17, verbose_name=_("Article ")) prdct_category = models.ForeignKey("Category", on_delete=models.CASCADE, blank=True, null=True) prdct_description = models.TextField(verbose_name=_("Description")) prdct_img = models.ImageField(upload_to='product/',verbose_name=_("Image"), blank=True, null=True) prdct_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name=_("Prix ")) prdct_cost = models.DecimalField(max_digits=10, decimal_places=2, verbose_name=_("Prix promotionel ")) prdct_weight = models.DecimalField(max_digits=10, decimal_places=2, verbose_name=_("Poid ")) prdct_created = models.DateTimeField(auto_now=False, auto_now_add=False, verbose_name=_("Date Creation ")) prdct_genre = models.CharField(max_length=50, verbose_name=_("Genre ")) prdct_matiere = models.CharField(max_length=50, verbose_name=_("Matiere ")) prdct_titrage = models.CharField(max_length=50, verbose_name=_("titrage ")) prdct_in_stock = models.BooleanField(verbose_name=_("in_stock ")) prdct_slug = models.SlugField(blank=True, null=True) # 新增动态价格属性 @property def calc_price_item(self): dailyprice = get_prixmatiere() item_price = self.prdct_price + dailyprice * self.prdct_weight return item_price.quantize(Decimal('0.00'))
第四步:模板层直接展示价格
现有views.py代码完全不用修改,直接在对应的HTML模板里调用属性即可:
- 商品列表页
product_list.html:
{% for product in product_list %} <div> <h4>{{ product.prdct_name }}</h4> <p>今日售价:€{{ product.calc_price_item }}</p> </div> {% endfor %}
- 商品详情页
product_detail.html:
<h2>{{ product_detail.prdct_name }}</h2> <p>当前售价:€{{ product_detail.calc_price_item }}</p>
- 分类商品页
category_product.html:
{% for item in product %} <div> <h4>{{ item.prdct_name }}</h4> <p>今日售价:€{{ item.calc_price_item }}</p> </div> {% endfor %}
可选优化
如果对页面响应速度要求高,可以用定时任务(Django Crontab/Celery)每天固定时间爬取价格更新到缓存,用户访问时直接读缓存,完全不用实时爬取,响应速度更快。
内容的提问来源于stack exchange,提问作者Mohamed Chougrani
相关产品推荐
相关产品推荐

