How can I split orders by attributes in my API - python

I have a method that creates orders from the user's cart. For the courier to take an order from different restaurants, the order is divided into several. But at the moment I'm splitting the order just by the dish in the cart. How to make an order split by restaurants? that is, if a user orders 5 dishes from two different restaurants, then 2 orders were formed.
views.py
#action(methods=['PUT'], detail=False, url_path='current_customer_cart/add_to_order')
def add_cart_to_order(self, *args, **kwargs):
cart = Cart.objects.get(owner=self.request.user.customer)
cart_meals = CartMeal.objects.filter(cart=cart)
data = self.request.data
for cart_meal in cart_meals:
order = Order.objects.create(customer=self.request.user.customer,
cart_meal=cart_meal,
first_name=data['first_name'],
last_name=data['last_name'],
phone=data['phone'],
address=data.get('address', self.request.user.customer.home_address),
restaurant_address=cart_meal.meal.restaurant.address,
)
order.save()
return response.Response({"detail": "Order is created", "added": True})
models.py
class Order(models.Model):
"""User's order"""
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='related_orders')
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
phone = models.CharField(max_length=20)
cart_meal = models.ForeignKey(CartMeal, on_delete=models.CASCADE, null=True, blank=True)
restaurant_address = models.CharField(max_length=1024, null=True)
address = models.CharField(max_length=1024)
status = models.CharField(max_length=100, choices=STATUS_CHOICES, default=STATUS_NEW)
created_at = models.DateTimeField(auto_now=True)
delivered_at = models.DateTimeField(null=True, blank=True)
courier = models.OneToOneField('Courier', on_delete=models.SET_NULL, null=True, blank=True)
class CartMeal(models.Model):
"""Cart Meal"""
user = models.ForeignKey('Customer', on_delete=models.CASCADE)
cart = models.ForeignKey('Cart', verbose_name='Cart', on_delete=models.CASCADE, related_name='related_meals')
meal = models.ForeignKey(Meal, verbose_name='Meal', on_delete=models.CASCADE)
qty = models.IntegerField(default=1)
final_price = models.DecimalField(max_digits=9, decimal_places=2)
class Meal(models.Model):
"""Meal"""
title = models.CharField(max_length=255)
description = models.TextField(default='The description will be later')
price = models.DecimalField(max_digits=9, decimal_places=2)
discount = models.IntegerField(default=0)
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, null=True)
slug = models.SlugField(unique=True)
class Restaurant(models.Model):
"""Restaurant"""
name = models.CharField(max_length=255)
slug = models.SlugField(unique=True)
address = models.CharField(max_length=1024)
owner = models.ForeignKey('Restaurateur', on_delete=models.CASCADE, null=True)
meals = models.ManyToManyField('Meal', related_name='related_restaurant', blank=True)
How can I do this, please help me

You can group your meals with respect to resturants.
import itertools
from core.models import CartMeal, Order
for restaurant, cart_meals in itertools.groupby(CartMeal.objects.order_by('meal__restaurant'), lambda s: s.meal.restaurant):
order = Order.objects.create(
customer=self.request.user.customer,
first_name=data['first_name'],
last_name=data['last_name'],
phone=data['phone'],
address=data.get('address', self.request.user.customer.home_address),
restaurant_address=cart_meal.meal.restaurant.address,
)
order.cart_meal.set([cart_meal for cart_meal in cart_meals])
Ref: The answer is formulated by taking help from following answer.
https://stackoverflow.com/a/57897654/14005534

Related

How to select multiple items with multiple quantities in django rest framework?

