django model ManyToManyField field join - django

--models.py--
class Products(models.Model):
name= models.CharField(max_length=120, unique=True)
slug = models.SlugField(unique=True)
price = models.IntegerField(default=100)
image1 = models.ImageField(upload_to='static/images/home', blank=True, null=True)
class Cart(models.Model):
user = models.ForeignKey(User, null=True, blank=True)
product = models.ManyToManyField(Products, blank=True)
--views.py--
#login_required
def cart(request):
try:
cart_user = Cart.objects.filter(user = request.user)
except:
cart_user = False
if cart_user != False:
j = Products.objects.filter(pk=Cart.objects.filter(user=request.user)) #Not getting results in j
now i want the list of products which is selected by user form Cart Model when he or she is logged in.
how to apply join in two models so that i get all the product list in 'p' variable which is in Cart.product model. Thanks

Shang Wang was right about model naming. Let's use those.
class Product(models.Model):
name= models.CharField(max_length=120, unique=True)
slug = models.SlugField(unique = True)
price = models.IntegerField(default=100)
image1 = models.ImageField(upload_to='static/images/home',blank=True,null=True)
class Cart(models.Model):
user = models.ForeignKey(User,null=True, blank=True)
products = models.ManyToManyField(Product, blank=True)
Now you can use filters like this.
products = Product.objects.filter(cart__user__id=1)
carts = Cart.objects.filter(articles__name__startswith="Something").distinct()

Related

Filter queryset of django inline formset based on attribute of through model

