I want to make a simple function that collects the product ID and adds it to the user's shopping cart by clicking the "add to cart" button. I have the shopping cart table and product table created but am struggling to find the correct function to add the product to the cart. Anything helps I am very new to Python and Django and am looking for some help to get me on the right track.
class Cart(models.Model):
cart_id = models.Charfield(primary_key=True)
total = models.DecimalField(max_digits=9,decimal_places=2)
quantity = models.IntegerField()
products = models.ManyToManyField(Product)
class Product(models.Model):
prod_id = models.CharField(max_length=15, null=True)
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits=10,decimal_places=2)
description = models.TextField(max_length=1000)
def cart_add(request, prod_id):
item = Product.objects.get(pk=prod_id)
I know this isn't much to work with but anything helps, I am just looking for some help with creating the add to cart function
You need to have a relation between Cart model and User model, So that you can save product to respective user's cart.
Moreover a good approach would be adding another model named CartItem and keeping the product information in that model instead of storing product directly to Cart model. This is because when we add a product to cart, we might need to save and later update extra information about the product for example 'quantity'.
class Cart(models.Model):
cart_id = models.Charfield(primary_key=True)
total = models.DecimalField(max_digits=9,decimal_places=2)
quantity = models.IntegerField()
user = models.OneToOneField(User)
class CartItem(models.Model):
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
product_quantity = models.IntegerField(default=0)
user = models.OneToOneField(User)
So in this case, all you need to do is create a new CartItem object in add to cart view.:
def cart_add(request, prod_id, qty):
item = Product.objects.get(pk=prod_id)
cart_obj = Cart.objects.get(user=request.user)
CartItem.objects.create(cart=cart_obj, product=item, product_quantity=qty)
Hope this helps :)
You need a relation between Cart* and User
class Cart(models.Model):
cart_id = models.Charfield(primary_key=True)
total = models.DecimalField(max_digits=9,decimal_places=2)
quantity = models.IntegerField()
products = models.ManyToManyField(Product)
user = models.OneToOneField(User)
class Product(models.Model):
prod_id = models.CharField(max_length=15, null=True)
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits=10,decimal_places=2)
description = models.TextField(max_length=1000)
def cart_add(request, prod_id):
item = Product.objects.get(pk=prod_id)
request.user.cart.add(item)
Related
I have three models Product, Order, and OrderItem
Once someone places an order I don't want the product object associated with the orderitem model on the receipt to change or get deleted if I were to delete or update the product model. How to achieve this?
#model
class Product(models.Model):
price = models.DecimalField()
class Order(models.Model):
buyer = models.ForeignKey(Buyer, on_delete=models.SET_NULL)
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL)
order = models.ForeignKey(Order, on_delete=models.SET_NULL)
#view
#login_required
def receipt(request):
orderitems = OrderItem.objects.filter(order__buyer__user=request.user)
don't make it a ForeignKey in OrderItem for price use an integer field and provide the value for it in your view.
I'm trying to make a auctions website for a project and I can't get to connect 2 models, I have in my models.py file, a model for the auction listings (Alisting) and a model for the bids that are made (Bid).
-The Alisting model has 4 fields: title CharField for the title of the auction, sta_bid for a starting bid, las_bid ForeignKey to Bid model, and user ForeignKey to User model.
-The Bid model has 3 fields: user ForeignKey to User for the user that makes the bid, listing a ForeignKey to Alisting, and new_bid IntegerField for the latest bid.
class User(AbstractUser):
pass
class Alisting(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=32)
sta_bid = models.IntegerField()
las_bid = models.ForeignKey(Bid, on_delete=models.CASCADE)
class Bid(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
listing = models.ForeignKey(Alisting, on_delete=models.CASCADE)
new_bid = models.IntegerField()
How could I connect these 2 models so that when I create a listing I can create new bids to this listing from the other model. Because later in the project I'll have to allow users to modify bids from other user's listings.
Thank you in advance!
I suggest you this design:
class User(AbstractUser):
pass
class Alisting(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=32)
sta_bid = models.IntegerField()
#property
def last_bid(self):
# You don' t need to update last_bid, since is obtained dynamically with this property
if self.bid_set.objects.count() > 0:
return self.bid_set.order('-creation_date')[0]
return None
class Bid(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
listing = models.ForeignKey(Alisting, on_delete=models.CASCADE)
new_bid = models.IntegerField()
creation_date = models.DateTimeField(auto_now_add=True) # Stores the date when the bid was created
You can access the last bid with:
listing = Alisting.objects.all()[0]
print(listing.last_bid)
You can access the bids of a listing with:
listing = Alisting.objects.all()[0]
listings.bid_set.objects.all()
# Or to get only bids of a given user
listings.bid_set.objects.filter(user=User.objects.all()[0])
You can access bids of an user with:
user = User.objects.all()[0]
user.bid_set.objects.all()
# Or to get only bids of an user with a given listing
user.bid_set.objects.filter(listing=Alisting.objects.all()[0])
You can access listings created by a given user with:
user = User.objects.all()[0]
user.alisting_set.objects.all()
I'm trying to save some data through a form and I'm trying to use a
FormSet. The data to be saved is an invoice which contains a Product
and it's Details.
I was able to render everything in one place (this wasn't simple) and
to save the invoice and the detail to the DB. For some reason, the
Detail table is saving the Product ID but not the Invoice ID. This is
my models.py:
class Detail(models.Model):
invoice = models.ForeignKey(Invoice, null=True, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField(default=1)
subtotal = models.DecimalField(max_digits=9 , null=True, decimal_places=2)
class Invoice(models.Model):
date = models.DateField(default=datetime.date.today)
number = models.CharField(max_length=10, default='0000000000')
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
products = models.ManyToManyField(Product, null=True, blank=True)
total = models.DecimalField(max_digits=9 , null=True, decimal_places=2)
And this is my views.py:
def invoice_new(request):
DetailFormSet = formset_factory(DetailForm, extra=2)
if request.method == "POST":
invoice_form = InvoiceForm(request.POST)
detail_formset = DetailFormSet(request.POST)
if invoice_form.is_valid() and detail_formset.is_valid():
invoice = invoice_form.save(commit=False)
invoice.save()
for details in detail_formset:
details.save()
return redirect('invoice_detail', pk=invoice.pk)
else:
return redirect('invoice_error')
else:
invoice_form = InvoiceForm()
detail_formset=formset_factory(DetailForm, extra=2)
return render(request, 'invoice/invoice_edit.html', {'invoice_form': invoice_form, 'detail_form': detail_formset} )
I tried adding this to the body of the for loop:
details.invoice_id = invoice.pk
invoice.id prints OK, but it won't save the number to the DB. I don't see how it picks up product id just fine but not invoice's.
I'm adding forms.py
class InvoiceForm(forms.ModelForm):
class Meta:
model = Invoice
fields = ['date','number','supplier']
total = forms.DecimalField(disabled=True)
class DetailForm(forms.ModelForm):
class Meta:
model = Detail
fields = ['product','quantity']
You can set the invoice id before saving the form.
if invoice_form.is_valid() and detail_formset.is_valid():
invoice = invoice_form.save(commit=False)
invoice.save()
for details in detail_formset:
details.invoice = invoice # Set the invoice
details.save()
the code did not return all of the item's name based on employee..? how to solve this probem? did the models wrong? or the query?
MODELS.PY
class Employee(models.Model):
name = models.CharField(max_length=100)
telephone_number = models.CharField(max_length=20)
address = models.TextField()
email = models.EmailField()
class Item(models.Model):
code = models.CharField(max_length=4)
name = models.CharField(max_length=100)
kind = models.CharField(max_length=100)
description = models.TextField()
class Inventory(models.Model):
employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
def get_absolute_url(self):
return reverse('inventaris-detail', kwargs={'pk': self.pk})
VIEWS.PY
how can i get all of the employee's item ?
query_set = Inventory.objects.all()
for query in query_set:
output.append([
query.employee.name,
query.item.name
])
i need something like query.employee.items_set.all() .. ?
You want to get all of the items from an employee? The following should achieve that:
employee = Employee.objects.all()[0] # Just get a random employee, you can do this with more employees too if you want
employees_items = [inventory.item for inventory in employee.inventory_set.all()]
Your code does not logically make a lot of sense though, to be honest. Most likely, there should be a field on a Item class which is a FK to Inventory. Your item class should probably be:
class Item(models.Model):
code = models.CharField(max_length=4)
name = models.CharField(max_length=100)
kind = models.CharField(max_length=100)
description = models.TextField()
inventory = models.ForeignKey(Inventory, on_delete=models.CASCADE)
(Of course this will not work since Inventory is defined after this class, but you can just put Inventory above it or use one of the other many methods to solve this problem)
Good luck!
I want to make an API End Point so the user can get a list of the users in his city ordered by their post reviews
I have defined a method in the post model to calculate the total review (up vote and down vote), I'm imagining that the solution can be realized in the following path but I'm not entirely sure groupBy post_owner in the post and orderBy sum(count_reactions()), but I don't know how to do it in django
Post Model
class Post(models.Model):
title = models.TextField(max_length=255, default='Title')
post_owner = models.ForeignKey(MyUser, on_delete=models.CASCADE)
description = models.TextField(max_length=255)
city = models.ForeignKey(City, related_name='location', on_delete=models.CASCADE)
longitude = models.CharField(max_length=255)
image = models.CharField(max_length=255,
default='https://www.eltis.org/sites/default/files/styles/web_quality/public/default_images/photo_default_2.png')
latitude = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
def count_reactions(self):
likes_count = Reaction.objects.filter(post=self.id, is_like=True).count()
dislikes_count = Reaction.objects.filter(post=self.id, is_like=False).count()
return likes_count - dislikes_count
def owner(self):
return self.post_owner
MyUser Model
class MyUser(AbstractUser):
phone_number = models.BigIntegerField(blank=False, unique=True)
city = models.ForeignKey(City, related_name='city', on_delete=models.CASCADE)
address = models.CharField(max_length=255)
def owner(self):
return self
Reaction Model
class Reaction(models.Model):
reaction_owner = models.ForeignKey(MyUser, on_delete=models.CASCADE)
post = models.ForeignKey(Post, related_name='reactions', on_delete=models.CASCADE)
is_like = models.BooleanField(null=False)
def owner(self):
return self.reaction_owner
The expected result is to get the ordered list of the users by their posts reviews but only the users in the same city (city field in MyUser model)
You can put it all into one query.
Depending on where your Reaction naming the query should look something like this:
# Filter for the city you want
users = MyUser.objects.filter(city=your_city_obj)
# Then doing the calculations
users = users.annotate(rank_point=(Count('post__reactions', filter=Q(post__reactions__is_like=True)) - (Count('post__reactions', filter=Q(post__reactions__is_like=False)))))
# And finaly, order the results
users = users.order_by('-rank_point')
The answer is Navid's answer but completing it with excluding the users with rank equal to zero and include also the limit
# Filter for the city you want
users = MyUser.objects.filter(city=your_city_obj)
# Then doing the calculations
users = users.annotate(rank_point=(Count('post__reactions', filter=Q(post__reactions__is_like=True)) - (Count('post__reactions', filter=Q(post__reactions__is_like=False))))).filter(rank_point__gt=0)
# And finaly, order the results
users = users.order_by('-rank_point')[:LIMIT]