Bez popisu

views.py 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  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. def get_fields(self):
  115. """
  116. Dynamically generate the fields to be displayed in the list view.
  117. - Includes all fields if `config_fields` is set to "all".
  118. - Respects `config_field_orders` and `config_excludes`.
  119. Returns field instances instead of field names.
  120. """
  121. model_fields = {f.name: f for f in self.model._meta.get_fields()}
  122. # Filter based on `config_fields` configuration
  123. fields = []
  124. if self.config_fields != "all":
  125. fields = [model_fields[f] for f in self.config_fields if f in model_fields]
  126. else:
  127. fields = list(model_fields.values())
  128. pprint("------------------------")
  129. pprint(f"fields = {fields}")
  130. # Exclude fields specified in `config_excludes`
  131. fields = [f for f in fields if f.name not in self.config_excludes]
  132. # Order fields based on `config_field_orders`
  133. ordered_fields = [f for f in fields if f.name in self.config_field_orders]
  134. remaining_fields = [f for f in fields if f.name not in self.config_field_orders]
  135. # Reorder fields to match the order specified in `config_field_orders`
  136. ordered_field_names = set(self.config_field_orders)
  137. 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))
  138. return ordered_fields + remaining_fields
  139. def get_breadcrumbs(self, view_type, obj=None):
  140. """
  141. Generate breadcrumbs dynamically based on the view type.
  142. :param view_type: The type of view (list, create, update, detail, delete)
  143. :param obj: The current object (if applicable)
  144. :return: A list of breadcrumb dictionaries
  145. """
  146. breadcrumbs = [
  147. {'label': 'Dashboard', 'url': reverse('dashboard:index')},
  148. {'label': self.page_title, 'url': reverse(self.list_url_name)} if self.list_url_name else None,
  149. ]
  150. if view_type == 'create':
  151. breadcrumbs.append({'label': f'Create {self.model._meta.verbose_name}', 'url': None})
  152. elif view_type == 'update' and obj:
  153. breadcrumbs.append({'label': obj, 'url': reverse(self.update_url_name, kwargs={'pk': obj.pk})})
  154. elif view_type == 'detail' and obj:
  155. breadcrumbs.append({'label': f'Detail of {obj}', 'url': None})
  156. elif view_type == 'delete' and obj:
  157. breadcrumbs.append({'label': f'Delete {obj}', 'url': None})
  158. return [b for b in breadcrumbs if b]
  159. def get_list_view(self):
  160. class ListViewClass(FilterView, ListView):
  161. model = self.model
  162. template_name = self.list_template_name
  163. paginate_by = self.paginate_by
  164. filterset_class = self.filterset_class
  165. def get_context_data(inner_self, **kwargs):
  166. context = super().get_context_data(**kwargs)
  167. fields = self.get_fields()
  168. context.update({
  169. 'fields': [f for f in fields],
  170. # 'fields': [field for field in self.model._meta.get_fields()],
  171. 'page_title': self.page_title,
  172. 'list_url': self.list_url_name,
  173. 'create_url': self.create_url_name,
  174. 'update_url': self.update_url_name,
  175. 'delete_url': self.delete_url_name,
  176. 'bs': self.get_breadcrumbs('list'),
  177. })
  178. return context
  179. return ListViewClass
  180. def get_detail_view(self):
  181. class DetailViewClass(DetailView):
  182. model = self.model
  183. template_name = self.detail_template_name
  184. def get_context_data(inner_self, **kwargs):
  185. context = super().get_context_data(**kwargs)
  186. context.update({
  187. 'page_title': self.page_title,
  188. 'bs': self.get_breadcrumbs('detail'),
  189. })
  190. return context
  191. return DetailViewClass
  192. def get_create_view(self):
  193. class CreateViewClass(CreateView):
  194. model = self.model
  195. template_name = self.form_template_name
  196. fields = self.config_edit_fields
  197. def form_valid(inner_self, form):
  198. response = super().form_valid(form)
  199. messages.success(inner_self.request, f"{self.model._meta.verbose_name} created successfully!")
  200. return response
  201. def get_success_url(inner_self):
  202. return reverse(self.update_url_name, kwargs={'pk': inner_self.object.pk})
  203. def get_context_data(inner_self, **kwargs):
  204. context = super().get_context_data(**kwargs)
  205. context.update({
  206. 'list_url_name': self.list_url_name,
  207. 'page_title': f"Create {self.model._meta.verbose_name}",
  208. 'bs': self.get_breadcrumbs('update', obj=inner_self.object),
  209. })
  210. return context
  211. return CreateViewClass
  212. def get_update_view(self):
  213. class UpdateViewClass(UpdateView):
  214. model = self.model
  215. template_name = self.form_template_name
  216. fields = self.config_edit_fields
  217. def form_valid(inner_self, form):
  218. response = super().form_valid(form)
  219. messages.success(inner_self.request, f"{self.model._meta.verbose_name} updated successfully!")
  220. return response
  221. def get_form(inner_self, *args, **kwargs):
  222. """
  223. Customize the form to make specified fields read-only.
  224. """
  225. form = super().get_form(*args, **kwargs)
  226. for field_name in self.config_readonly_fields:
  227. if field_name in form.fields:
  228. form.fields[field_name].widget.attrs['readonly'] = True
  229. form.fields[field_name].widget.attrs['style'] = 'background-color: #f9f9f9; cursor: not-allowed;'
  230. form.fields[field_name].disabled = True # Optional: Completely disable the field
  231. return form
  232. def get_success_url(inner_self):
  233. return reverse(self.update_url_name, kwargs={'pk': inner_self.object.pk})
  234. def get_context_data(inner_self, **kwargs):
  235. context = super().get_context_data(**kwargs)
  236. context.update({
  237. 'list_url_name': self.list_url_name,
  238. 'page_title': f"Update {self.model._meta.verbose_name}",
  239. 'bs': self.get_breadcrumbs('update', obj=inner_self.object),
  240. })
  241. return context
  242. return UpdateViewClass
  243. def get_delete_view(self):
  244. class DeleteViewClass(DeleteView):
  245. model = self.model
  246. template_name = self.confirm_delete_template_name
  247. success_url = reverse_lazy(self.delete_url_name)
  248. def get_context_data(inner_self, **kwargs):
  249. context = super().get_context_data(**kwargs)
  250. context.update({
  251. 'list_url_name': self.list_url_name,
  252. 'page_title': f"Delete {self.model._meta.verbose_name}",
  253. 'bs': self.get_breadcrumbs('delete', obj=inner_self.object),
  254. })
  255. return context
  256. return DeleteViewClass
  257. class DataMsCRUDView(ConfigurableCRUDView):
  258. model = DataMs
  259. list_template_name = 'legacy/datacrud_list.html'
  260. detail_template_name = 'legacy/datacrud_detail.html'
  261. form_template_name = 'legacy/datacrud_form.html'
  262. confirm_delete_template_name = 'legacy/datacrud_confirm_delete.html'
  263. filterset_class = DataMsFilter
  264. page_title = "Data Measurement"
  265. # URL name mappings
  266. list_url_name = 'legacy:datams-list'
  267. create_url_name = 'legacy:datams-create'
  268. update_url_name = 'legacy:datams-update'
  269. delete_url_name = 'legacy:datams-delete'
  270. excludes = ["splitdata"]
  271. config_field_orders = ["id", "lot_no", "code"] # Display these fields first
  272. class TbFgPressInfoLotListCRUDView(ConfigurableCRUDView):
  273. model = TbFgPressinfoLotlist
  274. list_template_name = 'legacy/datacrud_list.html'
  275. detail_template_name = 'legacy/datacrud_detail.html'
  276. form_template_name = 'legacy/datacrud_form.html'
  277. confirm_delete_template_name = 'legacy/datacrud_confirm_delete.html'
  278. filterset_class = TbFgPressFilter
  279. page_title = "Fg Press"
  280. # URL name mappings
  281. list_url_name = 'legacy:fg-list'
  282. create_url_name = 'legacy:fg-create'
  283. update_url_name = 'legacy:fg-update'
  284. delete_url_name = 'legacy:fg-delete'
  285. config_field_orders = ["productcode", "product_year"] # Display these fields first
  286. class LotSummaryCRUDView(ConfigurableCRUDView):
  287. model = LotSummary
  288. list_template_name = 'legacy/datacrud_list.html'
  289. detail_template_name = 'legacy/datacrud_detail.html'
  290. form_template_name = 'legacy/datacrud_form.html'
  291. confirm_delete_template_name = 'legacy/datacrud_confirm_delete.html'
  292. filterset_class = DataMsFilter
  293. page_title = "Lot Summary"
  294. # URL name mappings
  295. list_url_name = 'legacy:ls-list'
  296. create_url_name = 'legacy:ls-create'
  297. update_url_name = 'legacy:ls-update'
  298. delete_url_name = 'legacy:ls-delete'
  299. config_fields = ["id", "lot_no", "code", "avg", "start_time", "end_time", "grade", "created_at"] # Display these fields first
  300. config_field_orders = ["id", "lot_no", "code", "avg", "start_time", "end_time", "grade", "created_at"] # Display these fields first
  301. config_readonly_fields = ["lot_no"]
  302. config_edit_fields = ["lot_no", "code"]