I have a basic restaurant inventory tracking app that allows the user to create ingredients, menus, and items on the menus. For each item on a given menu, the user can list the required ingredients for that item along with a quantity required per ingredient for that item.
Menu items have a many-to-many relationship with ingredients, and are connected via an "IngredientQuantity" through table.
Here are my models:
class Ingredient(models.Model):
GRAM = 'Grams'
OUNCE = 'Ounces'
PIECE = 'Pieces'
UNIT_CHOICES = [
('Grams', 'Grams'),
('Ounces', 'Ounces'),
('Pieces', 'Pieces')
]
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
name = models.CharField(max_length=200)
unitType = models.CharField(max_length=200, choices=UNIT_CHOICES, verbose_name='Unit')
unitCost = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='Unit Cost')
inventoryQuantity = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='Quantity')
def __str__(self):
return self.name + ' (' + self.unitType + ')'
def totalCost(self):
result = self.inventoryQuantity * self.unitCost
return "{:.0f}".format(result)
class Menu(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
name = models.CharField(max_length=200)
timeCreated = models.DateTimeField(auto_now_add=True)
timeUpdated = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.name)
class MenuItem(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits=10, decimal_places=2)
ingredients = models.ManyToManyField(Ingredient, through='IngredientQuantity')
menu = models.ForeignKey(Menu, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.name
def itemCost(self):
relevantIngredients = IngredientQuantity.objects.filter(menuItem=self)
cost = 0
for ingredient in relevantIngredients:
cost += (ingredient.ingredient.unitCost * ingredient.ingredientQuantity)
return cost
class IngredientQuantity(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
ingredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE)
menuItem = models.ForeignKey(MenuItem, on_delete=models.CASCADE)
ingredientQuantity = models.IntegerField(default=0)
def __str__(self):
return str(self.ingredient)
This is a multi-user app, so when a user creates a new item on a menu and adds ingredients to it, they should only have the option of choosing ingredients they have created, not those of other users. Here is my attempt to do that in my views:
def ItemUpdate(request, pk):
item = MenuItem.objects.get(id=pk)
user = request.user
IngredientQuantityFormset = inlineformset_factory(
MenuItem, IngredientQuantity, fields=('ingredient', 'ingredientQuantity'), can_delete=True, extra=0
)
form = ItemCreateForm(instance=item)
formset = IngredientQuantityFormset(instance=item, queryset=IngredientQuantity.objects.filter(ingredient__user=user))
if request.method == 'POST':
form = ItemCreateForm(request.POST, instance=item)
formset = IngredientQuantityFormset(request.POST, instance=item, queryset=IngredientQuantity.objects.filter(ingredient__user=user))
# rest of view...
I've searched everywhere for how to implement the queryset parameter properly, but I cannot get it to work. When creating an item on a menu, the user still has the ability to choose from every ingredient in the database (including the ones created by other users). I would like the user to only be able to choose from the ingredients they themselves created.
Does anyone know how to do this properly? Thank you!
I received some guidance on Django forums and arrived at a solution which is documented below:
https://forum.djangoproject.com/t/filter-dropdown-options-in-django-inline-formset-based-on-attribute-of-through-model/13374/3

DJANGO POSTGRES matching query does not exist

Hi i have a seller model that is related one to one field with user in DJANGO. Seller can create a "deal" and to become seller you first have to create a normal account as a user.
I dont have any idea how to take to the view deals that are from the specyfic seller
MY views.
#user_passes_test(is_seller)
def seller_page(request):
if request.method == "GET":
user = request.user
_seller = Seller.objects.get(user_id=user) # TODO: doesnt work
deals = Deal.objects.get(seller_id=_seller)
form = forms.DealModelForm
context = {'deals': deals, 'form': form}
return render(request, 'seller_page.html', context)
My models
class Seller(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
address = models.CharField(max_length=255)
city = models.CharField(max_length=255)
post_code = models.CharField(max_length=6)
phone = models.CharField(max_length=12)
email = models.CharField(max_length=255)
bank_account = models.CharField(max_length=255)
nip = models.CharField(max_length=255)
is_seller_active = models.BooleanField(default=False)
sells = models.IntegerField(default=0)
class Deal(models.Model):
seller = models.ForeignKey(Seller, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
description = models.TextField()
image = models.ImageField()
is_deal_on = models.BooleanField(default=True)
sell_price = models.DecimalField(default=0, decimal_places=2, max_digits=6, help_text='Cena sprzedaży')
origin_price = models.DecimalField(default=0, decimal_places=2, max_digits=6, help_text='Oryginalna cena',
blank=True, null=True)
time_valid = models.IntegerField(default=12) # ilość miesięcy ile warty jest deal
unique_code = models.CharField(max_length=60, null=True, blank=True)
quantity = models.IntegerField(default=0)
province = models.IntegerField(choices=PROVINCES)
ERROR :
_seller = Seller.objects.get(user_id=user)
If the "user" variable is an integer:
_seller = Seller.objects.get(user__id=user) #Note that is "__" and not "_"
if the "user" variable is an object (User model):
_seller = Seller.objects.get(user=user)

Django: ModelForm get ManyToMany Field in clean Function

i have a Model called Order and it's it has manytomanyfield to ProductModel
i want to get the values of selected products in clean function to make some calculations
but i cannot find product field
this is the modelform code
class OrderForm(ModelForm):
class Meta:
model = Order
fields = "__all__"
def clean_points(self):
products = self.cleaned_data["Product"]
print(self.cleaned_data.get(
'product', None))
points = 20
self.set_customer_points(self.cleaned_data["customer"], points=points)
return points
def set_customer_points(self, customer, points=0):
customer.points = customer.points + points
customer.save()
and this is OrderModel
class Order(models.Model):
customer = models.ForeignKey(
Customer, on_delete=models.SET_NULL, null=True)
description = models.TextField(max_length=100)
price = models.DecimalField(decimal_places=2, max_digits=100, )
discount = models.DecimalField(decimal_places=2, max_digits=100)
order_state = models.ForeignKey(
'OrderState', on_delete=models.DO_NOTHING, null=True)
points = models.IntegerField(default=0)
product = models.ManyToManyField(
"product.Product", )
def __str__(self):
return self.customer.name
class Product(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(max_length=100)
price = models.DecimalField(decimal_places=2, max_digits=100)
discount = models.DecimalField(decimal_places=2, max_digits=100)
image = models.ImageField(upload_to="products",)
points = models.IntegerField(default=0)
def __str__(self):
return self.name
Have you tried this (lower case)?
If it doesn't work, print(self.cleaned_data) and see the available fields for debugging.
def clean_points(self):
products = self.cleaned_data.get("product")

I am getting invalid keyword argument while posting product array in customer order. What should i do?

First i was getting an error like to create an explicit create method while serializing an array of product. So i added it but stiil im getting thhis error :
TypeError: 'customerorder' is an invalid keyword argument for this function
This is my serializers.py
class ProductSerializer(serializers.ModelSerializer):
product_id = serializers.IntegerField(required=False)
class Meta:
model = Product
fields = '__all__'
class CustOrderSerializer(serializers.ModelSerializer):
price = serializers.SlugRelatedField(slug_field='price', queryset=Price.objects.all())
# product = serializers.SlugRelatedField(slug_field='product', queryset=Product.objects.all())
area = serializers.SlugRelatedField(slug_field='address', queryset=Area.objects.all())
city = serializers.SlugRelatedField(slug_field='city', queryset=City.objects.all())
product = ProductSerializer(many=True)
class Meta:
model = CustOrder
fields = '__all__'
def create(self, validated_data):
product = validated_data.pop('product')
customerorder = CustOrder.objects.create(**validated_data)
for product in product:
Product.objects.create(**product, customerorder= customerorder)
return customerorder
This is models.py
class Product(models.Model):
product_id = models.AutoField(primary_key=True)
product = ArrayField(models.CharField(max_length=200, blank=True))
def __str__(self):
return str(self.product)
class CustOrder(models.Model):
Customer_id = models.AutoField(primary_key=True)
CustomerName = models.CharField(max_length=200)
email = models.EmailField(max_length=70,blank=True, null= True, unique= True)
gender = models.CharField(max_length=6, choices=GENDER_CHOICES)
phone = PhoneField(null=False, blank=True, unique=True)
landmark = models.PointField()
#landmark = models.TextField(max_length=400, help_text="Enter the landmark", default='Enter landmark')
houseno = models.IntegerField(default=0)
#product_name = models.CharField(max_length=200, choices=PRODUCT_CHOICES,default='Boneless chicken')
# product_id = models.ForeignKey(Product, on_delete=models.CASCADE,related_name='custorder_productid')
product = models.ManyToManyField(Product, blank=True,related_name='pricetag')
quantity = models.IntegerField(default=0)
# price_id = models.ForeignKey(Price)
price = models.ForeignKey(Price, on_delete=models.SET_NULL, null=True,related_name='pricetag')
#price = models.DecimalField(max_digits=50, decimal_places=5, default=48.9)
pay_method = models.CharField(max_length=200,choices=PAYMENT_CHOICES, default='RAZOR PAY')
city = models.ForeignKey(City, on_delete=models.SET_NULL, null=True)
area = models.ForeignKey(Area, on_delete=models.SET_NULL, null=True)
# Price.objects.aggregate(Sum('price'))
def __str__(self):
return self.CustomerName
There are several errors here.
Firstly for some reason you've set the related name from Product back to CustOrder as pricetag. That name does not appear to relate to either side of the relationship, so not sure why you've used it.
However even with that change, it still won't work, because you can't set many-to-many relationships at create time. You would need to create the product and then add it to the order.
But that still makes no sense, because you don't actually want to be creating products at all here; you want to add existing products to the order. So just do that:
customerorder = CustOrder.objects.create(**validated_data)
customerorder.product.add(*product)
Your Product model has not field customerorder. That is the reason why Django raises the error.

Django REST: How to filter related set?

I'm trying to create a Serializer which contains cities and for every city list of trips which belongs to the current user. The problem is that I'm getting all trips, not just users ones.
My expectation for example if user was two times in London and once in Prague:
[{<serialized London>,'trips':[<serialized the two London trips>]},
{<serialized Prague>, 'trips':[<serialized one trip to Prague]}]
Now I'm getting all trips connected with the city.
Models:
class City(models.Model):
place_id = models.CharField(max_length=1000, unique=True, null=True, blank=True)
lat = models.DecimalField(max_digits=6, decimal_places=3, db_index=True, null=True, blank=True)
lng = models.DecimalField(max_digits=6, decimal_places=3, db_index=True, null=True, blank=True)
class Trip(models.Model):
user = models.ForeignKey('auth.User', related_name='trips')
city = models.ForeignKey('locations.City', related_name='trips')
date_from = models.DateField(default=now)
date_to = models.DateField(default=now)
detail = models.TextField(null=True, blank=True)
View:
def ajax_get_my_trips(request):
trips = Trip.objects.filter(user=request.user)
cities = City.objects.filter(trips__in=trips)
response = MyCityTripsSerializer(cities,many=True).data
return JsonResponse(response, safe=False)
Serializers:
class MyTripsSerializer(serializers.ModelSerializer):
class Meta:
model = Trip
fields = ('date_from', 'date_to', 'detail')
def get_queryset(self):
user = self.request.user
return Trip.objects.filter(user=user)
class MyCityTripsSerializer(serializers.ModelSerializer):
trips = MyTripsSerializer(many=True)
class Meta:
model = City
fields = ('place_id', 'lat', 'lng', 'number_of_users_here_now', 'formatted_address', 'trips')
Do you know how to make it work?
class MyTripsSerializer(serializers.ModelSerializer):
user = serializers.PrimaryKeyRelatedField(queryset=UserModel.objects.all())
city = serializers.PrimaryKeyRelatedField(queryset=City.objects.all())
class Meta:
model = Trip
fields = ('date_from', 'date_to', 'detail')
def get_queryset(self):
user = self.request.user
return Trip.objects.filter(user=user)
class MyCityTripsSerializer(serializers.ModelSerializer):
trips = MyTripsSerializer(many=True)
class Meta:
model = City
fields = ('place_id', 'lat', 'lng', 'number_of_users_here_now', 'formatted_address', 'trips')
class Trip(models.Model):
user = models.ForeignKey('auth.User', related_name='user_trips')
city = models.ForeignKey('locations.City', related_name='trips')
date_from = models.DateField(default=now)
date_to = models.DateField(default=now)
detail = models.TextField(null=True, blank=True)
Related name must be unique for every ForeignKey.