In a Django project, i have two apps; ecommerce and users. Ecommerce app has situation where logged in users are expected to be customers and they can add to cart. Non logged in users can as well add to cart. In the users app, new users are to register, logged in and be redirected to the store page(store.html).
The new registered users does not have this customer instance I guess, reason I'm getting the User has no customer RelatedObjectDoesNotExist.
How can I integrate this new registered users to have this customer instance so they can be redirected to the store page? or give a condition where not all users must have a customer instance.
(ecommerce app)
models.py:
class Customer(models.Model):
user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200)
def __str__(self):
"""String for representing a model object"""
return self.name
class Product(models.Model):
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits=7, decimal_places=2)
digital = models.BooleanField(default=False,null=True, blank=True)
image = models.ImageField(null=True, blank=True)
def __str__(self):
"""String for representing a model object"""
return self.name
#property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True, blank=True)
date_ordered = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False, null=True, blank=True)
transaction_id = models.CharField(max_length=100, null=True)
def __str__(self):
"""String for representing a model object"""
return str(self.id)
#property
def shipping(self):
shipping = False
orderitems = self.orderitem_set.all()
for i in orderitems:
if i.product.digital == False:
shipping = True
return shipping
#property
def get_cart_total(self):
orderitems = self.orderitem_set.all()
total = sum([item.get_total for item in orderitems])
return total
#property
def get_cart_items(self):
orderitems = self.orderitem_set.all()
total = sum([item.quantity for item in orderitems])
return total
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
quantity = models.IntegerField(default=0, null=True, blank=True)
date_added = models.DateTimeField(auto_now_add=True)
#property
def get_total(self):
total = self.product.price * self.quantity
return total
class ShippingAddress(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
address = models.CharField(max_length=200, null=False)
city = models.CharField(max_length=200, null=False)
state = models.CharField(max_length=200, null=False)
zipcode = models.CharField(max_length=200, null=False)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
"""String for representing a model object"""
return self.address
utils.py
(it is being imported to views.py and then rendered to the store.html template):
def cartData(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created = Order.objects.get_or_create(customer=customer, complete=False)
items = order.orderitem_set.all()
cartItems = order.get_cart_items
else:
cookieData = cookieCart(request)
cartItems = cookieData['cartItems']
order = cookieData['order']
items = cookieData['items']
return {'cartItems':cartItems ,'order':order, 'items':items}
views.py
def store(request):
data = cartData(request)
cartItems = data["cartItems"]
products = Product.objects.all()
#context = {'products': products }
context = { "products": products,'cartItems':cartItems}
return render(request, 'ecommerce/store.html', context)
This the main.html snippet template where both apps(ecommerce app and users app) inherits from.
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="{% url 'store' %}">Ecommerce<span class="sr-only">(current)</span></a>
</li>
</ul>
<div class="form-inline my-2 my-lg-0">
{% if request.user.is_authenticated %}
Logout
{% else %}
Login
Register
{% endif %}
(users app) below:
it has no models.py
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class UserRegistrationForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
views.py
from django.shortcuts import render, redirect
#from django.contrib.auth.forms import UserCreationForm
from django.contrib import messages
from .forms import UserRegistrationForm
def register(request):
if request.method == "POST":
form = UserRegistrationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'{username}, your account has been created! You are able to log in')
return redirect('login')
else:
form = UserRegistrationForm()
return render(request, 'users/register.html', {'form':form})
settings.py
LOGIN_REDIRECT_URL = 'store' #redirecting to store page after a successful login session configuration.
Yo must create the Customer with the User you are trying to access the store.
Related
Hello i want to fetch a specific field to a variable
For that I have Order model:
class Order(models.Model):
product = models.ForeignKey(
Product, on_delete=models.CASCADE, related_name="product")
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
fname = models.CharField(max_length=100, null=True)
address = models.CharField(max_length=1000, null=True)
phone = models.CharField(max_length=12, null=True)
price = models.IntegerField()
date = models.DateField(datetime.datetime.today, null=True)
status = models.ForeignKey(
Status, on_delete=models.CASCADE, blank=True, null=True)
payment_method = models.ForeignKey(
PaymentMethod, on_delete=models.CASCADE, blank=True, null=True)
total = models.IntegerField(null=True)
Here I want to fetch total field in a variable.But I am new for that reason I am really confused about this topic
There is another method you can use. You would have to define a method or property for the field and then call it in your templates.
models.py
class Order(models.Model):
total = models.IntegerField(null=True)
#property
def get_total(self):
return self.total
views.py
from django.shortcuts import render
from .models import *
def Index(request):
Orders = Order.objects.all()
context = {"Orders":Orders}
return render(request, "template/page.html", context)
page.html
{% for order in Orders %}
{{order.get_total}}
# You can do the same to other field to get them
{% endfor %}
Its quite easy. Since you have defined your models already. All you have to do is to use it in your view.py and then in your templates. Exaple is the below:
view.py
from django.shortcuts import render
from .models import *
def Index(request):
Orders = Order.objects.all()
context = {"Orders":Orders}
return render(request, "template/page.html", context)
page.html
{% for order in Orders %}
{{order.total}}
{{order.price}}
# You can do the same to other field to get them
{% endfor %}
I am trying to create a django application to keep track of a product(product stock application).whenever I try to add new product ,I cannot add more than one product in the same category. It gives UNIQUE constraint failed error .
I want to add multiple products in same category.
models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=100, blank=True, null=True)
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=100)
slug = models.CharField(max_length=100)
price = models.DecimalField(max_digits=6, decimal_places=2)
quantity = models.IntegerField(null=True, blank=True)
category = models.ForeignKey(
Category, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Stock(models.Model):
sold_quantity = models.IntegerField(null=True, blank=True)
product = models.ForeignKey(Product, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.product.name
Edit:
Views
def createProduct(request):
form = AddProductForm()
if request.method == 'POST':
form = AddProductForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
contex = {'form': form}
return render(request, 'stockmgmt/add_products.html', contex)
Forms.py
class AddProductForm(ModelForm):
class Meta:
model = Product
fields = '__all__'
Error Message
I am building an online shop to sell music. I have a problem with my ProfileView, where I want to show the customer his finished orders with the files that he has purchased.
Here are my models:
class Product(models.Model):
title = models.CharField(max_length=50)
slug = models.SlugField()
description = models.TextField()
image = models.ImageField(upload_to='product_images')
file = models.FileField(upload_to='product_files')
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=False)
soundkit = models.BooleanField(default=False)
licence_variation = models.ManyToManyField(LicenceVariation)
def get_absolute_url(self):
return reverse("cart:product-detail", kwargs={'slug': self.slug})
def get_delete_url(self):
return reverse('staff:product-delete', kwargs={'pk': self.pk})
def is_soundkit(self):
return self.soundkit
def __str__(self):
return self.title
def get_update_url(self):
return reverse("staff:product-update", kwargs={'pk': self.pk})
class OrderItem(models.Model):
order = models.ForeignKey("Order", related_name='items', on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
licence_variation = models.ForeignKey(LicenceVariation, on_delete=models.CASCADE)
def __str__(self):
return self.product.title
def get_raw_total_item_price(self):
return self.licence_variation.price
def get_total_item_price(self):
price = self.get_raw_total_item_price()
return "{:.2f}".format(price / 100)
class Order(models.Model):
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)
start_date = models.DateTimeField(auto_now_add=True)
ordered_date = models.DateTimeField(blank=True, null=True)
ordered = models.BooleanField(default=False)
billing_address = models.ForeignKey(Address, related_name='billing_address', blank=True, null=True,
on_delete=models.SET_NULL)
shipping_address = models.ForeignKey(Address, related_name='shipping_address', blank=True, null=True,
on_delete=models.SET_NULL)
def __str__(self):
return self.reference_number
#property
def reference_number(self):
return f"Order-{self.pk}"
def get_raw_subtotal(self):
total = 0
for order_item in self.items.all():
total += order_item.get_raw_total_item_price()
return total
def get_subtotal(self):
subtotal = self.get_raw_subtotal()
return "{:.2f}".format(subtotal / 100)
def get_raw_total(self):
subtotal = self.get_raw_subtotal()
return subtotal
def get_total(self):
total = self.get_raw_total()
return "{:.2f}".format(total / 100)
def get_order_item_set(self):
return self.items.all()
Here is my Profile View
class ProfileView(LoginRequiredMixin, generic.TemplateView):
template_name = 'profile.html'
def get_context_data(self, **kwargs):
context = super(ProfileView, self).get_context_data(**kwargs)
context.update({
"orders": Order.objects.filter(user=self.request.user, ordered=True),
'order_items': OrderItem.objects.all
})
return context
Obviously it is displaying all the OrderItems in my template, because I use the objects.all method, but I want to filter it, so that it only displays the OrderItems which belong to the correct order.
Can anybody help me with the correct way of filtering the OrderItems?
Thanks a lot
In the template, you could group the order items by order using the FK relation:
{% for order in orders %}
<h3>{{ order }}</h3>
{% for item in order.items.all %}
<p>{{ item }}</p>
{% endfor %}
{% endfor %}
But if you just want an ordered list of all the items by order, you could probably do
OrderItem.objects.all().order_by('order')
I have a shopping cart and I want to add an object to that shopping cart. There is a button which I press and when that happens I want the request to go through.
This is what I want to do in the POST request (When Button Is Pressed):
Check for Item with the same id as the product I pressed.
Create a CartItem with the same Item as the one I checked for above.
Add that cart item to my shopping cart linked to my profile. (Not started work yet)
Models:
class Item(models.Model):
name = models.CharField(max_length=100, null=True)
info = models.CharField(max_length=100, null=True)
price = models.IntegerField(default=0, null=True)
discount = models.CharField(max_length=100, null=True, blank=True)
discountPrice = models.IntegerField(default=0, null=True)
inStock = models.BooleanField(default=False)
imagefield = models.ImageField()
reviews = models.ManyToManyField(Review, blank=True, related_name="itemreview")
class Meta:
verbose_name_plural = 'Items'
def __str__(self):
return "{name}".format(name=self.name)
class CartItem(models.Model):
item = models.ForeignKey(Item, blank=True, related_name="CartItem", on_delete=models.CASCADE)
quantity = models.IntegerField(default=0, null=True)
price = models.IntegerField(default=0, null=True)
class Meta:
verbose_name_plural = 'Cart Items'
def __str__(self):
return self.item.name
def get_total_item_price(self):
return self.quantity * self.item.price
class ShoppingCart(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
items = models.ManyToManyField(CartItem, blank=True, related_name="orderitem")
class Meta:
verbose_name_plural = 'Shopping Carts'
def __str__(self):
return self.user.username
def get_total(self):
total = 0
for cart_item in self.items.all():
total += cart_item.get_total_item_price()
return total
#receiver(post_save, sender=User)
def create_user_data(sender, update_fields, created, instance, **kwargs):
if created:
user = instance
profile = ShoppingCart.objects.create(user=user)
Views and urls:
def add_to_cart(request, item_id):
if request.method == 'POST':
#create a cartitem
selectedItem = Item.objects.filter(id=item_id)
theQuantity = 1
thePrice = selectedItem.price
cartItem = CartItem(quantity=theQuantity, price=thePrice)
cartItem.save()
cartItem.item.add(selectedItem)
#add that cartitem to the cart
return redirect('landing-page')
urlpatterns = [
path('', views.landingPage, name='landing-page'),
path('product/<int:itemID>', views.singleProduct, name='singleProduct'),
path('cart', views.shoppingCart, name='cart'),
path('add-to-cart/<int:item_id>', views.add_to_cart, name="addToCart"),
path('quantity-up/<int:cartitem_id>', views.change_quantity_up, name="quantity-upp"),
path('quantity-down/<int:cartitem_id>', views.change_quantity_down, name="quantity-down"),
]
This is how I made the request and inside the html its a button with an a href="{% url 'addToCart' item.id %}"
html:
<a class="button primary-btn" href="{% url 'addToCart' item.id %}">Add to Cart</a>
I would like to display only the pictures uploaded by the creator (user) on their individual profiles.
How would I alter my code to display that?
Thank you!
models.py:
class Photo(models.Model):
creator = models.ForeignKey(MyUser, null=False, blank=False)
category = models.ForeignKey("Category", default=1, null=True, blank=True)
title = models.CharField(max_length=30, null=True, blank=True)
description = models.TextField(max_length=120, null=True, blank=True)
image = models.ImageField(upload_to='user/photos/', null=True, blank=True)
slug = models.SlugField(null=False, blank=False)
active = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False, null=True)
updated = models.DateTimeField(auto_now_add=False, auto_now=True, null=True)
class Meta:
unique_together = ('slug', 'category')
ordering = ['-timestamp']
def __unicode__(self):
return "%s" %(self.creator)
def get_image_url(self):
return "%s/%s" %(settings.MEDIA_URL, self.image)
def get_absolute_url(self):
return "%s/%s" %(self.creator, self.slug)
views.py:
#login_required
def account_home(request, username):
try:
u = MyUser.objects.get(username=username)
except:
u = None
photo_set = Photo.objects.all()
context = {
"photo_set": photo_set,
"notifications": notifications,
"transactions": transactions
}
return render(request, "accounts/account_home.html", context)
.html:
{% for photo in photo_set %}
<img src="{{ photo.get_image_url }}" class='img-responsive'>
<hr/>
{% endfor %}
You have a ForeignKey to user, so you can just filter the photos by that:
photo_set = Photo.objects.filter(creator=u)
or even better use the reverse relationship:
photo_set = u.photo_set.all()
Also, never ever ever ever use a blank except statement in your code. The only exception you are expecting the get to raise is MyUser.DoesNotExist, so you should catch that only.