@@ -19,6 +19,14 @@ class Profile(models.Model):
1919 birth_date = models .DateField (null = True , blank = True )
2020 picture = models .ImageField (upload_to = profile_upload_to_unique , null = True , blank = True )
2121
22+ class Meta :
23+ verbose_name = "Profile"
24+ verbose_name_plural = "Profiles"
25+ indexes = [
26+ models .Index (fields = ['user' ]),
27+ ]
28+ ordering = ['user' ]
29+
2230 def __str__ (self ):
2331 return f'{ self .user .username } Profile'
2432
@@ -27,8 +35,16 @@ class Category(models.Model):
2735 name = models .CharField (max_length = 255 )
2836 slug = models .SlugField (max_length = 255 , unique = True )
2937
38+ class Meta :
39+ verbose_name = "Category"
40+ verbose_name_plural = "Categories"
41+ indexes = [
42+ models .Index (fields = ['name' ]),
43+ ]
44+ ordering = ["name" ]
45+
3046 def __str__ (self ):
31- return self .name
47+ return f"Category: { self .name } "
3248
3349
3450class Product (models .Model ):
@@ -43,20 +59,90 @@ class Product(models.Model):
4359 blank = True ,
4460 upload_to = product_upload_to_unique
4561 )
46-
4762 category = models .ForeignKey (
4863 Category ,
4964 related_name = "products" ,
5065 on_delete = models .CASCADE ,
51-
5266 )
53-
54- objects = models .Manager ()
55- tags = TaggableManager
67+ tags = TaggableManager ()
68+
69+ class Meta :
70+ verbose_name = "Product"
71+ verbose_name_plural = "Products"
72+ indexes = [
73+ models .Index (fields = ['slug' ]),
74+ models .Index (fields = ['name' ]),
75+ models .Index (fields = ['category' ]),
76+ ]
77+ ordering = ["name" ]
5678
5779 def save (self , * args , ** kwargs ):
58- self .slug = slugify (self .name )
80+ # Auto-generate slug if not set or name changes
81+ if not self .slug or self .name != self .__class__ .objects .get (pk = self .pk ).name :
82+ self .slug = slugify (self .name )
5983 super ().save (* args , ** kwargs )
6084
6185 def __str__ (self ):
62- return self .name
86+ return f"Product: { self .name } (ID: { self .product_id } )"
87+
88+
89+ class Order (models .Model ):
90+ class Status (models .TextChoices ):
91+ PENDING = 'PE' , 'Pending'
92+ COMPLETED = 'CO' , 'Completed'
93+ CANCELLED = 'CA' , 'Cancelled'
94+
95+ user = models .ForeignKey (User , on_delete = models .SET_NULL , null = True )
96+ quantity = models .IntegerField ()
97+ order_date = models .DateTimeField (auto_now_add = True )
98+ status = models .CharField (max_length = 10 , choices = Status .choices , default = Status .PENDING )
99+
100+ class Meta :
101+ verbose_name = "Order"
102+ verbose_name_plural = "Orders"
103+ indexes = [
104+ models .Index (fields = ['user' ]),
105+ models .Index (fields = ['order_date' ]),
106+ ]
107+ ordering = ["-order_date" ]
108+
109+ @property
110+ def total_price (self ):
111+ """
112+ Calculate the total price of the order.
113+
114+ Returns:
115+ Decimal: The total price, which is the sum of all order items' prices.
116+ """
117+ return sum (item .price for item in self .items .all ())
118+
119+ def __str__ (self ):
120+ return f"Order: { self .id } by { self .user .username if self .user else 'Deleted User' } "
121+
122+
123+ class OrderItem (models .Model ):
124+ order = models .ForeignKey (Order , related_name = 'items' , on_delete = models .CASCADE )
125+ product = models .ForeignKey (Product , on_delete = models .CASCADE )
126+ quantity = models .PositiveSmallIntegerField ()
127+
128+ class Meta :
129+ verbose_name = "Order Item"
130+ verbose_name_plural = "Order Items"
131+ indexes = [
132+ models .Index (fields = ['order' ]),
133+ models .Index (fields = ['product' ]),
134+ ]
135+ ordering = ["order" ]
136+
137+ @property
138+ def price (self ):
139+ """
140+ Calculate the total price for the order item.
141+
142+ Returns:
143+ Decimal: The total price, which is the product of the item's price and quantity.
144+ """
145+ return self .product .price * self .quantity
146+
147+ def __str__ (self ):
148+ return f"Order Item: { self .product .name } (Order ID: { self .order .id } )"
0 commit comments