Models.py
class BaseModel(models.Model):
branch = models.ForeignKey(Branch, on_delete=models.PROTECT, blank=True, null=True)
company = models.ForeignKey(
Company, on_delete=models.PROTECT, blank=True, null=True
)
class Meta:
abstract = True
class MealMenu(BaseModel):
employee = models.ForeignKey(
Employee, on_delete=models.PROTECT, null=True, blank=True
)
item_name = models.CharField(max_length=50, null=True, blank=True)
quantity = models.PositiveIntegerField()
price = models.FloatField()
def __str__(self):
return f"{self.item_name} {self.price}"
class MealOrder(BaseModel):
RECEIVED = "Received"
PENDING = "Pending"
REJECTED = "Rejected"
MEAL_CHOICES = (
("Breakfast", "Breakfast"),
("Lunch", "Lunch"),
("Dinner", "Dinner"),
)
STATUS_CHOICES = (
(RECEIVED, "Received"),
(PENDING, "Pending"),
(REJECTED, "Rejected"),
)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, null=False)
total_items = models.IntegerField(null=True, default=0)
total_amounts = models.FloatField(default=0.0)
menu = models.ForeignKey(MealMenu, on_delete=models.PROTECT)
quantity = models.PositiveIntegerField(default=1, blank=False)
meal_time = models.CharField(max_length=25, choices=MEAL_CHOICES)
employee = models.ForeignKey(Employee, on_delete=models.PROTECT)
date = models.DateField(auto_now=True)
status = models.CharField(max_length=25, choices=STATUS_CHOICES, default=PENDING)
I have two models. In First Model i have created a menu item_name,price and quantity.
In MealOrder i have foreign key MealMenu Model and created quantity field separately.
I want to select multiple items with their multiple quantities. But i can't understand the scenario.
So you could have a separate model to handle the quantity for different items in an order.
Like this:
class MealOrderItem(BaseModel):
order = models.ForeignKey(
MealOrder, on_delete=models.PROTECT, null=True, blank=True
)
quantity = models.PositiveIntegerField()
meal = ForeignKey(
MealMenu, on_delete=models.PROTECT, null=True, blank=True
)
This will help you create multiple meal menu selections for an order with each having its own quantity.

Django - Get user with highest bid

I need to get the user who placed the highest bid for the listing on an auction site.
models.py:
class Listing(models.Model):
class Category(models.TextChoices):
BOOKS = 'Books'
SPORTS = 'Sports'
DEATHLY_HALLOWS = 'Deathly Hallows'
CLOTHING = 'Clothing'
WANDS = 'Wands'
JEWELRY = 'Jewelry'
title = models.CharField(max_length=64)
description = models.TextField(max_length=320)
starting_bid = models.DecimalField(max_digits=10, decimal_places=2, default=0)
current_price = models.DecimalField(max_digits=10, decimal_places=2, default=0 )
img_url = models.URLField(blank=True)
category = models.CharField(choices=Category.choices, max_length=64, blank=True)
is_closed = models.BooleanField(default=False)
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
winner = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name="Winner")
def __str__(self):
return f"{self.title}"
class Bid(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, default=1)
bid = models.DecimalField(max_digits=10, decimal_places=2)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, related_name="Bidder")
views.py:
def listing(request, listing_id):
highest_bid = Bid.objects.aggregate(Max('bid'))
winner = highest_bid.user
print(winner)
Returns the error: 'dict' object has no attribute 'user'.
How can I get the user from the maximum bid placed on the listing?
Order the Bids by the bid:
def listing(request, listing_id):
highest_bid = Bid.objects.latest('bid')
winner = highest_bid.user
print(winner)
# …

How to filter Many to Many field in django admin page using a foreign key value?

