暂无描述

utils.py 8.9KB

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