Items are not being added in the Cart.

Hi there, I have two apps in my Django Project, one is named as index and other is named as cart.
In index.models, I have a model TwoPieceSuit(), and in cart.models, I have two models viz. Cart() and CartManager() (just to make sure the cart is not created if it already exists and if the user was not logged in while adding items to cart, so after logging in, the system does not create new cart).

Well, the problem is when I try to get the Cart items by writing cart_obj.two_piece_suits, I get empty results. I am basically wanting to get items of the cart, and then add up their prices and update the total attribute of Cart() instance. I have added two items in index.models.TwoPieceSuit(). Also I have a ManyToMany relation between cart.models.Cart() and index.models.TwoPieceSuit(). But still I see empty results.

My index.models.py is:

import os
from django.db import models
from django.utils.text import slugify

def get_file_ext(filepath):
    base_name = os.path.basename(filepath)
    name, ext = os.path.splitext(base_name)
    return name, ext

def upload_image_path(instance, filepath):
    name, ext = get_file_ext(filepath)
    filename = instance.fabric + '-' + instance.lining + '-' + instance.buttons + '-' + \
            instance.button_hole_thread + '-' + instance.buttoning + '-' + instance.lapel + '-' + \
                instance.pockets + '-' + instance.vent + '-' + instance.contrasts + '-' + \
                    instance.trouser_pockets + '-' + instance.trouser_buttoning + '-' + \
                        instance.trouser_back_pocket + '-' + instance.trouser_turn_up + ext
    return "products/{filename}".format(filename=filename)

# Create your models here.

