2

I am very new to Django so it is hard for me to understand what information is most relevant to try and find the answer to my question.

I followed a tutorial to learn Django. The class creates a shopping cart. I have a problem where I can not add items to the shopping cart or remove them. The main thing that looks suspicious to me is that in the database when I look at a cart there is a drop down to select book but instead of the name of the book it says Book Object. I believe this is the problem but I am not sure how to troubleshoot it.
enter image description here

I am starting to think maybe this problem is the difference in versions. The tutorial is using a later version. I am using

python 2.7.10 django 1.9.4

I assume this comes down to my models and my view

URL to add to cart and remove

url(r'^add/(\d+)', views.add_to_cart, name='add_to_cart'),  
url(r'^remove/(\d+)', views.remove_from_cart, name='remove_from_cart'),

Here is the model for Cart and BookOrder

   from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User

class Author(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

    def __unicode__(self): 
        return "%s, %s" % (self.last_name, self.first_name)


def cover_upload_path(instance,filename):
    return '/'.join(['books',str(instance.id),filename])


class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author)
    description = models.TextField()
    publish_date = models.DateField(default=timezone.now)
    price = models.DecimalField(decimal_places=2, max_digits=8)
    stock = models.IntegerField(default=0)
    cover_image = models.ImageField(upload_to=cover_upload_path, default='books/empty_cover.jpg')

class Review(models.Model):
    book = models.ForeignKey(Book)
    user = models.ForeignKey(User)
    publish_date = models.DateField(default=timezone.now)
    text = models.TextField()
    latitude= models.FloatField(max_length=20, default="37.41920")
    longitude= models.FloatField(max_length=20, default="122.8574")

class Cart(models.Model):
    user = models.ForeignKey(User)
    active = models.BooleanField(default=True)
    order_date = models.DateField(null=True)
    payment_type = models.CharField(max_length=100, null=True)
    payment_id = models.CharField(max_length=100, null=True)

    def add_to_cart(self, book_id):
        book = Book.objects.get(pk=book_id)
        try:
            preexisting_order = BookOrder.objects.get(book=book, cart=self)
            preexisting_order.quantity += 1
            preexisting_order.save()
        except BookOrder.DoesNotExist:
            new_order = BookOrder.objects.create(
                book=book,
                cart=self,
                quantity=1
                )
            new_order.save()

    def remove_from_cart(self, book_id):
        book = Book.objects.get(pk=book_id)
        try:
            preexisting_order = BookOrder.objects.get(book=book, cart=self)
            if preexisting_order.quantity > 1:
                preexisting_order.quantity -= 1
                preexisting_order.save()
            else:
                preexisting_order.delete()
        except BookOrder.DoesNotExist:
            pass


class BookOrder(models.Model):
    book = models.ForeignKey(Book)
    cart = models.ForeignKey(Cart)
    quantity = models.IntegerField()

And here is the view for adding and removing from cart.

def add_to_cart(request,book_id):
        if request.user.is_authenticated():
            try:
                book = Book.objects.get(pk=book_id)
            except ObjectDoesNotExist:
                pass
            else :
                try:
                    cart = Cart.objects.get(user = request.user, active = True)
                except ObjectDoesNotExist:
                    cart = Cart.objects.create(user = request.user)
                    cart.save()
                    cart.add_to_cart(book_id)
                    return redirect('cart')
                else:
                    return redirect('index')


def remove_from_cart(request, book_id):
    if request.user.is_authenticated():
        try:
            book = Book.objects.get(pk = book_id)
        except ObjectDoesNotExist:
            pass 
        else:
            cart = Cart.objects.get(user = request.user, active = True)
            cart.remove_from_cart(book_id)
        return redirect('cart')
    else:
        return redirect('index')

2 Answers 2

1

For being able to see object names instead of seeing Model object, you need to define __unicode__ method in your model.

For your cart model:

class Cart(models.Model):
    ...
    [fields]
    ...

    def __unicode__(self):
        return "%s's cart" % self.user.username

By defining this, you'll be able to see "username's cart"

For BookOrder Model

class BookOrder(models.Model):

    def __unicode__(self):
        return self.book.name or self.book.title

By defining this, you'll be able to see the book name like "My Book name".

Sign up to request clarification or add additional context in comments.

8 Comments

I had a unicode method in my model. I updated the question with my full model to show you.
You have __unicode__ method only in your Author model, you need to define it on every model.
ahh ok thank you. Just the same thing I have? Copy it each time to each method? Better question. is sel.lastname the value I am getting? So Ig I want book ID i need self.book_id
Yes exactly! You can access foreignkey fields too.
Ok great thank you. Did this change recently because it does not do this in the tutorial. Could this be do to versions? I really want to master this.
|
1

Add __str__() or __unicode__() method in your models. This method is called whenever string representation of an object is required e.g. as you seeing while displaying as a choice in dropdown menu.

You can return any string as it suits your.

Sample:

class Cart(models.Model):
    ...
    def __str__(self,):
        return str(self.id)
        #OR
        return str(self.user)+str(self.id)

4 Comments

I had a unicode method in my model. I updated the question with my full model to show you.
@wuno, You may want to decorate your class for support for unicode with python2, something changed in django 1.9. Also, try adding __str__ method as well, ref docs.djangoproject.com/en/1.9/ref/models/instances/#str
Great thank you man. Can you explain what str is going vs just unicode? the unicode works for the author name so I assume I don't need str but I am about to find out. But for future reference why would you suggest using that here?
__str__ for python3.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.