add-product-to-cart-footer
tl;drその製品と他の情報を組み合わせた別のモデルのインスタンスを追加するように変更するにはどうすればよいですか?
私はメガネを販売しているので、フレームとフレームのバリエーション (色とサイズによって異なります) の情報を示す製品詳細ページがありますが、お客様は、そのフレームで入手したいレンズの種類のフォームにも記入する必要があります。 .
1 つのオプションは、フレーム バリアントとレンズの組み合わせの各順列をフレーム バリアントとしてデータベースに格納することです。これは、スマートフォンのさまざまなストレージ オプションと同様ですが、次の理由から、それは良い考えではないと思います。
- 数十の可能なレンズオプションがあります
- 利用可能なレンズは、選択したフレームとは本質的に無関係です
- フレーム バリアント + レンズ オブジェクトしかない場合、フレーム バリアントの在庫に関する情報を保存するのは困難です。(私は管理在庫を追加する Django Shop 1.1 を使用しています。)
代わりに、フレーム バリアントとレンズへの外部キーを備えたメガネ モデルを用意することを考えています。これがカートに追加されるものです。
class Lenses(models.Model):
material = models.CharField(choices=...)
anti_reflective = models.CharField(choices=...)
# ...
class Glasses(models.Model):
frame = models.ForeignKey(FrameVariant)
lenses = models.ForeignKey(Lenses)
「カートに追加」ボタンを変更して、フレーム バリアントをカートに追加する代わりに、レンズを選択するためのフォーム (同じページにオーバーレイされる可能性があります) に移動するようにしたいと思います。オーバーライドする関連ブロックは次add-product-to-cart-footer
のshop/catalog/product-add2cart
とおりです。
{% block add-product-to-cart-footer %}
<div class="card-footer bg-white">
<div class="d-flex flex-column flex-lg-row justify-content-between">
<button class="btn btn-secondary m-1" ng-disabled="context.is_in_cart" ng-click="do(addToCart('{% url "shop:watch-list" %}'))">
{% trans "Watch product" %}
<i class="fa" ng-class="context.is_in_cart ? 'fa-heart' : 'fa-heart-o'"></i>
</button>
{% url "shop:cart-list" as cart_endpoint %}{% trans "The product has been successfully placed in the shopping cart:" as modal_title %}
<button
class="btn btn-primary m-1"
ng-disabled="!context.availability.quantity"
ng-click="
{% if use_modal_dialog %}
do(openModal('{{ modal_title }}'))
.then(addToCart('{{ cart_endpoint }}'))
.then(redirectTo())
{% else %}
do(addToCart('{{ cart_endpoint }}'))
.then(emit('shop.cart.change'))
{% endif %}
"
>
{% trans "Add to cart" %}
<i class="fa fa-cart-arrow-down"></i>
</button>
</div>
{% if request.session.is_empty %}
<small class="text-muted m-1">{% block cookie-disclaimer %}
{% blocktrans %}By adding a product to the cart you are giving consent to cookies being used.{% endblocktrans %}
{% endblock %}</small>
{% endif %}
</div>
{% endblock add-product-to-cart-footer %}
addToCart(endpoint)
ショップ/静的/ショップ/js/catalog.js から:
scope.addToCart = function(endpoint) {
return function(context) {
var deferred = $q.defer();
$http.post(endpoint, scope.context).then(function(response) {
scope.context.is_in_cart = true;
deferred.resolve(context);
}).catch(function(response) {
$log.error('Unable to update context: ' + response.statusText);
deferred.reject();
});
return deferred.promise;
};
};
context
カートに追加されるものを決定するように見えるので、それを変更する必要があります. context
が通過しているようですshop/cascade/catalog.py
:
class ShopAddToCartPlugin(ShopPluginBase):
name = _("Add Product to Cart")
require_parent = True
parent_classes = ('BootstrapColumnPlugin',)
cache = False
use_modal_dialog = GlossaryField(
widgets.CheckboxInput(),
label=_("Use Modal Dialog"),
initial='on',
help_text=_("After adding product to cart, render a modal dialog"),
)
def get_render_template(self, context, instance, placeholder):
templates = []
if instance.glossary.get('render_template'):
templates.append(instance.glossary['render_template'])
if context['product'].managed_availability():
template_prefix = 'available-'
else:
template_prefix = ''
templates.extend([
'{}/catalog/{}product-add2cart.html'.format(app_settings.APP_LABEL, template_prefix),
'shop/catalog/{}product-add2cart.html'.format(template_prefix),
])
return select_template(templates)
def render(self, context, instance, placeholder):
context = super(ShopAddToCartPlugin, self).render(context, instance, placeholder)
context['use_modal_dialog'] = bool(instance.glossary.get('use_modal_dialog', True))
return context
ShopAddToCartPlugin を調べても、Django Shop コードでも Cookiecutter によって生成されたものでも注目すべき使用法は見つかりませんでしcontext
たrender
。
編集: 別のオプションは、通常どおりフレーム バリアントをカートに追加することですが、そのフレーム バリアントに関連付けられた Lenses オブジェクトを作成するレンズ フォームにリダイレクトします。もっと簡単にできそうです。