class Fabric(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'fabrics/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

class Lining(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'linings/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

class Button(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'buttons/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

class ButtonHoleThread(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'button-hole-threads/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

class Buttoning(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'buttonings/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

class Lapel(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'lapels/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

class Pocket(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'pockets/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

class Vent(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'vents/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

class Contrast(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'contrasts/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

class TrouserPocket(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'trouser-pockets/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

class TrouserButtoning(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'trouser-buttonings/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

class TrouserBackPocket(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'trouser-back-pockets/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

class TrouserTurnUp(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = 'trouser-turn-ups/', null = True, verbose_name = "Picture")

    def __str__(self):
        return f"{self.title}"

FABRICS = []
LININGS = []
BUTTONS = []
BUTTON_HOLE_THREADS = []
BUTTONINGS = []
LAPELS = []
POCKETS = []
VENTS = []
CONTRASTS = []
TROUSER_POCKETS = []
TROUSER_BUTTONINGS = []
TROUSER_BACK_POCKETS = []
TROUSER_TURN_UPS = []

for item in Fabric.objects.all():
    FABRICS.append((item.title.lower(), item.title))

FABRICS = tuple(FABRICS)

for item in Lining.objects.all():
    LININGS.append((item.title.lower(), item.title))

LININGS = tuple(LININGS)

for item in Button.objects.all():
    BUTTONS.append((item.title.lower(), item.title))

BUTTONS = tuple(BUTTONS)

for item in ButtonHoleThread.objects.all():
    BUTTON_HOLE_THREADS.append((item.title.lower(), item.title))

BUTTON_HOLE_THREADS = tuple(BUTTON_HOLE_THREADS)

for item in Buttoning.objects.all():
    BUTTONINGS.append((item.title.lower(), item.title))

BUTTONINGS = tuple(BUTTONINGS)

for item in Lapel.objects.all():
    LAPELS.append((item.title.lower(), item.title))

LAPELS = tuple(LAPELS)

for item in Pocket.objects.all():
    POCKETS.append((item.title.lower(), item.title))

POCKETS = tuple(POCKETS)

for item in Vent.objects.all():
    VENTS.append((item.title.lower(), item.title))

VENTS = tuple(VENTS)

for item in Contrast.objects.all():
    CONTRASTS.append((item.title.lower(), item.title))

CONTRASTS = tuple(CONTRASTS)

for item in TrouserPocket.objects.all():
    TROUSER_POCKETS.append((item.title.lower(), item.title))

TROUSER_POCKETS = tuple(TROUSER_POCKETS)

for item in TrouserButtoning.objects.all():
    TROUSER_BUTTONINGS.append((item.title.lower(), item.title))

TROUSER_BUTTONINGS = tuple(TROUSER_BUTTONINGS)

for item in TrouserBackPocket.objects.all():
    TROUSER_BACK_POCKETS.append((item.title.lower(), item.title))

TROUSER_BACK_POCKETS = tuple(TROUSER_BACK_POCKETS)

for item in TrouserTurnUp.objects.all():
    TROUSER_TURN_UPS.append((item.title.lower(), item.title))

TROUSER_TURN_UPS = tuple(TROUSER_TURN_UPS)

class TwoPieceSuit(models.Model):
    title = models.CharField(max_length = 100, verbose_name = "Title")
    img = models.FileField(upload_to = upload_image_path, null = True, \
        verbose_name = "Picture")
    fabric = models.CharField(max_length = 100, choices = FABRICS, \
        null = True)
    lining = models.CharField(max_length = 100, choices = LININGS, \
        null = True)
    buttons = models.CharField(max_length = 100, choices = BUTTONS, \
        null = True)
    button_hole_thread = models.CharField(max_length = 100, \
        choices = BUTTON_HOLE_THREADS, null = True, \
            verbose_name = "Button Hole Threads")
    buttoning = models.CharField(max_length = 100, \
        choices = BUTTONINGS, null = True)
    lapel = models.CharField(max_length = 100, choices = LAPELS, \
        null = True)
    pockets = models.CharField(max_length = 100, choices = POCKETS, \
        null = True)
    vent = models.CharField(max_length = 100, choices = VENTS, \
        null = True)
    contrasts = models.CharField(max_length = 100, choices = CONTRASTS, \
        null = True)
    trouser_pockets = models.CharField(max_length = 100, \
        choices = TROUSER_POCKETS, null = True, \
            verbose_name = "Trouser Pockets")
    trouser_buttoning = models.CharField(max_length = 100, \
        choices = TROUSER_BUTTONINGS, null = True, \
            verbose_name = "Trouser Buttoning")
    trouser_back_pocket = models.CharField(max_length = 100, \
        choices = TROUSER_BACK_POCKETS, null = True, \
            verbose_name = "Trouser Back Pocket")
    trouser_turn_up = models.CharField(max_length = 100, \
        choices = TROUSER_TURN_UPS, null = True, \
            verbose_name = "Trouser Turn Up")
    price = models.DecimalField(decimal_places = 2, max_digits = 20, default = 99.99)
    slug = models.SlugField(null = True, blank = True, db_index = True)

    def save(self, *args, **kwargs):
        self.slug = slugify(self.fabric + self.lining + self.buttons + \
            self.button_hole_thread + self.buttoning + self.lapel + \
                self.pockets + self.vent + self.contrasts + \
                    self.trouser_pockets + self.trouser_buttoning + \
                        self.trouser_back_pocket + self.trouser_turn_up)
        super().save(*args, **kwargs)

    def __str__(self):
        return f"{self.title}"

My cart.models.py is

from django.conf import settings
from django.db import models
from index.models import TwoPieceSuit

User = settings.AUTH_USER_MODEL

# Create your models here.
class CartManager(models.Manager):
    def new_or_get(self, request):
        cart_id = request.session.get("cart_id", None)
        qs = self.get_queryset().filter(id = cart_id)

        if qs.count() == 1:
            new_obj = False
            cart_obj = qs.first()
            if request.user.is_authenticated and cart_obj.user is None:
                cart_obj.user = request.user
                cart_obj.save()
        else:
            cart_obj = Cart.objects.new(user = request.user)
            new_obj = True
            request.session["cart_id"] = cart_obj.id
        
        return cart_obj, new_obj

    def new(self, user = None):
        user_obj = None
        if user is not None:
            if user.is_authenticated:
                user_obj = user
        return self.model.objects.create(user = user_obj)

class Cart(models.Model):
    user = models.ForeignKey(User, null = True, blank = True, on_delete = models.CASCADE)
    two_piece_suits = models.ManyToManyField(TwoPieceSuit, blank = True)
    total = models.DecimalField(default = 00.00, max_digits = 100, decimal_places = 2)
    updated = models.DateTimeField(auto_now = True)
    timestamp = models.DateTimeField(auto_now_add = True)

    objects = CartManager()

    def __str__(self):
        return str(self.id)

My cart.views.py is:

from django.shortcuts import render
from .models import Cart, CartManager

# Create your views here.
def cart_home(request):
    cart_obj, new_obj = Cart.objects.new_or_get(request)
    print(cart_obj.two_piece_suits)
    two_piece_suits = cart_obj.two_piece_suits.all()
    total = 0

    for item in two_piece_suits:
        print(item)
        print(item.price)
        total = total + item.price

    cart_obj.total = total
    cart_obj.save()

    return render(request, "cart/home.html", {})

I am tired of working it around and getting no results. Any help would be appreciated

Are you getting data from this? Or are these lines not printing anything?

Where is the code that adds the TwoPieceSuit to the Cart?

No, I am not getting any data printed on the screen by the code you quoted above. Had I been getting, would not it have worked all the way to add up the prices to the cart_obj.total?

In below code, line number 3 adds TwoPieceSuit to the Cart as a ManyToManyField.

No, that adds a reference to the TwoPieceSuit table as a field in your model.

I’m asking to see the code where you’re assigning instances of TwoPieceSuit to instances of Cart.

I did that manually using Django Administration Interface. Below screenshot explains that:

I can’t tell from that image whether you’ve selected those items in the list or not.

From the Django shell:

  • Get an instance of Cart
    (e.g. cart = Cart.objects.get(pk=<the pk you know having suits assigned to it>)
  • Print the related objects:
    (e.g. print(cart.two_piece_suits.all())

What’s the output?

If you don’t see the entries you expect, then you have not assigned the suits to the cart.

It may also be worth your time to review the relevant docs:

@KenWhitesell how do I get the primary key of the suits assigned to Cart instance? I have not put any mechanism to store the primary key of the suits.

Your Cart has an FK to User.

So, from the shell, you could do something like:

User = settings.AUTH_USER_MODEL
user = User.objects.get(username=<the username owning the cart you wish to examine>)
carts = Cart.objects.filter(user=user)
for cart in carts:
    print(cart.id)

That should give you all the carts associated with a specific user.

This gives me the following error:
AttributeError: 'str' object has no attribute 'objects'

and

this gives me the same error as well.

What’s the actual class you’re using as User?

This one which you wrote above.

Correct. What is the value of settings.AUTH_USER_MODEL?

The value is 'auth.User'.
image

Ok, so you don’t need to reassign User in the shell. Import the class from django.auth and run the ... User.objects.get( ... ) statement again.

And for future reference, please stop posting images here. They’re difficult to read on many devices, and cannot be quoted or copied for reference and explanations. Copy paste the actual text (placed between triple-backtick lines) into your messages. It works a whole lot better that way.

Noted, I knew about the triple-backtick lines method. But I though its better to post images. But, alright if the text-based info helps more.

Well, the django.auth gives this error:

>>> from django.auth import User
Traceback (most recent call last):
  File "<console>", line 1, in <module>
ModuleNotFoundError: No module named 'django.auth'
>>>

I don’t see how you can be running the Django shell and get that error. Are you running manage.py shell from the right directory?

Yes, I am running manage.py from right directory. Below is the detail of directory:

PS C:\Users\Admin\Desktop\projects\customise\customise> dir


    Directory: C:\Users\Admin\Desktop\projects\customise\customise


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----        11/18/2021  10:20 AM                cart
d-----         9/26/2021   9:37 PM                customise
d-----        11/14/2021   3:04 AM                index
d-----         11/3/2021   7:06 PM                media
d-----         9/26/2021   9:37 PM                static
d-----         9/27/2021   7:37 AM                templates
-a----        11/18/2021   3:06 PM         278528 db.sqlite3
-a----         7/30/2021   1:03 AM            687 manage.py


PS C:\Users\Admin\Desktop\projects\customise\customise> python .\manage.py shell
Python 3.9.7 (tags/v3.9.7:1016ef3, Aug 30 2021, 20:19:38) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.auth import User
Traceback (most recent call last):
  File "<console>", line 1, in <module>
ModuleNotFoundError: No module named 'django.auth'
>>>

Oops, that’s my goof. (I’m so used to using shell_plus I forget this)
It’s django.contrib.auth.models

OK, I got it working, and got the cart.id, but what is it’s use?

PS C:\Users\Admin\Desktop\projects\customise\customise> python .\manage.py shell
Python 3.9.7 (tags/v3.9.7:1016ef3, Aug 30 2021, 20:19:38) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.contrib.auth.models import User
>>> user = User.objects.get(username="khubi")
>>> from cart.models import Cart, CartManager
>>> carts = Cart.objects.filter(user=user)    
>>> carts                                     
<QuerySet [<Cart: 8>]>
>>> for cart in carts:  
...    print(cart.id)
... 
8
>>>

To determine whether or not you actually have suits assigned to that cart through the many-to-many relationship - Items are not being added in the Cart. - #6 by KenWhitesell