django - 如何在模型名称订单的单个字段中由用户获取购物车的所有项目
问题描述
现在我可以保存数据,但所有项目都单独保存而不是在一个字段中,所以我如何实现这一点,我使用购物车作为会话将其 id 和大小保存为键和值
我要保存订单的models.py
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE,)
item = models.ForeignKey(Item, on_delete=models.CASCADE )
status = models.IntegerField(choices = status_choices, default=1)
method = models.CharField(max_length=50, blank=False,)
size = models.CharField(max_length=20, blank=False)
price = models.FloatField(blank=False)
created_at = models.DateField(auto_now=True, editable=False)
payment_status = models.IntegerField(choices = payment_status_choices, default=3)
order_id = models.CharField(unique=True, max_length=200, null=True, blank=True, default=None)
datetime_of_payment = models.DateTimeField(default=timezone.now)
def placeorder(self):
self.save()
def __str__(self):
return self.user.username
我的views.py 来保存数据
以及我的购物车显示的 html
<tbody style="margin-bottom: 20px;">
{% for item in items %}
<tr>
<th scope="row">{{forloop.counter}}</th>
<td> <img src="{{item.first.url}}" alt="" height="100px"></td>
<td>{{item.name}}</td>
{% if item.swag %}
<td>{{item|cart_size:request.session.cart}}</td>
{% endif %}
{% if not item.swag %}
<td>Regular </td>
{% endif %}
<td>{{item.price|currency}}</td>
<td> <a href="#">Remove</a> </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</aside>
<aside class="col-lg-3">
<div class="card mb-3">
<div class="card-body">
<form>
<div class="form-group"> <label>Have coupon?</label>
<div class="input-group"> <input type="text" class="form-control coupon" name="" placeholder="Coupon code"> <span class="input-group-append"> <button class="btn btn-primary btn-apply coupon">Apply</button> </span> </div>
</div>
</form>
</div>
</div>
<div class="card">
<div class="card-body">
<dl class="dlist-align">
<dt style="float: left; font-size:20px; margin-right:10px;">Total price:</dt>
<dd style="font-size: 20px; color:#025;" class="text-right">{{items|total_actual_price:request.session.cart|currency}}</dd>
</dl>
<dl class="dlist-align">
<dt style="float: left; font-size:20px; margin-right:10px;">Discount:</dt>
<dd style="font-size: 20px; color:#025;" class="text-right text-danger">{{items|discount_price:request.session.cart|currency}}</dd>
</dl>
<dl class="dlist-align">
<dt style="float: left; font-size:20px; margin-right:10px;">Total Paying Amount:</dt>
<dd style="font-size: 20px; color:#025;" class="text-right"><strong name="price" >{{items|total_price:request.session.cart|currency}}</strong></dd>
</dl>
<hr>
<a href="#" class="btn btn-out btn-primary btn-square btn-main" data-bs-toggle="modal" data-bs-target="#exampleModal"> Make Purchase </a> <a href="#" class="btn btn-out btn-success btn-square btn-main mt-2" data-abc="true">Continue Shopping</a>
</div>
</div>
</aside>
</div>
</div>
正如您所看到的,我正在使用过滤器来显示用户购物车的总价格,所以我想要的是保存项目字段中所有项目的项目 ID 和大小字段中的大小,根据他们的项目,而不是总价格得到保存。但是现在它正在为项目保存单独的字段,我不想要那个
我用于结帐和保存订单的 html 表单
<div class="modal-body">
<form action="{% url 'orders:checkout' %}" method="Post">
{% csrf_token %}
<h3>Please Select Your Payment Method</h3> <br>
<div class="method" style="font-size: 23px;">
<input type="radio" value="postpaid" name="payment" style="height: 20px; width: 20px;">
<label for="postpaid">Cash On Delivery</label>
<input type="radio" value="Prepaid" name="payment" style="height: 20px; width: 20px;">
<label for="prepaid">Online Payment</label>
</div>
</div>
<input type="submit" class="btn float-right btn-primary" value='Go Ahead'>
</form>
项目模型
class Item(models.Model):
categories = models.ForeignKey(Categories, on_delete=models.CASCADE, related_name='our_items')
subcategories = models.ForeignKey(Subcategories, on_delete=models.CASCADE, related_name='products')
name = models.CharField(max_length=200, blank=False)
contain_size = models.CharField(max_length=50, blank=True)
brand_name = models.CharField(max_length=100, blank=False, default='Bagh')
swag = models.BooleanField(blank=False, default=False)
male = models.BooleanField(blank=False, default=False)
female = models.BooleanField(blank=False, default=False)
unisex = models.BooleanField(blank=False, default=False)
first = models.ImageField(upload_to='items', blank=False)
second = models.ImageField(upload_to='items', blank=False)
third = models.ImageField(upload_to='items', blank=True)
fourth = models.ImageField(upload_to='items', blank=True)
fifth = models.ImageField(upload_to='items', blank=True)
sixth = models.ImageField(upload_to='items', blank=True)
seventh = models.ImageField(upload_to='items', blank=True)
rate = models.CharField(max_length=5, choices=rating, default='⭐⭐⭐⭐')
stock = models.CharField(max_length=50, blank=False, default='In Stock')
authentic = models.CharField(max_length=1,blank=False,choices=auth, default='✔')
price = models.FloatField(blank=False,)
actual_price = models.FloatField(blank=False)
type = models.CharField(blank=False, max_length=100, default='Cloth')
joined_date = models.DateTimeField(default=timezone.now,editable=False)
update_at = models.DateTimeField(auto_now=True)
description = models.TextField(blank=True)
@staticmethod
def get_items_by_id(ids):
return Item.objects.filter(id__in = ids)
def __str__(self):
return self.name
和购物车视图,用户选择后所有项目都在哪里
class Cart(View):
def get (self, request):
cart = request.session.get('cart', None)
if not cart:
cart = {}
request.session['cart'] = cart
ids = (list(cart.keys()))
ids = (list(request.session.get('cart').keys()))
item = Item.get_items_by_id(ids)
address = Address.objects.filter(user=request.user)
print(item)
return render(request, 'cart.html', {'items': item, 'addresses':address })
它确实将项目保存在其中,但我想在该字段中获取汽车的所有项目
adding updated model as told
class Order(models.Model):
status_choices = (
(1, 'PENDING'),
(2, 'CONFIRMED'),
(3, 'PACKED'),
(4, 'SHIPPED'),
(5, 'IN WAY'),
(6, 'ARRIVED DESTINATION'),
(7, 'RECIEVED'),
(8, 'COMPLETED')
)
payment_status_choices = (
(1, 'SUCCESS'),
(2, 'FAILURE' ),
(3, 'PENDING'),
)
user = models.ForeignKey(User, on_delete=models.CASCADE,)
address = models.ForeignKey(Address, default= True, on_delete=models.CASCADE )
status = models.IntegerField(choices = status_choices, default=1)
method = models.CharField(max_length=50, blank=False,)
total_price = models.FloatField(blank=False, default=0)
created_at = models.DateField(auto_now=True, editable=False)
payment_status = models.IntegerField(choices = payment_status_choices, default=3)
order_id = models.CharField(unique=True, max_length=200, null=True, default=None)
datetime_of_payment = models.DateTimeField(default=timezone.now)
# related to razorpay
razorpay_order_id = models.CharField(max_length=1000, null=True, blank=True)
razorpay_payment_id = models.CharField(max_length=1000, null=True, blank=True)
razorpay_signature = models.CharField(max_length=1000, null=True, blank=True)
def save(self, *args, **kwargs):
if self.order_id is None and self.datetime_of_payment and self.id:
self.order_id = self.datetime_of_payment.strftime('CODER%Y%m%dODR') + str(self.id)
return super().save(*args, **kwargs)
def __str__(self):
return self.user.username + " " + str(self.order_id) + " " + str(self.created_at)
class OrderItem(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE,)
item = models.ForeignKey(Item, on_delete=models.CASCADE )
size = models.CharField(max_length=20, blank=False)
price = models.FloatField(blank=False)
def __str__(self):
return self.order.order_id
更新的views.py
class Checkout(View):
def post (self, request,):
user = request.user
address = Address.objects.filter(default=True, user=request.user)
cart = request.session.get('cart')
items = Item.get_items_by_id(list(cart.keys()))
prefer = request.POST.get('payment')
total_price = request.POST.get('paying_price')
total_price = json.loads(total_price)
with transaction.atomic():
order = Order.objects.create(
user=user,
total_price=total_price,
address=address.first(),
method = prefer,
)
for item in items:
item_order = OrderItem.objects.create(
order=order,
item=item,
size=cart.get(str(item.id)),
price=item.price,
)
request.session['cart'] = {}
return redirect('orders:cart',)
添加回溯
环境:
Request Method: POST
Request URL: http://localhost:8000/Check-Out/
Django Version: 3.2.6
Python Version: 3.8.5
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'crispy_forms',
'xhtml2pdf',
'accounts',
'products',
'orders']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback (most recent call last):
File "C:\Users\mithlesh\Desktop\coolbuy\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\mithlesh\Desktop\coolbuy\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\mithlesh\Desktop\coolbuy\lib\site-packages\django\views\generic\base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\mithlesh\Desktop\coolbuy\lib\site-packages\django\views\generic\base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File "C:\Users\mithlesh\Desktop\coolbuy\coolbuy\orders\views.py", line 61, in post
item_order = OrderItem.objects.create(
File "C:\Users\mithlesh\Desktop\coolbuy\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Users\mithlesh\Desktop\coolbuy\lib\site-packages\django\db\models\query.py", line 453, in create
obj.save(force_insert=True, using=self.db)
File "C:\Users\mithlesh\Desktop\coolbuy\lib\site-packages\django\db\models\base.py", line 682, in save
self._prepare_related_fields_for_save(operation_name='save')
File "C:\Users\mithlesh\Desktop\coolbuy\lib\site-packages\django\db\models\base.py", line 932, in _prepare_related_fields_for_save
raise ValueError(
Exception Type: ValueError at /Check-Out/
Exception Value: save() prohibited to prevent data loss due to unsaved related object 'order'.
解决方案
正如大多数答案中提到的,您必须将模型分成 2 个。 Order-OrderItem 场景是一对多关系的一个很好的例子。
假设您从 Swiggy(印度食品配送应用程序)订购 Roti、Paneer(印度菜)和可乐。Swiggy 说您的订单 ID 是 #123456。
模型应该是这样的。
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE,)
status = models.IntegerField(choices = status_choices, default=1)
method = models.CharField(max_length=50, blank=False,)
... other fields ...
Order 模型告诉用户 Shreyas 下订单,付款方式是 X,当前状态是 this。
class OrderItem(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE,)
item = models.ForeignKey(Item, on_delete=models.CASCADE )
size = models.CharField(max_length=20, blank=False)
price = models.FloatField(blank=False)
... any other fields ...
OrderItem 模型告诉这个项目 - 可乐 - 是订单 ID #123456 的一部分,订购时的价格是 Rs.X。
保存后的数据库应如下所示 -
订单表
ID | 用户 | 方法 | 地位 |
---|---|---|---|
123456 | shreyas(身份证) | 支付 | 订单已下 |
订单项表
ID | order_id | item_id | 尺寸 | 价格 |
---|---|---|---|---|
1 | 123456 | 烤肉(身份证) | n | 10.00 |
2 | 123456 | 芝士 (id) | n | 50.00 |
3 | 123456 | 可乐(身份证) | n | 25.00 |
保存您的订单
代码中有一条with transaction.atomic
语句,这使您可以一次编写所有模型,并在任何写入语句失败时恢复。参考:Django 交易
class Checkout(View):
def post (self, request):
user = request.user
address = Address.objects.filter(user=request.user)
cart = request.session.get('cart')
total_price = request.POST.get('price')
items = Item.get_items_by_id(list(cart.keys()))
prefer = request.POST.get('payment')
with transaction.atomic:
order = Order.objects.create(
user=user,
date_of_payment=datetime.datetime.now(),
total_price=total_price,
address=address
)
for item in items:
prod_order = OrderItem.objects.create(
order=order
item=item,
size=item.size,
price=price,
)
... return the view ...
推荐阅读
- javascript - 如何在 React.js 中映射到另一个地图
- c# - 如何在列表中赋值
类型 Xml 类 - javascript - Express 4 中路径参数中的 Json 对象
- apache-kafka - 同步来自多个数据源的数据
- javascript - 在手机上测试时,文本隐藏在图表 js 中
- mysql - 更新 JSON 列耗时过长
- cocoa - NSTextField 设置禁用的文本颜色
- java - 在 android 模拟器中执行 appium 脚本时收到意外响应:{"code":"ECONNRESET"}
- javascript - react中如何处理异步函数?
- reactjs - 如何制作像优步汽车一样的移动标记?