Andrew
Andrew

Reputation: 433

Save a list of objects in model as a field

I'm trying to write internet-shop, and I have a model Order:

class Order(models.Model):
    state_choices = ('ACTIVE', 'COMPLETED', 'FROZEN')
    order_date = models.DateTimeField(auto_now_add=True)
    delivery_time = models.CharField(max_length=100)
    address_city = models.CharField(max_length=40)
    address_street = models.CharField(max_length=40)
    address_building = models.CharField(max_length=40)
    state = models.CharField(max_length=200, default='ACTIVE')
    products = models.ForeignKey(OrderProduct)
    client = models.ForeignKey(CustomUser)

And OrderProduct:

class OrderProduct(models.Model):
    product = models.ForeignKey(Product)
    product_ammount = models.IntegerField()

As you can see, user can add to order different products and different ammount of each product. So, with current models, I can add to order only one type of product. Then I rewrite it in the next way:

class Order(models.Model):
    state_choices = ('ACTIVE', 'COMPLETED', 'FROZEN')
    order_date = models.DateTimeField(auto_now_add=True)
    delivery_time = models.CharField(max_length=100)
    address_city = models.CharField(max_length=40)
    address_street = models.CharField(max_length=40)
    address_building = models.CharField(max_length=40)
    state = models.CharField(max_length=200, default='ACTIVE')
    client = models.ForeignKey(CustomUser)

class OrderProduct(models.Model):
    product = models.ForeignKey(Product)
    order = models.ForeignKey(Order)
    product_ammount = models.IntegerField()

And in a view, when I need to get a user's orders, I just do next: Order.objects.get(client=request.user).orderproduct_set But I think that it's not correct. How to rebuild these models to gain the desired result?

Upvotes: 2

Views: 3546

Answers (1)

sthzg
sthzg

Reputation: 5554

In my opinion the second approach is perfectly fine.

One small error in the question is that the query uses get() instead of filter(). This will lead to an exception once one user has more than one order.

So, instead of the get() it would be:

orders = Order.objects.filter(client=request.user)
for order in orders:
    print order.orderproduct_set.all()

To use this in a template (question from the comments) it is enough to pass the orders:

views.py

class MyView(View):
    def get(self, request):
         ctx = {
             'orders': Order.objects.filter(client=request.user)
         }
         return render(request, 'my/template.html', ctx)

my/template.html

{% for order in orders %}
    {% for item in order.orderproduct_set.all %}
        {{ item.product_amount }}x {{ item.product }}<br/>
    {% endfor %}
{% endfor %} 

Upvotes: 2

Related Questions