Coverage for src/products/admin.py: 88%

91 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-09-21 16:24 +0300

1from django.utils.html import format_html 

2from django.utils.translation import gettext_lazy as _ 

3from django.contrib import admin 

4from django.contrib.contenttypes.admin import GenericTabularInline 

5 

6from src.products.models import ( 

7 Collection, 

8 Color, 

9 Metal, 

10 Stone, 

11 Size, 

12 Inventory, 

13) 

14from src.products.models.product import Bracelet, Earring, Necklace, Pendant, Ring, Watch 

15from src.products.models.review import Review 

16 

17 

18@admin.register(Collection) 

19class CollectionAdmin(admin.ModelAdmin): 

20 pass 

21 

22 

23@admin.register(Color) 

24class ColorAdmin(admin.ModelAdmin): 

25 pass 

26 

27 

28@admin.register(Metal) 

29class MetalAdmin(admin.ModelAdmin): 

30 pass 

31 

32 

33@admin.register(Stone) 

34class StoneAdmin(admin.ModelAdmin): 

35 pass 

36 

37 

38@admin.register(Size) 

39class SizeAdmin(admin.ModelAdmin): 

40 pass 

41 

42 

43@admin.register(Inventory) 

44class InventoryAdmin(admin.ModelAdmin): 

45 pass 

46 

47 

48class StoneListFilter(admin.SimpleListFilter): 

49 title = _('Stone') 

50 parameter_name = 'stone' 

51 

52 def lookups(self, request, model_admin): 

53 return [(s.id, s.name) for s in Stone.objects.all()] 

54 

55 def queryset(self, request, queryset): 

56 return ( 

57 queryset.filter(stone__id=self.value()) 

58 if self.value() 

59 else queryset 

60 ) 

61 

62 

63class ColorListFilter(admin.SimpleListFilter): 

64 title = _('Color') 

65 parameter_name = 'color' 

66 

67 def lookups(self, request, model_admin): 

68 return [(c.id, c.name) for c in Color.objects.all()] 

69 

70 def queryset(self, request, queryset): 

71 return ( 

72 queryset.filter(color__id=self.value()) 

73 if self.value() 

74 else queryset 

75 ) 

76 

77 

78class InventoryInline(GenericTabularInline): 

79 model = Inventory 

80 ct_field = "content_type" 

81 ct_fk_field = "object_id" 

82 min_num = 1 

83 max_num = 3 

84 validate_min = True 

85 

86 

87class BaseProductAdmin(admin.ModelAdmin): 

88 list_display = ( 

89 'first_picture', 

90 'second_picture', 

91 'collection', 

92 'created_at', 

93 'pk' 

94 ) 

95 

96 list_filter = (StoneListFilter, ColorListFilter, 'collection', 'metal') 

97 

98 ordering = ( 

99 'created_at', 

100 'collection', 

101 'metal', 

102 ) 

103 

104 search_fields = ( 

105 'collection__name', 

106 'metal__name', 

107 'color__name', 

108 'stone__name', 

109 ) 

110 

111 fieldsets = ( 

112 ('Images', {'fields': ('first_image', 'second_image')}), 

113 ( 

114 'Material and Design', 

115 { 

116 'fields': ( 

117 'collection', 

118 'metal', 

119 'stone', 

120 'color', 

121 ) 

122 }, 

123 ), 

124 ) 

125 

126 def first_picture(self, obj): 

127 return format_html( 

128 '<img src="{}" width="100" height="100" style="object-fit: cover;" />', 

129 obj.first_image, 

130 ) 

131 

132 def second_picture(self, obj): 

133 return format_html( 

134 '<img src="{}" width="100" height="100" style="object-fit: cover;" />', 

135 obj.second_image, 

136 ) 

137 

138 

139 

140@admin.register(Earring) 

141class EarringAdmin(BaseProductAdmin): 

142 inlines = [InventoryInline] 

143 

144 

145@admin.register(Necklace) 

146class NecklaceAdmin(BaseProductAdmin): 

147 inlines = [InventoryInline] 

148 

149 

150@admin.register(Pendant) 

151class PendantAdmin(BaseProductAdmin): 

152 inlines = [InventoryInline] 

153 

154 

155@admin.register(Bracelet) 

156class BraceletAdmin(BaseProductAdmin): 

157 inlines = [InventoryInline] 

158 

159 

160@admin.register(Watch) 

161class WatchAdmin(BaseProductAdmin): 

162 inlines = [InventoryInline] 

163 

164 

165@admin.register(Ring) 

166class RingAdmin(BaseProductAdmin): 

167 inlines = [InventoryInline] 

168 

169 

170@admin.register(Review) 

171class ReviewAdmin(admin.ModelAdmin): 

172 list_display = [ 

173 '__str__', 

174 'user', 

175 'rating', 

176 'approved', 

177 'created_at', 

178 'product_link', 

179 ] 

180 list_filter = [ 

181 'approved', 

182 'rating', 

183 'created_at', 

184 ] 

185 search_fields = [ 

186 'user__email', 

187 'user__userprofile__first_name', 

188 'user__userprofile__last_name', 

189 'comment', 

190 ] 

191 list_editable = ['approved'] 

192 readonly_fields = [ 

193 'user', 

194 'rating', 

195 'comment', 

196 'created_at', 

197 'content_type', 

198 'object_id', 

199 'product', 

200 ] 

201 ordering = ['-created_at'] 

202 

203 def product_link(self, obj): 

204 if obj.product: 

205 return format_html( 

206 '<a href="/admin/products/{}/{}/change/">{}</a>', 

207 obj.content_type.model, 

208 obj.object_id, 

209 str(obj.product), 

210 ) 

211 return '-' 

212 

213 product_link.short_description = 'Product' 

214 

215 def has_add_permission(self, request): 

216 return False 

217 

218 def has_delete_permission(self, request, obj=None): 

219 return request.user.is_superuser