wuno
wuno

Reputation: 9885

Passing Object ID to URL Django Python

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

Upvotes: 2

Views: 1260

Answers (2)

v1k45
v1k45

Reputation: 8250

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

Upvotes: 1

Rohan
Rohan

Reputation: 53386

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)

Upvotes: 1

Related Questions