Нет описания

views.py 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. from django.shortcuts import render
  2. # Create your views here.
  3. from django_filters.views import FilterView
  4. from django.urls import reverse_lazy, reverse
  5. from django.views.generic import (
  6. ListView,
  7. DetailView,
  8. CreateView,
  9. UpdateView,
  10. DeleteView,
  11. )
  12. from django.core.paginator import Paginator
  13. from .models import Data, DataMs, TbFgPressinfoLotlist, LotSummary
  14. from .filters import DataFilter, DataMsFilter, TbFgPressFilter, LotSummaryFilter
  15. from django.urls import reverse
  16. from django.contrib import messages
  17. from pprint import pprint
  18. class DataListView(FilterView, ListView):
  19. model = Data
  20. template_name = 'legacy/data_list.html'
  21. # context_object_name = 'data_list'
  22. paginate_by = 10 # Enable pagination
  23. # Specify the filter class
  24. filterset_class = DataFilter
  25. def get_context_data(self, **kwargs):
  26. context = super().get_context_data(**kwargs)
  27. # Pass model fields to the template
  28. context['fields'] = [field for field in self.model._meta.get_fields()]
  29. context['bs'] = [
  30. {'label': 'Dashboard', 'url': reverse('dashboard:index')},
  31. {'label': 'Data', 'url': reverse('legacy:data-list')},
  32. ]
  33. return context
  34. # Read (detail view)
  35. class DataDetailView(DetailView):
  36. model = Data
  37. template_name = 'data_detail.html'
  38. context_object_name = 'data' # Use this name in templates
  39. # Create
  40. class DataCreateView(CreateView):
  41. model = Data
  42. template_name = 'legacy/data_form.html'
  43. fields = '__all__' # Use all fields or specify a list of fields
  44. def form_valid(self, form):
  45. response = super().form_valid(form)
  46. messages.success(self.request, "Data has been successfully created!")
  47. return response
  48. def get_success_url(self):
  49. # Redirect to the edit page of the newly created object
  50. return reverse('legacy:data-update', kwargs={'pk': self.object.pk})
  51. def get_context_data(self, **kwargs):
  52. context = super().get_context_data(**kwargs)
  53. # Pass model fields to the template
  54. context['bs'] = [
  55. {'label': 'Dashboard', 'url': reverse('dashboard:index')},
  56. {'label': 'Data', 'url': reverse('legacy:data-list')},
  57. {'label': 'Data Create', 'url': reverse('legacy:data-create')},
  58. ]
  59. return context
  60. # Update
  61. class DataUpdateView(UpdateView):
  62. model = Data
  63. template_name = 'legacy/data_form.html'
  64. fields = '__all__' # Use all fields or specify a list of fields
  65. def get_success_url(self):
  66. # Redirect to the edit page of the newly created object
  67. return reverse('legacy:data-update', kwargs={'pk': self.object.pk})
  68. def form_valid(self, form):
  69. response = super().form_valid(form)
  70. messages.success(self.request, "Data has been successfully updated!")
  71. return response
  72. def get_context_data(self, **kwargs):
  73. context = super().get_context_data(**kwargs)
  74. # Pass model fields to the template
  75. context['bs'] = [
  76. {'label': 'Dashboard', 'url': reverse('dashboard:index')},
  77. {'label': 'Data', 'url': reverse('legacy:data-list')},
  78. {'label': self.object, 'url': reverse('legacy:data-update', kwargs={'pk':self.object.pk})},
  79. ]
  80. return context
  81. # Delete
  82. class DataDeleteView(DeleteView):
  83. model = Data
  84. template_name = 'legacy/data_confirm_delete.html'
  85. success_url = reverse_lazy('legacy:data-list') # Redirect after deletion
  86. def get_context_data(self, **kwargs):
  87. context = super().get_context_data(**kwargs)
  88. # Pass model fields to the template
  89. context['bs'] = [
  90. {'label': 'Dashboard', 'url': reverse('dashboard:index')},
  91. {'label': 'Data', 'url': reverse('legacy:data-list')},
  92. {'label': self.object, 'url': reverse('legacy:data-update', kwargs={'pk':self.object.pk})},
  93. ]
  94. return context
  95. class ConfigurableCRUDView:
  96. model = None
  97. list_template_name = None
  98. detail_template_name = None
  99. form_template_name = None
  100. confirm_delete_template_name = None
  101. fields = '__all__' # Default to all fields
  102. paginate_by = 10
  103. filterset_class = None
  104. page_title = "Page Title"
  105. create_url_name = None
  106. update_url_name = None
  107. delete_url_name = None
  108. list_url_name = None
  109. config_fields = "all" # "all" or a list of field names to display
  110. config_field_orders = [] # Fields to display first
  111. config_excludes = [] # Fields to exclude
  112. config_readonly_fields = [] # Fields that should be read-only in update view
  113. config_edit_fields = "__all__" # "all" or a list of field names to display
  114. ordering = None
  115. def get_fields(self):
  116. """
  117. Dynamically generate the fields to be displayed in the list view.
  118. - Includes all fields if `config_fields` is set to "all".
  119. - Respects `config_field_orders` and `config_excludes`.
  120. Returns field instances instead of field names.
  121. """
  122. model_fields = {f.name: f for f in self.model._meta.get_fields()}
  123. # Filter based on `config_fields` configuration
  124. fields = []
  125. if self.config_fields != "all":
  126. fields = [model_fields[f] for f in self.config_fields if f in model_fields]
  127. else:
  128. fields = list(model_fields.values())
  129. # pprint("------------------------")
  130. # pprint(f"fields = {fields}")
  131. # Exclude fields specified in `config_excludes`
  132. fields = [f for f in fields if f.name not in self.config_excludes]
  133. # Order fields based on `config_field_orders`
  134. ordered_fields = [f for f in fields if f.name in self.config_field_orders]
  135. remaining_fields = [f for f in fields if f.name not in self.config_field_orders]
  136. # Reorder fields to match the order specified in `config_field_orders`
  137. ordered_field_names = set(self.config_field_orders)
  138. 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))
  139. return ordered_fields + remaining_fields
  140. def get_breadcrumbs(self, view_type, obj=None):
  141. """
  142. Generate breadcrumbs dynamically based on the view type.
  143. :param view_type: The type of view (list, create, update, detail, delete)
  144. :param obj: The current object (if applicable)
  145. :return: A list of breadcrumb dictionaries
  146. """
  147. breadcrumbs = [
  148. {'label': 'Dashboard', 'url': reverse('dashboard:index')},
  149. {'label': self.page_title, 'url': reverse(self.list_url_name)} if self.list_url_name else None,
  150. ]
  151. if view_type == 'create':
  152. breadcrumbs.append({'label': f'Create {self.model._meta.verbose_name}', 'url': None})
  153. elif view_type == 'update' and obj:
  154. breadcrumbs.append({'label': obj, 'url': reverse(self.update_url_name, kwargs={'pk': obj.pk})})
  155. elif view_type == 'detail' and obj:
  156. breadcrumbs.append({'label': f'Detail of {obj}', 'url': None})
  157. elif view_type == 'delete' and obj:
  158. breadcrumbs.append({'label': f'Delete {obj}', 'url': None})
  159. return [b for b in breadcrumbs if b]
  160. def get_list_view(self):
  161. class ListViewClass(FilterView, ListView):
  162. model = self.model
  163. template_name = self.list_template_name
  164. paginate_by = self.paginate_by
  165. filterset_class = self.filterset_class
  166. ordering = self.ordering
  167. def get_context_data(inner_self, **kwargs):
  168. context = super().get_context_data(**kwargs)
  169. fields = self.get_fields()
  170. context.update({
  171. 'fields': [f for f in fields],
  172. # 'fields': [field for field in self.model._meta.get_fields()],
  173. 'page_title': self.page_title,
  174. 'list_url': self.list_url_name,
  175. 'create_url': self.create_url_name,
  176. 'update_url': self.update_url_name,
  177. 'delete_url': self.delete_url_name,
  178. 'bs': self.get_breadcrumbs('list'),
  179. })
  180. return context
  181. return ListViewClass
  182. def get_detail_view(self):
  183. class DetailViewClass(DetailView):
  184. model = self.model
  185. template_name = self.detail_template_name
  186. def get_context_data(inner_self, **kwargs):
  187. context = super().get_context_data(**kwargs)
  188. context.update({
  189. 'page_title': self.page_title,
  190. 'bs': self.get_breadcrumbs('detail'),
  191. })
  192. return context
  193. return DetailViewClass
  194. def get_create_view(self):
  195. class CreateViewClass(CreateView):
  196. model = self.model
  197. template_name = self.form_template_name
  198. fields = self.config_edit_fields
  199. def form_valid(inner_self, form):
  200. response = super().form_valid(form)
  201. messages.success(inner_self.request, f"{self.model._meta.verbose_name} created successfully!")
  202. return response
  203. def get_success_url(inner_self):
  204. return reverse(self.update_url_name, kwargs={'pk': inner_self.object.pk})
  205. def get_context_data(inner_self, **kwargs):
  206. context = super().get_context_data(**kwargs)
  207. context.update({
  208. 'list_url_name': self.list_url_name,
  209. 'page_title': f"Create {self.model._meta.verbose_name}",
  210. 'bs': self.get_breadcrumbs('update', obj=inner_self.object),
  211. })
  212. return context
  213. return CreateViewClass
  214. def get_update_view(self):
  215. class UpdateViewClass(UpdateView):
  216. model = self.model
  217. template_name = self.form_template_name
  218. fields = self.config_edit_fields
  219. def form_valid(inner_self, form):
  220. response = super().form_valid(form)
  221. messages.success(inner_self.request, f"{self.model._meta.verbose_name} updated successfully!")
  222. return response
  223. def get_form(inner_self, *args, **kwargs):
  224. """
  225. Customize the form to make specified fields read-only.
  226. """
  227. form = super().get_form(*args, **kwargs)
  228. for field_name in self.config_readonly_fields:
  229. if field_name in form.fields:
  230. form.fields[field_name].widget.attrs['readonly'] = True
  231. form.fields[field_name].widget.attrs['style'] = 'background-color: #f9f9f9; cursor: not-allowed;'
  232. form.fields[field_name].disabled = True # Optional: Completely disable the field
  233. return form
  234. def get_success_url(inner_self):
  235. return reverse(self.update_url_name, kwargs={'pk': inner_self.object.pk})
  236. def get_context_data(inner_self, **kwargs):
  237. context = super().get_context_data(**kwargs)
  238. context.update({
  239. 'list_url_name': self.list_url_name,
  240. 'page_title': f"Update {self.model._meta.verbose_name}",
  241. 'bs': self.get_breadcrumbs('update', obj=inner_self.object),
  242. })
  243. return context
  244. return UpdateViewClass
  245. def get_delete_view(self):
  246. class DeleteViewClass(DeleteView):
  247. model = self.model
  248. template_name = self.confirm_delete_template_name
  249. success_url = reverse_lazy(self.delete_url_name)
  250. def get_context_data(inner_self, **kwargs):
  251. context = super().get_context_data(**kwargs)
  252. context.update({
  253. 'list_url_name': self.list_url_name,
  254. 'page_title': f"Delete {self.model._meta.verbose_name}",
  255. 'bs': self.get_breadcrumbs('delete', obj=inner_self.object),
  256. })
  257. return context
  258. return DeleteViewClass
  259. class DataMsCRUDView(ConfigurableCRUDView):
  260. model = DataMs
  261. list_template_name = 'legacy/datacrud_list.html'
  262. detail_template_name = 'legacy/datacrud_detail.html'
  263. form_template_name = 'legacy/datacrud_form.html'
  264. confirm_delete_template_name = 'legacy/datacrud_confirm_delete.html'
  265. filterset_class = DataMsFilter
  266. page_title = "Data Measurement"
  267. # URL name mappings
  268. list_url_name = 'legacy:datams-list'
  269. create_url_name = 'legacy:datams-create'
  270. update_url_name = 'legacy:datams-update'
  271. delete_url_name = 'legacy:datams-delete'
  272. excludes = ["splitdata"]
  273. config_field_orders = ["id", "lot_no", "code"] # Display these fields first
  274. class TbFgPressInfoLotListCRUDView(ConfigurableCRUDView):
  275. model = TbFgPressinfoLotlist
  276. list_template_name = 'legacy/datacrud_list.html'
  277. detail_template_name = 'legacy/datacrud_detail.html'
  278. form_template_name = 'legacy/datacrud_form.html'
  279. confirm_delete_template_name = 'legacy/datacrud_confirm_delete.html'
  280. filterset_class = TbFgPressFilter
  281. page_title = "Fg Press"
  282. # URL name mappings
  283. list_url_name = 'legacy:fg-list'
  284. create_url_name = 'legacy:fg-create'
  285. update_url_name = 'legacy:fg-update'
  286. delete_url_name = 'legacy:fg-delete'
  287. config_field_orders = ["productcode", "product_year"] # Display these fields first
  288. class LotSummaryCRUDView(ConfigurableCRUDView):
  289. model = LotSummary
  290. list_template_name = 'legacy/datacrud_list.html'
  291. detail_template_name = 'legacy/datacrud_detail.html'
  292. form_template_name = 'legacy/datacrud_form.html'
  293. confirm_delete_template_name = 'legacy/datacrud_confirm_delete.html'
  294. filterset_class = DataMsFilter
  295. page_title = "Lot Summary"
  296. # URL name mappings
  297. list_url_name = 'legacy:ls-list'
  298. create_url_name = 'legacy:ls-create'
  299. update_url_name = 'legacy:ls-update'
  300. delete_url_name = 'legacy:ls-delete'
  301. config_fields = ["id", "lot_no", "code", "avg", "start_time", "end_time", "grade", "created_at"] # Display these fields first
  302. config_field_orders = ["id", "lot_no", "code", "avg", "start_time", "end_time", "grade", "created_at"] # Display these fields first
  303. config_readonly_fields = ["lot_no"]
  304. # config_edit_fields = ["lot_no", "code"]
  305. ordering = ["-created_at", "-id",]