Заполнение формы данными из сессии; 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)
Еще две вещи, о которых я хочу упомянуть.
Не стоит использовать данные, предоставленные пользователем, без проверки. Что если
pk
не совпадает ни с одним существующимProduct
?В вашей модели
.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.
...