How to associate quantity amount in Django's many to many relationship - django

In Django I have 2 models. One called Box and one called Product. A Box can have many different products and with different quantities of each product. For example box1 can have 1 productA and 2 productB.
My box model
class Box(models.Model):
boxName = models.CharField(max_length=255, blank = False)
product = models.ManyToManyField(Product)
def __str__(self):
return self.boxName
My product model
class Product(models.Model):
productName = models.CharField(max_length=200)
productDescription = models.TextField(blank=True)
productPrice = models.DecimalField(max_digits=9, decimal_places=0, default=0)
class Meta:
db_table = 'products'
ordering = ['-productName']
def __str__(self):
return self.productName
How do I set up this model allowing me to select quantity of a products when creating the box object?

Define an intermediary model that contains product + quantity.
class Box(models.Model):
boxName = models.CharField(max_length=255, blank = False)
product_set = models.ManyToManyField(ProductSet)
def __str__(self):
return self.boxName
class ProductSet(models.Model):
quantity = models.PositiveIntegerField()
product = models.ForeignKey(Product, on_delete = models.PROTECT)
class Product(models.Model):
productName = models.CharField(max_length=200)
productDescription = models.TextField(blank=True)
productPrice = models.DecimalField(max_digits=9, decimal_places=0, default=0)
class Meta:
db_table = 'products'
ordering = ['-productName']
def __str__(self):
return self.productName

Related

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")

labeling in Django Admin

I am new to Django and still learning, I have created a database and some models but I got stuck with meaningful labels in Django Admin. This is the model:
class Product(models.Model):
product_id = models.AutoField(primary_key=True)
product_name = models.CharField(max_length= 50)
brand_name = models.CharField(max_length = 20)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
min_order = models.IntegerField()
max_order = models.IntegerField()
units = models.IntegerField()
quantity = models.ForeignKey(Quantity, on_delete=models.SET_NULL, null=True)
objects = ProductManager()
class Meta:
verbose_name = "Product"
verbose_name_plural = 'Products'
And I get this:
I want Product object (3) to be replaced byt the product_name. Thank you in advance!
You can override the __str__ method [python-doc] and return the product_name instead:
class Product(models.Model):
# …
def __str__(self):
return self.product_name

How to create a Many to Many Relation in Django

I´m new in Django and I´ve been trying to create a Model, where I have many warehouses and many products. So far I have achieved this:
class Product(models.Model):
idProduct = models.IntegerField(primary_key=True)
name = models.CharField(max_length=50)
quantity = models.IntegerField()
def __str__(self):
return self.name
class Warehouse(models.Model):
idWareouse = models.IntegerField(primary_key=True)
name = models.CharField(max_length=50)
address = models.CharField(max_length=100)
city = models.CharField(max_length=50)
products = models.ManyToManyField(Product)
def __str__(self):
return self.name
But the problem is, that one product can be in multiple warehouses with different product quantity, and I don´t know how to model this.
Thank you
You could use the attribute through of a ManyToMany relation. See HERE.
It would result in this :
class Product(models.Model):
idProduct = models.IntegerField(primary_key=True)
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Warehouse(models.Model):
idWareouse = models.IntegerField(primary_key=True)
name = models.CharField(max_length=50)
address = models.CharField(max_length=100)
city = models.CharField(max_length=50)
products = models.ManyToManyField(Product, through='Catalog')
def __str__(self):
return self.name
class Catalog(models.Model):
products = models.ForeignKey(Product, on_delete=models.CASCADE)
warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
quantity = models.IntegerField()
See the products field in the Warehouse class :
products = models.ManyToManyField(Product, through='Catalog')
There is a full example in the documentation.
I would add the third model:
class Product(models.Model):
idProduct = models.IntegerField(primary_key=True)
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Warehouse(models.Model):
idWareouse = models.IntegerField(primary_key=True)
name = models.CharField(max_length=50)
address = models.CharField(max_length=100)
city = models.CharField(max_length=50)
def __str__(self):
return self.name
class Catalogue(models.Model):
products = models.ForeignKey(Product)
warehouse = models.ForeignKey(Warehouse)
quantity = models.IntegerField()

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.

Get all parent categories Django - Follow foreign key UP

I got the following models:
class Category(models.Model):
name = models.CharField(max_length=255)
parent = models.ForeignKey("self", blank=True, null=True)
class Meta:
verbose_name = _("category")
verbose_name_plural = _("categories")
def __unicode__(self):
return self.name
class Item(models.Model):
name = models.CharField(max_length=100, verbose_name=_("name"))
keywords = models.CharField(max_length=255, verbose_name=_("keywords"))
category = models.ForeignKey(Category)
class Meta:
abstract = True
verbose_name = _('item')
verbose_name_plural = _('items')
class Product(Item):
price = models.DecimalField(decimal_places=2, max_digits=8, verbose_name=_("price"))
brand = models.ForeignKey(Brand, verbose_name=_("brand"))
article_number = models.CharField(max_length=255, verbose_name=_("article_number"))
def __unicode__(self):
return self.name
class Meta:
verbose_name = _('product')
verbose_name_plural = _('products')
Let's say i have the following categories in the database:
ID NAME PARENT_ID
1 Products null
2 Phones 1
3 iPhones 2
I can get the top category by doing the following:
#This is a product with the category "iPhones"
product.category.parent.parent
But that's not nice because a product can be x numbers of categories deep.
How can I get all the related categories in an array or something?
Wanted output = [iPhones, Phones, Products]
Write a Model Property Method for the item class:
class Item(models.Model):
#property
def all_categories(self):
categories = []
current_category = self.category
while current_category is not None:
categories.append(current_category)
current_category = current_category.parent
return categories
#optional return reversed list:
#return list(reversed(categories))
Now you can get the desired list with
product.all_categories