I am trying to filter my many to many variation fields with respect to the product. means, I only want the variations related to the current product to show in the admin page. now its showing all the variations available for every product.
I added formfield_for_manytomany() function to my admin.py but how can I get the current product(id) in the cart or order to filter the variations?
most of the questions in stack overflow Is based on the current user, which is easy to get? but how should I get the specific product(id) that is opened in the admin panel.
admin.py
from django.contrib import admin
from .models import *
from products.models import Variation
class CartAdmin(admin.ModelAdmin):
list_display = ('cart_id', 'date_created')
class CartItemAdmin(admin.ModelAdmin):
list_display = ('user','cart', 'product', 'quantity','is_active')
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name == "variation":
product = Products.objects.get(id='??') # how I get the current product in the cart or order
kwargs["queryset"] = Variation.objects.filter(product=product.id)
return super().formfield_for_manytomany(db_field, request, **kwargs)
admin.site.register(Cart, CartAdmin)
admin.site.register(CartItem, CartItemAdmin)
CartItem Model
class CartItem(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=True)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE, null=True)
product = models.ForeignKey(Products, on_delete=models.CASCADE)
variation = models.ManyToManyField(Variation, blank=True)
quantity = models.IntegerField()
is_active = models.BooleanField(default=True)
created_date = models.DateTimeField(auto_now_add=True)
def item_total(self):
return self.product.price * self.quantity
def __str__(self):
return self.product.name
Product and Variation Model
class Products(models.Model):
name = models.CharField(max_length=50, unique=True)
slug = AutoSlugField(populate_from='name', max_length=100, unique=True)
isbn = models.CharField(max_length=20, unique=True, blank=True, null=True)
sub_category = models.ForeignKey(SubCategory, on_delete=models.CASCADE)
language = models.ForeignKey(Language, on_delete=models.SET_NULL, null=True)
author = models.CharField(max_length=100)
Publisher = models.CharField(max_length=100, blank=True, default=None)
release_date = models.DateField(blank=True, null=True, default=None)
price = models.IntegerField(default=None)
stock = models.IntegerField(default=None)
is_available = models.BooleanField(default=True)
cover_image = models.ImageField(upload_to='images/products')
image1 = models.ImageField(upload_to='images/products', blank=True, default=None, null=True)
image2 = models.ImageField(upload_to='images/products', blank=True, default=None, null=True)
image3 = models.ImageField(upload_to='images/products', blank=True, default=None, null=True)
description = models.TextField(max_length=2000, blank=True, default=None)
create_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
number_of_pages = models.IntegerField(blank=True, null=True)
weight = models.IntegerField(blank=True, null=True)
width = models.IntegerField(blank=True, null=True)
height = models.IntegerField(blank=True, null=True)
spine_width = models.IntegerField(blank=True, null=True)
class Meta:
verbose_name = 'Product'
verbose_name_plural = 'Products'
def get_url(self):
return reverse('product-view', args=[self.slug])
def __str__(self):
return self.name
class Variation(models.Model):
product = models.ForeignKey(Products, on_delete=models.CASCADE)
variation_category = models.CharField(max_length=100, choices=variation_category_choice)
variation_value = models.CharField(max_length=100, choices=variation_value_choice)
is_available = models.BooleanField(default=True)
date_added = models.DateTimeField(auto_now_add=True)
objects = VariationManager()
def __str__(self):
return self.variation_value

Django ManyToMany field object automatically pre-fills

