【问题标题】:Django recommendation engine only works via python shellDjango 推荐引擎只能通过 python shell 工作
【发布时间】:2018-04-10 16:42:59
【问题描述】:

我已经编写了这个推荐引擎(基于示例 Antonio Mele 的 Django)。

使用 shell 测试时一切正常,在渲染的模板中可以看到推荐的产品。 但是,当通过应用程序完成订单时,不会创建或显示推荐。

我完全坚持这个,任何建议都非常感谢......

import redis
from django.conf import settings
from .models import Product
# connect to redis
r = redis.StrictRedis(host=settings.REDIS_HOST,port=settings.REDIS_PORT,db=settings.REDIS_DB)
class Recommender(object):
    def get_product_key(self, id):
        return 'product:{}:purchased_with'.format(id)

    def products_bought(self, products):
        product_ids = [p.id for p in products]
        for product_id in product_ids:
            for with_id in product_ids:
                # get the other products bought with each product
                if product_id != with_id:
                    # increment score for product purchased together
                    r.zincrby(self.get_product_key(product_id),with_id,amount=1)
    def suggest_products_for(self, products, max_results=6):
        product_ids = [p.id for p in products]
        if len(products) == 1:  
            # only 1 product
            suggestions = r.zrange(self.get_product_key(product_ids[0]),0, -1, desc=True)[:max_results]
        else:
            # generate a temporary key
            flat_ids = ''.join([str(id) for id in product_ids])
            tmp_key = 'tmp_{}'.format(flat_ids)
            # multiple products, combine scores of all products
            # store the resulting sorted set in a temporary key
            keys = [self.get_product_key(id) for id in product_ids]
            r.zunionstore(tmp_key, keys)
            # remove ids for the products the recommendation is for
            r.zrem(tmp_key, *product_ids)
            # get the product ids by their score, descendant sort
            suggestions = r.zrange(tmp_key, 0, -1,desc=True)[:max_results]
            # remove the temporary key
            r.delete(tmp_key)
        suggested_products_ids = [int(id) for id in suggestions]
        # get suggested products and sort by order of appearance
        suggested_products = list(Product.objects.filter(id__in=suggested_products_ids))
        suggested_products.sort(key=lambda x: suggested_products_ids.index(x.id))
        return suggested_products

这是产品详细信息视图

def product_detail(request, id, slug):
    language = request.LANGUAGE_CODE
    product = get_object_or_404(Product, id=id, translations__language_code=language,
                                translations__slug=slug, available=True)
    cart_product_form = CartAddProductForm()
    r = Recommender()
    recommended_products = r.suggest_products_for([product])
    return render(request, 'shop/product/detail.html', 
        {'product': product, 'cart_product_form': cart_product_form, 
        'recommended_products': recommended_products })

购物车视图

def cart_detail(request):
    cart = Cart(request)
    for item in cart:
        item['update_quantity_form'] = CartAddProductForm(initial={'quantity': item['quantity'], 'update':True})

    coupon_apply_form = CouponApplyForm()
    r = Recommender()
    cart_products = [item['product'] for item in cart]
    recommended_products = r.suggest_products_for(cart_products)
    return render(request, 'cart/detail.html', {'cart': cart,'recommended_products': recommended_products,'coupon_apply_form': coupon_apply_form })

订单视图

def order_create(request):
    cart = Cart(request)

    if request.method == 'POST':
        r = Recommender()
        cart_products = [item['product'] for item in cart]
        recommended_products = r.suggest_products_for(cart_products,4)
        form = OrderCreateForm(request.POST)
        if form.is_valid():
            order = form.save(commit=False)
            order.save()

            if cart.coupon:
                coupon = cart.coupon
                coupon.save()
                order.discount = coupon.discount
                order.save()
            for item in cart:
                OrderItem.objects.create(order=order, product=item['product'], price=item['price'], quantity=item['quantity'])

            #emptying the cart
            r = Recommender()
            cart_products = [item['product'] for item in cart]
            recommended_products = r.suggest_products_for(cart_products)
            cart.clear()
            #launch celery async task
            order_created.delay(order.id)
            request.session['order_id'] = order.id #set order.id session
            return redirect(reverse('payment:process'))
    else:

        form = OrderCreateForm()
        r = Recommender()
        cart_products = [item['product'] for item in cart]
        recommended_products = r.suggest_products_for(cart_products)
    return render(request, 'orders/order/create.html', {'cart': cart, 'form':form, 'recommended_products':recommended_products})

以下 HTML 被添加到模板中,

{% if recommended_products %}
<div class="recommendations">
<h3>{% trans "People who bought this also bought" %}</h3>
{% for p in recommended_products %}
<div class="item">
<a href="{{ p.get_absolute_url }}">
<img src="{% if p.image %}{{ p.image.url }}{% else %}{%static "img/no_image.png" %}{% endif %}">
</a>
<p><a href="{{ p.get_absolute_url }}">{{ p.name }}</a></p>
</div>
{% endfor %}
</div>
{% endif %}

【问题讨论】:

  • 您是否尝试过调试或在某些时候添加一些打印?
  • 我已经学习了这门课程,但遇到了问题!当我选择每个产品时,它只建议第一个产品,即使我选择了第一个产品!我认为这是因为Recommender.py 中的这一行:suggestions = r.zrange(self.get_product_key(product_ids[0]), 0, -1, desc=True)[:max_results] 你收到的建议正确吗?你能帮我解决这个问题吗?

标签: django python-2.7 redis recommendation-engine


【解决方案1】:

已解决

问题是需要先调用 porducts_bought() 方法

所以cart_detail函数中的代码变了

来自

.......
    r = Recommender()
    cart_products = [item['product'] for item in cart]
    recommended_products = r.suggest_products_for(cart_products)
    return render(request, 'cart/detail.html', {'cart': cart,'recommended_products': recommended_products,'coupon_apply_form': coupon_apply_form})

........
    r = Recommender()
    cart_products = [item['product'] for item in cart]
    r.products_bought([item['product'] for item in cart])
    recommended_products = r.suggest_products_for(cart_products)
    return render(request, 'cart/detail.html', {'cart': cart,'recommended_products': recommended_products,'coupon_apply_form': coupon_apply_form})

【讨论】:

    猜你喜欢
    • 2011-02-11
    • 2014-04-18
    • 2012-01-09
    • 2023-03-13
    • 1970-01-01
    • 2019-09-25
    • 2017-10-26
    • 1970-01-01
    • 2014-10-27
    相关资源
    最近更新 更多