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

84 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-08-04 12:59 +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 Earwear, 

8 Fingerwear, 

9 Neckwear, 

10 Wristwear, 

11 Collection, 

12 Color, 

13 Metal, 

14 Stone, 

15 Size, 

16 Inventory, 

17) 

18from src.products.models.review import Review 

19 

20 

21@admin.register(Collection) 

22class CollectionAdmin(admin.ModelAdmin): 

23 pass 

24 

25 

26@admin.register(Color) 

27class ColorAdmin(admin.ModelAdmin): 

28 pass 

29 

30 

31@admin.register(Metal) 

32class MetalAdmin(admin.ModelAdmin): 

33 pass 

34 

35 

36@admin.register(Stone) 

37class StoneAdmin(admin.ModelAdmin): 

38 pass 

39 

40 

41@admin.register(Size) 

42class SizeAdmin(admin.ModelAdmin): 

43 pass 

44 

45 

46@admin.register(Inventory) 

47class InventoryAdmin(admin.ModelAdmin): 

48 pass 

49 

50 

51class StoneListFilter(admin.SimpleListFilter): 

52 title = _('Stone') 

53 parameter_name = 'stone' 

54 

55 def lookups(self, request, model_admin): 

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

57 

58 def queryset(self, request, queryset): 

59 return ( 

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

61 if self.value() 

62 else queryset 

63 ) 

64 

65 

66class ColorListFilter(admin.SimpleListFilter): 

67 title = _('Color') 

68 parameter_name = 'color' 

69 

70 def lookups(self, request, model_admin): 

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

72 

73 def queryset(self, request, queryset): 

74 return ( 

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

76 if self.value() 

77 else queryset 

78 ) 

79 

80 

81class InventoryInline(GenericTabularInline): 

82 model = Inventory 

83 ct_field = "content_type" 

84 ct_fk_field = "object_id" 

85 min_num = 1 

86 max_num = 3 

87 validate_min = True 

88 

89 

90class BaseProductAdmin(admin.ModelAdmin): 

91 list_display = ( 

92 'first_picture', 

93 'second_picture', 

94 'collection', 

95 'created_at', 

96 ) 

97 

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

99 

100 ordering = ( 

101 'created_at', 

102 'collection', 

103 'metal', 

104 ) 

105 

106 search_fields = ( 

107 'collection__name', 

108 'metal__name', 

109 'color__name', 

110 'stone__name', 

111 ) 

112 

113 fieldsets = ( 

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

115 ( 

116 'Material and Design', 

117 { 

118 'fields': ( 

119 'collection', 

120 'metal', 

121 'stone', 

122 'color', 

123 ) 

124 }, 

125 ), 

126 ) 

127 

128 def first_picture(self, obj): 

129 return format_html( 

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

131 obj.first_image, 

132 ) 

133 

134 def second_picture(self, obj): 

135 return format_html( 

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

137 obj.second_image, 

138 ) 

139 

140 

141@admin.register(Earwear) 

142class EarwearAdmin(BaseProductAdmin): 

143 inlines = [InventoryInline] 

144 

145 

146@admin.register(Neckwear) 

147class NeckwearAdmin(BaseProductAdmin): 

148 inlines = [InventoryInline] 

149 

150 

151@admin.register(Wristwear) 

152class WristwearAdmin(BaseProductAdmin): 

153 inlines = [InventoryInline] 

154 

155 

156@admin.register(Fingerwear) 

157class FingerwearAdmin(BaseProductAdmin): 

158 inlines = [InventoryInline] 

159 

160 

161@admin.register(Review) 

162class ReviewAdmin(admin.ModelAdmin): 

163 list_display = [ 

164 '__str__', 

165 'user', 

166 'rating', 

167 'approved', 

168 'created_at', 

169 'product_link', 

170 ] 

171 list_filter = [ 

172 'approved', 

173 'rating', 

174 'created_at', 

175 ] 

176 search_fields = [ 

177 'user__email', 

178 'user__userprofile__first_name', 

179 'user__userprofile__last_name', 

180 'comment', 

181 ] 

182 list_editable = ['approved'] 

183 readonly_fields = [ 

184 'user', 

185 'rating', 

186 'comment', 

187 'created_at', 

188 'content_type', 

189 'object_id', 

190 'product', 

191 ] 

192 ordering = ['-created_at'] 

193 

194 def product_link(self, obj): 

195 if obj.product: 

196 return format_html( 

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

198 obj.content_type.model, 

199 obj.object_id, 

200 str(obj.product), 

201 ) 

202 return '-' 

203 

204 product_link.short_description = 'Product' 

205 

206 def has_add_permission(self, request): 

207 return False 

208 

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

210 return request.user.is_superuser