I have an PaypalOrder model that is created when someone orders from a website, and it has a ManyToManyField that connects it to multiple OrderItems. Whenever I create a PaypalOrder, it automatically lists every OrderItem that exists in the django admin panel. How do I only list the objects that I set it to connect to?
my models.py:
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.IntegerField()
is_a_subscription = models.BooleanField(default=False)
subscription = models.ForeignKey('Subscription', on_delete=models.CASCADE, null=True, blank=True)
class PaypalOrder(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
items_and_quantities = models.ManyToManyField(OrderItem, blank=True, related_name="paypalorder")
full_name = models.CharField(max_length=100)
address1 = models.CharField(max_length=250)
address2 = models.CharField(max_length=250, null=True, blank=True)
city = models.CharField(max_length=100)
zipcode = models.CharField(max_length=20)
created_at = models.DateTimeField(auto_now_add=True)
total_paid = models.DecimalField(max_digits=10, decimal_places=2)
order_id = models.CharField(max_length=100, null=True, blank=True)
subscription_id = models.CharField(max_length=100, null=True, blank=True)
email=models.CharField(max_length=100, null=True)
country_code = models.CharField(max_length=100)
state = models.CharField(max_length=50, null=True)
my view:
order = PaypalOrder.objects.create(
user = user,
full_name= resp['subscriber']['name']['given_name'] + " " + resp['subscriber']['name']['surname'],
email = resp['subscriber']['email_address'],
city = resp['subscriber']['shipping_address']['address']['admin_area_2'],
state = resp['subscriber']['shipping_address']['address']['admin_area_1'],
address1 = resp['subscriber']['shipping_address']['address']['address_line_1'],
address2 = addr2,
zipcode = resp['subscriber']['shipping_address']['address']['postal_code'],
country_code = resp['subscriber']['shipping_address']['address']['country_code'],
total_paid = resp['billing_info']['last_payment']['amount']['value'],
order_id = "product_ID: " + resp['id'],
subscription_id = resp['plan_id'],
created_at = resp['create_time'],
)
order.save()
subscription = Subscription.objects.create(user = request.user, paypal_order = order)
order.items_and_quantities.set(OrderItem.objects.filter(pk=100))
I believe that you are being tricked by the Front end; look again; even when the Django admin displays all the items, only those related to PayPal orders are highlighted.

How can i update a specific field using foreign key relationship

I want to update a field which is called level. My relation is like this. i am using django User model. Which is extended to Extended user like this below:-
class ExtendedUser(models.Model):
levels_fields = (
("NEW SELLER", "NEW SELLER"),
("LEVEL1", "LEVEL1"),
("LEVEL 2", "LEVEL 2"),
("LEVEL 3", "LEVEL 3")
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
email = models.EmailField(null=True, unique=True)
contact_no = models.CharField(max_length=15, null=True)
profile_picture = models.ImageField(upload_to="images/", null=True)
country = models.ForeignKey(Country, on_delete=models.CASCADE, null=True)
city = models.ForeignKey(City, on_delete=models.CASCADE, null=True)
level = models.CharField(max_length = 120, null=True, blank=True, choices=levels_fields, default="NEW SELLER")
I have a field call "Level" which is full of choices. Now i have a model named Checkout
This is the checkout model :-
class Checkout(models.Model):
ORDER_CHOICES = (
("ACTIVE", "ACTIVE"),
("LATE", "LATE"),
("DELIVERED", "DELIVERED"),
("CANCELLED", "CANCELLED"),
)
user = models.ForeignKey(User, on_delete=models.CASCADE)
seller = models.ForeignKey(
User, on_delete=models.CASCADE, null=True, related_name='seller')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now_add=True)
first_name = models.CharField(max_length=120)
last_name = models.CharField(max_length=120)
package = models.ForeignKey(OfferManager, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField(default=0)
price = models.DecimalField(decimal_places=2, max_digits=10, default=0.00)
total = models.DecimalField(decimal_places=2, max_digits=10, default=0.00)
grand_total = models.DecimalField(
decimal_places=2, max_digits=10, default=0.00, null=True)
paid = models.BooleanField(default=False)
due_date = models.DateField(null=True)
order_status = models.CharField(max_length=200, choices=ORDER_CHOICES, default="ACTIVE")
is_complete = models.BooleanField(default=False, null=True)
I have another model which is called SellerSubmit and the checkout is the foreign key here. Here is the model :-
class SellerSubmit(models.Model):
checkout = models.ForeignKey(Checkout, on_delete=models.CASCADE, related_name="checkout")
file_field = models.FileField(upload_to="files/", null=True)
submit_date = models.DateField(auto_now_add=True, null=True)
def __str__(self):
return str(self.id)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
Now when a seller post in the SUbmitModel it will update the level to LEVEL1. How can do it,
This is what i tried :-
def sellerSubmitView(request, pk):
form = SellerSubmitForm()
if request.method == "POST":
file_field = request.FILES.get("file_field")
try:
checkout = Checkout.objects.get(id=pk)
# print(file_field)
except:
return redirect("manage-order")
else:
SellerSubmit.objects.create(checkout=checkout, file_field=file_field)
checkout.order_status ="DELIVERED"
chk = checkout.is_complete = True
l = Checkout.objects.filter(is_complete = True).filter(seller=request.user).count()
print("Count:" + str(l))
if l > 5:
out = checkout.seller.extendeduser.level = "LEVEL1"
print(out)
checkout.save()
print(chk)
checkout.save()
return redirect("manage-order")
args = {
"form": form,
"checkout_id": pk,
}
return render(request, "wasekPart/sellerSubmit.html", args)
checkout.seller.extendeduser.level = "LEVEL1"
checkout.seller.extendeduser.save()
This should solve your problem
out = checkout.seller.extendeduser.level = "LEVEL1"
print(out)
checkout.seller.extendeduser.save()
checkout.save()
It's my bad that didn't notice ExtendedUser is not extended from User.
Please let me know if it's worked or not

Categories

Resources