如何在模型名称订单的单个字段中获取用户购物车的所有商品

how to fetch all the item of a cart by a user in single field of model name orders

现在我可以保存数据,但所有项目都是单独保存的,而不是在一个字段中,所以我如何才能实现这一点,我使用购物车作为会话来保存它的 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'.

您需要将模型 Order 拆分为两个模型:

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,)
    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)
    created_at = models.DateField(auto_now=True, editable=False)

    def placeorder(self):
        self.save()
    
    def __str__(self):
        return self.user.username


class ProductOrder(models.Model):
    order = models.ForeingKey(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)

这样一来,每个订单将有 1 个订单和多个产品。

添加来自@allexiusw 的答案

最佳做法是,您需要为 product_order 创建 2 个多对多关系的模型:

class Order(models.Model):
    order_group_id = models.AutoField(primary_key=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    product_order = models.ManyToManyField(OrderItem, related_name='order', null=True)
    total_price = models.DecimalField(default=0, decimal_places=2, max_digits=10, null=True)
    datetime_of_payment = models.DateTimeField(default=timezone.now, null=True)
    ...
   

class OrderItem(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE, null=True)
    size = models.CharField(max_length=20, blank=False, null=True)
    price = models.FloatField(blank=False, null=True)
    ...

要将其保存到这 2 个模型,您可以这样做:

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')


        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(
                item=item,
                size=item.size,
                price=price,
            )
            order.product_order.add(prod_order)
        order.save()
        ....

您好,我有电子商务方面的经验, 据我所知,您想在一个字段中保存商品的所有详细信息,例如尺寸、价格、名称、邮件描述。对吗?

如果是,那么我直接认为不可能,你可以尝试一件事 --

1.You can take all the desired data and create a dictionary or list out of them
2. Create a single textfield with more maxlength and a FK with user or customer model  and then you can save the list or dict as text in that one field in db, and then can retrieve the all data as well as you can get by index also.\

但仅存储数据会更有效,如果您想有效地检索数据,请使用您创建的单独模型。

希望它会有,我应用了相同类型的概念来存储客户投诉和用户的付款详细信息,我喜欢你的代码,你正在遵循良好的做法!

如大多数答案中所述,您必须将模型拆分为 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 ...

订单模型告诉用户 Shreyas 下了订单,付款方式是 X,当前状态是这样。

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。

保存后的数据库应如下所示 -

订单table

id user method status
123456 shreyas (id) payment order_placed

订单项table

id order_id item_id size price
1 123456 roti (id) n 10.00
2 123456 paneer (id) n 50.00
3 123456 coke (id) n 25.00

正在保存您的订单

代码中有一个with transaction.atomic语句,这允许您一次编写所有模型,并在任何写入语句失败时恢复。参考:Django transactions

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 ...