Arpit Linux
Arpit Linux

Reputation: 259

Object returning true even if it is None

So i'm trying to see if the user has something in their cart, if they don't and they click on chekout then it should say that their cart is empty but it just makes an order object. makeorder and createorder function handles creating orders. CartItem objects returns True even if user does not have it. makeorder function handles checking if user has that object or not.

views.py

from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import User
from django.contrib.auth import login, logout, authenticate
from django.db import IntegrityError
from .models import Book, CartItem, OrderItem
from django.contrib.auth.decorators import login_required
from .forms import BookForm
from django.core.exceptions import ObjectDoesNotExist
import random
# Create your views here.

removederror = ''


def calculate(request):
    oof = CartItem.objects.filter(user=request.user)
    fianlprice = 0
    for item in oof:
        fianlprice += item.book.price

        


def signupuser(request):
    if request.user.is_authenticated:
        return render(request, 'main/alreadyloggedin.html')
    elif request.user != request.user.is_authenticated:
        if request.method == "GET":
            return render(request, 'main/signupuser.html', {'form':UserCreationForm()})
        elif request.method == "POST":
            if request.POST['password1'] == request.POST['password2']:
                try:
                    user = User.objects.create_user(request.POST['username'], password=request.POST['password1'])
                    user.save()
                    login(request, user)
                    return render(request, 'main/UserCreated.html')
                except IntegrityError:
                    return render(request, 'main/signupuser.html', {'form':UserCreationForm(), 'error':'That username has already been taken. Please choose a new username'})
            else:
                return render(request, 'main/signupuser.html', {'form':UserCreationForm(), 'error':'Passwords did not match'})

def signinuser(request):
    if request.user.is_authenticated:
        return render(request, 'main/alreadyloggedin.html', {'error':'You are already logged in'})
    elif request.user != request.user.is_authenticated:
        if request.method == "GET":
            return render(request, 'main/signinuser.html', {'form':AuthenticationForm()})
        elif request.method == "POST":
            user = authenticate(request, username=request.POST['username'], password=request.POST['password'])
            if user is None:
                return render(request, 'main/signinuser.html', {'form':AuthenticationForm(), 'error':'Username and password did not match'})
            else:
                login(request, user)
                return render(request, 'main/loggedin.html', {'error':'You are now logged in!'})
 
def logoutuser(request):
    if request.user.is_authenticated:
        if request.method == "GET": 
            return render(request, 'main/logoutuser.html')
        elif request.method == "POST":
            logout(request)
            return render(request, 'main/loggedin.html', {'error':'You are now logged out!'})
    elif request.user != request.user.is_authenticated:
        return render(request, 'main/alreadyloggedin.html', {'error':'You are not logged in'})
    

def home(request):
    if request.user.is_authenticated:
        oof = CartItem.objects.filter(user=request.user)
        fianlprice = 0
        for item in oof:
            fianlprice += item.book.price
        books = Book.objects.all()
        return render(request, 'main/home.html', {'books':books, 'price':fianlprice, 'error':''})
    else:
        books = Book.objects.all()
        return render(request, 'main/home.html', {'books':books})


@login_required
def addtocartforhome(request):
    oof = CartItem.objects.filter(user=request.user)
    fianlprice = 0
    for item in oof:
        fianlprice += item.book.price
    books = Book.objects.all()
    if request.method == 'POST':
        if CartItem.objects.filter(user=request.user, book=Book.objects.get(pk=request.POST['bookid'])).exists():
            return render(request, 'main/home.html', {'books':books, 'error':'That book is already in your cart!', 'price':fianlprice})
            
        else:
            try:
                book = Book.objects.get(pk=request.POST['bookid'])
            except Book.DoesNotExist:
                return redirect('home')
            cart_item = CartItem.objects.create(book=book, user=request.user)
            return redirect('home')
            
    elif request.method == 'GET':
        return render(request, 'main/signinuser.html', {'form':BookForm})
                                            

