формы с ModelMultipleChoicefield / флажки, добавить множество экземпляров модели в один клик для сессии - PullRequest
0 голосов
/ 11 июня 2019

Чего я хотел бы достичь: я хочу построить форму с forms.ModelMultipleChoiceField и widget = forms.CheckboxSelectMultiple.Я хотел бы добиться с помощью формы, что я могу выбрать несколько экземпляров продукта одновременно и добавить их вместе одним нажатием кнопки в сеанс корзины.

Что я пытался сделать: я пытался создать форму с помощьюforms.ModelMultipleChoiceField и widget = forms.CheckboxSelectMultiple, представление и URL-адрес к нему.Я разделяю логику объекта корзины из модели продукта на 2 отдельных приложения.

В чем проблема: при переходе на зарегистрированный URL-маршрут шаблон формы становится черным, а в linux-терминале возникает следующая ошибка.

[11 / Jun / 2019 14:52:06] «GET / HTTP / 1.1» 200 1083 Метод не разрешен (GET): / cart / add_many_products / [11 / Jun / 2019 14:52:36] "GET / cart / add_many_products / HTTP / 1.1 "405 0

Я думаю, что проблема в следующем: я уверен, что это должно что-то делать с представлением.Я не совсем понимаю, как написать код для этого.Мне нужно объединить корзину добавить логику с формой с моделью несколько полей.Я предполагаю, что форму добавления множества товаров нужно перенести в массив / json, чтобы отправлять сразу несколько товаров в сессию корзины.Я не уверен, как именно с этим справиться.

Я надеюсь, что кто-нибудь сможет мне помочь или подскажет, как мне продолжить.

Любая помощь / подсказка будет высоко оценена

модель продукта:

from django.db import models
from django.urls import reverse

class Product(models.Model):

    name = models.CharField(max_length=200, db_index=True)
    slug = models.SlugField(max_length=200, db_index=True)
    image = models.ImageField(upload_to='products/%Y/%m/%d', blank=True)
    description = models.TextField(blank=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    available = models.BooleanField(default=True)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ('name',)
        index_together = (('id', 'slug'),)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
            return reverse('shop:product_detail', args=[self.id, self.slug])

модель корзины / cart.py

from decimal import Decimal
from django.conf import settings
from shop.models import Product


class Cart(object):

    def __init__(self, request):
        """
        Initialize the cart.
        """
        self.session = request.session
        cart = self.session.get(settings.CART_SESSION_ID)
        if not cart:
            # save an empty cart in the session
            cart = self.session[settings.CART_SESSION_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 = Product.objects.filter(id__in=product_ids)

        cart = self.cart.copy()
        for product in products:
            cart[str(product.id)]['product'] = product

        for item in cart.values():
            item['price'] = Decimal(item['price'])
            item['total_price'] = item['price'] * item['quantity']
            yield item

    def __len__(self):
        """
        Count all items in the cart.
        """
        return sum(item['quantity'] for item in self.cart.values())

    def add(self, product, quantity=1, update_quantity=False):
        """
        Add a product to the cart or update its quantity.
        """
        product_id = str(product.id)
        if product_id not in self.cart:
            self.cart[product_id] = {'quantity': 0, 'price': str(product.price)}
        if update_quantity:
            self.cart[product_id]['quantity'] = 1
        else:
            self.cart[product_id]['quantity'] += 1
        self.save()

    def save(self):
        # mark the session as "modified" to make sure it gets 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()

    def get_total_price(self):
        return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values())

    def clear(self):
        # remove cart from session
        del self.session[settings.CART_SESSION_ID]
        self.save()

корзина форм.py:

from django import forms
from shop.models import Product


PRODUCT_QUANTITY_CHOICES = [(1, str(1))]

class ProductCartAddManyForm(forms.Form):

    products = forms.ModelMultipleChoiceField(queryset=Product.objects.all(), widget=forms.CheckboxSelectMultiple,)
    quantity = forms.TypedChoiceField( choices=PRODUCT_QUANTITY_CHOICES, coerce=int, widget=forms.HiddenInput )
    update = forms.BooleanField(required=False,
                                initial=False,
                                widget=forms.HiddenInput)

просмотры корзины:

from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_POST
from shop.models import Product
from .cart import Cart
from .forms import CartAddProductForm, ProductCartAddManyForm


####writing new Form, add product queryset and connect with cart.add !


@require_POST
def cart_add_many_products(request, product_id):
    cart = Cart(request)
    form = ProductCartAddManyForm(request.POST)
    if form.is_valid():
        cd = form.cleaned_data
        cart.add(product=cd['products'], cd['products']
                    quantity=cd['quantity'],
                    update_quantity=cd['update'])
        #return redirect('cart:cart_detail')
    return render(request, 'cart/products_add.html', {'form': form})

form template:

<form action="{% url "cart:cart_add" product.id %}" method="post">
        {{ form }}
        {% csrf_token %}
        <input type="submit" value="Add to cart">
</form>

URL:

from django.urls import path
from . import views

app_name = 'cart'

urlpatterns = [
    path('', views.cart_detail, name='cart_detail'),
    path('add/<int:product_id>/', views.cart_add, name='cart_add'),
    path('remove/<int:product_id>/', views.cart_remove, name='cart_remove'),
    path('add_many_products/', views.cart_add_many_products, name='products_to_cart'),
]

.

...