Nessuna descrizione

utils.py 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. from django.shortcuts import render
  2. from django.contrib import messages
  3. # Create your views here.
  4. from django_filters.views import FilterView
  5. from django.urls import reverse_lazy, reverse
  6. from django.views.generic import (
  7. ListView,
  8. DetailView,
  9. CreateView,
  10. UpdateView,
  11. DeleteView,
  12. )
  13. from django.core.paginator import Paginator
  14. from core.models import MgMasterView, VMasterView, BelMasterView, EMasterView
  15. from pprint import pprint
  16. class ConfigurableCRUDView:
  17. model = None
  18. list_template_name = None
  19. detail_template_name = None
  20. form_template_name = None
  21. confirm_delete_template_name = None
  22. fields = '__all__' # Default to all fields
  23. paginate_by = 50
  24. filterset_class = None
  25. page_title = "Page Title"
  26. create_url_name = None
  27. update_url_name = None
  28. delete_url_name = None
  29. list_url_name = None
  30. config_fields = "all" # "all" or a list of field names to display
  31. config_field_orders = [] # Fields to display first
  32. config_excludes = [] # Fields to exclude
  33. config_readonly_fields = [] # Fields that should be read-only in update view
  34. config_edit_fields = "__all__" # "all" or a list of field names to display
  35. ordering = None
  36. form_class = None
  37. def get_fields(self):
  38. """
  39. Dynamically generate the fields to be displayed in the list view.
  40. - Includes all fields if `config_fields` is set to "all".
  41. - Respects `config_field_orders` and `config_excludes`.
  42. Returns field instances instead of field names.
  43. """
  44. pprint("get_fields")
  45. model_fields = {f.name: f for f in self.model._meta.get_fields()}
  46. # Filter based on `config_fields` configuration
  47. fields = []
  48. if self.config_fields != "all":
  49. fields = [model_fields[f] for f in self.config_fields if f in model_fields]
  50. else:
  51. fields = list(model_fields.values())
  52. # pprint("------------------------")
  53. # pprint(f"fields = {fields}")
  54. # Exclude fields specified in `config_excludes`
  55. fields = [f for f in fields if f.name not in self.config_excludes]
  56. # Order fields based on `config_field_orders`
  57. ordered_fields = [f for f in fields if f.name in self.config_field_orders]
  58. remaining_fields = [f for f in fields if f.name not in self.config_field_orders]
  59. # Reorder fields to match the order specified in `config_field_orders`
  60. ordered_field_names = set(self.config_field_orders)
  61. ordered_fields.sort(key=lambda f: self.config_field_orders.index(f.name) if f.name in ordered_field_names else len(ordered_field_names))
  62. return ordered_fields + remaining_fields
  63. def get_breadcrumbs(self, view_type, obj=None):
  64. """
  65. Generate breadcrumbs dynamically based on the view type.
  66. :param view_type: The type of view (list, create, update, detail, delete)
  67. :param obj: The current object (if applicable)
  68. :return: A list of breadcrumb dictionaries
  69. """
  70. breadcrumbs = [
  71. {'label': 'Dashboard', 'url': reverse('dashboard:index')},
  72. {'label': self.page_title, 'url': reverse(self.list_url_name)} if self.list_url_name else None,
  73. ]
  74. if view_type == 'create':
  75. breadcrumbs.append({'label': f'Create {self.model._meta.verbose_name}', 'url': None})
  76. elif view_type == 'update' and obj:
  77. breadcrumbs.append({'label': obj, 'url': reverse(self.update_url_name, kwargs={'pk': obj.pk})})
  78. elif view_type == 'detail' and obj:
  79. breadcrumbs.append({'label': f'Detail of {obj}', 'url': None})
  80. elif view_type == 'delete' and obj:
  81. breadcrumbs.append({'label': f'Delete {obj}', 'url': None})
  82. return [b for b in breadcrumbs if b]
  83. def get_list_view(self):
  84. class ListViewClass(FilterView, ListView):
  85. model = self.model
  86. template_name = self.list_template_name
  87. paginate_by = self.paginate_by
  88. filterset_class = self.filterset_class
  89. ordering = self.ordering
  90. def get_context_data(inner_self, **kwargs):
  91. context = super().get_context_data(**kwargs)
  92. fields = self.get_fields()
  93. context.update({
  94. 'fields': [f for f in fields],
  95. # 'fields': [field for field in self.model._meta.get_fields()],
  96. 'page_title': self.page_title,
  97. 'list_url': self.list_url_name,
  98. 'create_url': self.create_url_name,
  99. 'update_url': self.update_url_name,
  100. 'delete_url': self.delete_url_name,
  101. 'bs': self.get_breadcrumbs('list'),
  102. })
  103. return context
  104. return ListViewClass
  105. def get_detail_view(self):
  106. class DetailViewClass(DetailView):
  107. model = self.model
  108. template_name = self.detail_template_name
  109. def get_context_data(inner_self, **kwargs):
  110. context = super().get_context_data(**kwargs)
  111. context.update({
  112. 'page_title': self.page_title,
  113. 'bs': self.get_breadcrumbs('detail'),
  114. })
  115. return context
  116. return DetailViewClass
  117. def get_create_view(self):
  118. class CreateViewClass(CreateView):
  119. model = self.model
  120. template_name = self.form_template_name
  121. fields = self.config_edit_fields
  122. form_class = self.form_class
  123. def form_valid(inner_self, form):
  124. response = super().form_valid(form)
  125. messages.success(inner_self.request, f"{self.model._meta.verbose_name} created successfully!")
  126. return response
  127. def get_success_url(inner_self):
  128. return reverse(self.update_url_name, kwargs={'pk': inner_self.object.pk})
  129. def get_context_data(inner_self, **kwargs):
  130. context = super().get_context_data(**kwargs)
  131. context.update({
  132. 'list_url_name': self.list_url_name,
  133. 'page_title': f"Create {self.model._meta.verbose_name}",
  134. 'bs': self.get_breadcrumbs('update', obj=inner_self.object),
  135. })
  136. return context
  137. return CreateViewClass
  138. def get_update_view(self):
  139. class UpdateViewClass(UpdateView):
  140. model = self.model
  141. template_name = self.form_template_name
  142. fields = self.config_edit_fields
  143. form_class = self.form_class
  144. def form_valid(inner_self, form):
  145. response = super().form_valid(form)
  146. messages.success(inner_self.request, f"{self.model._meta.verbose_name} updated successfully!")
  147. return response
  148. def get_form(inner_self, *args, **kwargs):
  149. """
  150. Customize the form to make specified fields read-only.
  151. """
  152. form = super().get_form(*args, **kwargs)
  153. for field_name in self.config_readonly_fields:
  154. if field_name in form.fields:
  155. form.fields[field_name].widget.attrs['readonly'] = True
  156. form.fields[field_name].widget.attrs['style'] = 'background-color: #f9f9f9; cursor: not-allowed;'
  157. form.fields[field_name].disabled = True # Optional: Completely disable the field
  158. return form
  159. def get_success_url(inner_self):
  160. return reverse(self.update_url_name, kwargs={'pk': inner_self.object.pk})
  161. def get_context_data(inner_self, **kwargs):
  162. context = super().get_context_data(**kwargs)
  163. context.update({
  164. 'list_url_name': self.list_url_name,
  165. 'page_title': f"Update {self.model._meta.verbose_name}",
  166. 'bs': self.get_breadcrumbs('update', obj=inner_self.object),
  167. })
  168. return context
  169. return UpdateViewClass
  170. def get_delete_view(self):
  171. class DeleteViewClass(DeleteView):
  172. model = self.model
  173. template_name = self.confirm_delete_template_name
  174. success_url = reverse_lazy(self.delete_url_name)
  175. def get_context_data(inner_self, **kwargs):
  176. context = super().get_context_data(**kwargs)
  177. context.update({
  178. 'list_url_name': self.list_url_name,
  179. 'page_title': f"Delete {self.model._meta.verbose_name}",
  180. 'bs': self.get_breadcrumbs('delete', obj=inner_self.object),
  181. })
  182. return context
  183. return DeleteViewClass
  184. def queryFromMaster(lot_no):
  185. models = [MgMasterView, VMasterView, BelMasterView, EMasterView]
  186. value_to_filter = lot_no
  187. results = []
  188. for model in models:
  189. queryset = model.objects.filter(PRO2=value_to_filter)
  190. results.extend(queryset)
  191. return results
  192. SHEET_NAMES = {
  193. 'hardness_out': 'Hardness Out',
  194. 'hardness_out_in': 'Hardness Out/In',
  195. 'hardness_both_size': 'Hardness Both Size',
  196. 'dimension': 'Dimension',
  197. 'dimension_app': 'Dimension Appearance',
  198. 'dimension_app_drawing': 'Dimension Appearance + Drawing',
  199. 'dimension_bal_weight': 'Dimension Balance/Weight',
  200. 'dim_bal_app_hard': 'Dimension Balance/Appearance/Hardness',
  201. 'dim_bal_app_rot_hard': 'Dimension Balance/Appearance/Rotation/Hardness',
  202. 'thickness_8_point': 'Thickness 8 Points',
  203. 'centering': 'Centering',
  204. }