Reputation: 259
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
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
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:
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.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 functionif/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.get_random_string()
(which doesn't do exactly the same thing, but close enough) for order ID generation.Order
model and OrderItem
s should have a ForeignKey
to it, not an "ad-hoc" order_id
that groups items in an order together.OrderItem
's book and user foreign keys to be nullable.CartItem
's book and user foreign keys to be nullable.Upvotes: 2