Заполнение формы данными из сессии; django

Мне интересно, как заполнить мою форму данными, которые я сохранил в моей сессии. моя модель:

models.py

class Order(models.Model):
    order_by = ForeignKey(User, on_delete=DO_NOTHING)
    order_status = ForeignKey(OrderStatus, on_delete=DO_NOTHING)
    created = DateTimeField(default=datetime.now)
    address_street = CharField(max_length=256)
    address_postal_code = CharField(max_length=18)
    address_city = CharField(max_length=128)
    shipping = ForeignKey(ShippingMethod, on_delete=DO_NOTHING)
    payment = DecimalField(max_digits=12, decimal_places=2, null=False)
    payment_method = ForeignKey(PaymentMethod, on_delete=DO_NOTHING)

    def __str__(self):
        return self.id

У меня есть представление, которое хранит мой выбор в 'cart'

class AddProductToCartView(View):
    def get(self, request, pk):
        cart = request.session.get("cart")
        if cart:
            for item in cart:
                if item["id"] == pk:
                    item["quantity"] += 1
                    break
            else:
                cart.append({"id": pk, "quantity": 1})
            request.session["cart"] = cart
        else:
            request.session["cart"] = [{"id": pk, "quantity": 1}]
        return redirect("store:cart_view")

class CartView(View):
    def get(self, request):
        in_cart = []
        overall_price = 0
        overall_tax = 0
        if "cart" in request.session:
            overall_price = 0
            for item in request.session["cart"]:
                product = Product.objects.select_related("category").get(id=item["id"])
                total_price = product.price * item["quantity"]
                tax = (total_price * product.tax)
                in_cart.append({
                    "product": product,
                    "quantity": item["quantity"],
                    "total_price": total_price,
                    "tax": tax
                })
                overall_price += total_price
                overall_tax += tax
        return render(
            request,
            template_name="cart/cart_view.html",
            context={
                "products": in_cart if len(in_cart) > 0 else None,
                "overall_price": overall_price,
                "overall_tax": overall_tax
            }
        )

и я хочу заполнить мою форму данными (некоторые из них не все находятся в моей "корзине", поэтому я ненавижу брать информацию от пользователя из формы.

).

Я понял, что я хочу создать форму с определенными данными:

class AddAditionalDataForm(forms.ModelForm):
    class Meta:
        model = Order
        fields = ['certain fields']

и в файле views.py

class CheckOutView(CreateView):
    form_class = AddAditionalDataForm
    template_name = 'check_form/check_out_form.html'
    

Я не знаю, что такое готовое решение, скорее, подсказка, в каком направлении двигаться дальше.

Чтобы заполнить форму из нескольких источников данных, можно просто объединить эти источники и использовать новые данные.

# request.POST is immutable by default. 
# .copy() will make a new, mutable copy. 
data = request.POST.copy()
data['cart'] = request.sessions.get('cart')

form = AddAdditionalDataForm(data)

Еще две вещи, о которых я хочу упомянуть.

  1. Не стоит использовать данные, предоставленные пользователем, без проверки. Что если pk не совпадает ни с одним существующим Product?

  2. В вашей модели Order нет поля, связанного с Product. Я не уверен, так ли это задумано, но наличие дополнительной модели, описывающей список заказов, имеет ряд преимуществ.

    .

2.1 Детализация заказа теперь отслеживается.

2.2 Скидка может быть применена к индивидуальному заказу.

2.3 Статистика продуктов теперь включает данные о продажах.

# Example order item definition
class OrderItem(models.Model):
    order = models.ForeignKey(Order, on_delete=models.CASCADE)
    product = models.ForeignKey(Product, on_delete=models.PROTECT)
    quantity = models.IntegerField(default=1)
    price = models.DecimalField(max_digits=12, decimal_places=2)

В таком случае валидация формы становится немного сложнее

ItemFormSet = modelformset_factory(OrderItem, fields=['product', 'quantity', 'price'])

class CheckOutView(CreateView):
    form_class = AddAdditionalDataForm
    template_name = 'check_form/check_out_form.html'
    def post(self, request, *args, **kwargs):
        order_form = self.form_class(request.POST)
        # NOTE formset identifies different item data by their prefix,
        # and requires additional management data. i.e.
        # cart_data = {
        #     'item-0-pk': 17, 'item-0-quantity': 1,
        #     'item-1-pk': 28, 'item-1-quantity': 3,
        #     'item-INITIAL_FORMS': 0,
        #     'item-TOTAL_FORMS': 2}
        cart_data = get_cart_data(request.session.get('cart'))
        items_formset = ItemFormSet(cart_data)
        # Save order only when both forms are valid.
        if order_form.is_valid() and items_formset.is_valid()
            order = order_form.save()
            items = items_formset.save(commit=False)
            for item in items:
                item.order = order
            OrderItem.objects.bulk_create(items)
            return redirect(...)
        else:
            ...
    def get_context_data(self, **kwargs):
        # Include empty formset in get request. 
        # NOTE not to override form and formset containing error data in post request. 
        ...
Вернуться на верх