@login_required
def addtocartforproducts(request):
    oof = CartItem.objects.filter(user=request.user)
    fianlprice = 0
    for item in oof:
        fianlprice += item.book.price
    books = Book.objects.all()
    if request.method == 'POST':
        if CartItem.objects.filter(user=request.user, book=Book.objects.get(pk=request.POST['bookid'])).exists():
            return render(request, 'main/products.html', {'books':books, 'error':'That book is already in your cart!', 'price':fianlprice})
            
        else:
            try:
                book = Book.objects.get(pk=request.POST['bookid'])
            except Book.DoesNotExist:
                return redirect('showproducts')
            cart_item = CartItem.objects.create(book=book, user=request.user)
            return redirect('showproducts')
            
    elif request.method == 'GET':
        return render(request, 'main/signinuser.html', {'form':BookForm})

@login_required
def removefromcartforcart(request):
    if request.method == 'POST':
        oof = CartItem.objects.filter(user=request.user)
        fianlprice = 0
        for item in oof:
            fianlprice += item.book.price
        books = Book.objects.all()
        removebook = Book.objects.get(pk=request.POST['removeid'])
        try:
            cart_item = CartItem.objects.get(book=removebook, user=request.user).delete()
        except ObjectDoesNotExist:
            return render(request, 'main/cart.html', {'books':books, 'error':'That item is not in your cart!', 'price':fianlprice})
        return redirect('showcart')
    else:
        pass

@login_required
def removefromcartforhome(request):
    if request.method == 'POST':
        oof = CartItem.objects.filter(user=request.user)
        fianlprice = 0
        for item in oof:
            fianlprice += item.book.price
        books = Book.objects.all()
        removebook = Book.objects.get(pk=request.POST['removeid'])
        try:
            cart_item = CartItem.objects.get(book=removebook, user=request.user).delete()
        except ObjectDoesNotExist:
            removederror = 'That item is not in your cart!'
            return redirect('home')
        return redirect('home')
    else:
        pass

@login_required
def removefromcartforproducts(request):
    if request.method == 'POST':
        oof = CartItem.objects.filter(user=request.user)
        fianlprice = 0
        for item in oof:
            fianlprice += item.book.price
        books = Book.objects.all()
        removebook = Book.objects.get(pk=request.POST['removeid'])
        try:
            cart_item = CartItem.objects.get(book=removebook, user=request.user).delete()
        except ObjectDoesNotExist:
            return render(request, 'main/products.html', {'books':books, 'error':'That item is not in your cart!', 'price':fianlprice})
        return redirect('showproducts')
    else:
        pass


def showproducts(request):
    oof = CartItem.objects.filter(user=request.user)
    fianlprice = 0
    for item in oof:
        fianlprice += item.book.price
    books = Book.objects.all()
    return render(request, 'main/products.html', {'books':books, 'price':fianlprice})


@login_required
def showcart(request):
    oof = CartItem.objects.filter(user=request.user)
    fianlprice = 0
    for item in oof:
        fianlprice += item.book.price
    oof = CartItem.objects.filter(user=request.user)
    return render(request, 'main/cart.html', {'cart':oof, 'price':fianlprice})

@login_required
def makeorder(request):
    if request.method == 'POST':
        request_cart = CartItem.objects.filter(user=request.user)
        if request_cart is None:
            return render(request, 'main/orderdone.html', {'error':'Your cart is empty'})
        else:
            for item in request_cart:
                createorder(item.book, item.user)
            request_cart.delete()
            return render(request, 'main/orderdone.html', {'error':'Your order has been placed!'})
    else:
        return redirect('home')


def createorder(product, user):
    order_item = Book.objects.get(pk=product.id)
    order_user = User.objects.get(username=user.username)
    unique_id = ''
    for x in range(10):
        letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
        numbers = ['1','2','3','4','5','6','7','8','9','10']
        choice =  random.randint(1,5)
        if choice == 1:
            unique_id += letters[random.randint(0,25)]
        elif choice == 2:
            unique_id += numbers[random.randint(0,9)]
        elif choice == 3:
            unique_id += letters[random.randint(0,25)]
        elif choice == 4:
            unique_id += numbers[random.randint(0,9)]
        elif choice == 5:
            unique_id += letters[random.randint(0,25)]
    OrderItem.objects.create(user=order_user, book=order_item, order_id=unique_id)




models.py

from django.db import models
from django.contrib.auth.models import User
# Create your models here.

class Category(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = 'Category'
        verbose_name_plural = 'Categories'


class Book(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField()
    image = models.ImageField()
    price = models.IntegerField()
    category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)

    def __str__(self):
        return self.name

class OrderItem(models.Model):
    order_id = models.CharField(max_length=10)
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    book = models.ForeignKey(Book, on_delete=models.SET_NULL, null=True)

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

class CartItem(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    book = models.ForeignKey(Book, on_delete=models.SET_NULL, null=True)

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

urls.py

"""EBook URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.conf.urls.static import static
from django.conf import settings
from core import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('signup/', views.signupuser, name='signupuser'),
    path('login/', views.signinuser, name='signinuser'),
    path('logout/', views.logoutuser, name='logoutuser'),
    path('', views.home, name='home'),
    path('products/', views.showproducts, name='showproducts'),
    path('showcart/', views.showcart, name='showcart'),
    path('addtocartforhome/', views.addtocartforhome, name='addtocartforhome'),
    path('addtocartforproducts/', views.addtocartforproducts, name='addtocartforproducts'),
    path('removefromcartforcart/', views.removefromcartforcart, name='removefromcartforcart'),
    path('removefromcartforhome/', views.removefromcartforhome, name='removefromcartforhome'),
    path('removefromcartforproducts/', views.removefromcartforproducts, name='removefromcartforproducts'),
    path('checkout/', views.makeorder, name='makeorder'),
]

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Upvotes: 0

Views: 46

Answers (2)

Krishna Singhal
Krishna Singhal

Reputation: 661

Instead of checking None replace by If

@login_required
def makeorder(request):
    if request.method == 'POST':
        request_cart = CartItem.objects.filter(user=request.user)
        if request_cart.exists():
            return render(request, 'main/orderdone.html', {'error':'Your cart is empty'})
        else:
            for item in request_cart:
                createorder(item.book, item.user)
            request_cart.delete()
            return render(request, 'main/orderdone.html', {'error':'Your order has been placed!'})
    else:
        return redirect('home')
```

Upvotes: 1

AKX
AKX

Reputation: 169041

request_cart = CartItem.objects.filter(user=request.user)

returns a QuerySet object which is never None.

You'll want to either

if not request_cart:

which will fetch any matching objects, then check whether there were any, or (if you didn't need request_cart next), the more efficient

if not CartItem.objects.filter(user=request.user).exists():
    ...

Beyond that, there's a bunch of other stuff that's not exactly correct:

  • You should not have global state such as that removederror variable. It will be non-deterministically (since you might be running in a multiprocess context) shared between requests, which is almost never what you want.
  • You should probably use (or at least customize) Django's built-in signup/login views instead of rolling your own.
  • You could do those fianlprice [sic] calculations directly in the database with an .aggregate() clause; beyond that, it would make sense to refactor that calculation (since you use it several times) into a function
  • You have plenty of if/else statements and bodies that repeat that could be simplified; for instance, home() has two return render()s, where you could just instead build a single context dictionary and only add the fianlprice to it if the user has logged in.
  • You should probably redirect to your login view instead of rendering the login template from other functions if the user is not logged in
    • But you should raise a "method not allowed" exception (or use class-based views that do that automatically) instead of allowing GET for POST-only views
  • You could use get_random_string() (which doesn't do exactly the same thing, but close enough) for order ID generation.
  • Your model verbose names should not be capitalized in general; Django can capitalize them when needed, but it won't un-capitalize them since it can't know whether you meant a proper noun that should always be capitalized.
  • You should have a separate Order model and OrderItems should have a ForeignKey to it, not an "ad-hoc" order_id that groups items in an order together.
  • It makes no sense for OrderItem's book and user foreign keys to be nullable.
  • It makes no sense for CartItem's book and user foreign keys to be nullable.

Upvotes: 2

Related Questions