from django.shortcuts import render # Create your views here. from django_filters.views import FilterView from django.urls import reverse_lazy, reverse from django.views.generic import ( ListView, DetailView, CreateView, UpdateView, DeleteView, ) from django.core.paginator import Paginator from .models import Data, DataMs, TbFgPressinfoLotlist, LotSummary from .filters import DataFilter, DataMsFilter, TbFgPressFilter, LotSummaryFilter from django.urls import reverse from django.contrib import messages from pprint import pprint class DataListView(FilterView, ListView): model = Data template_name = 'legacy/data_list.html' # context_object_name = 'data_list' paginate_by = 10 # Enable pagination # Specify the filter class filterset_class = DataFilter def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Pass model fields to the template context['fields'] = [field for field in self.model._meta.get_fields()] context['bs'] = [ {'label': 'Dashboard', 'url': reverse('dashboard:index')}, {'label': 'Data', 'url': reverse('legacy:data-list')}, ] return context # Read (detail view) class DataDetailView(DetailView): model = Data template_name = 'data_detail.html' context_object_name = 'data' # Use this name in templates # Create class DataCreateView(CreateView): model = Data template_name = 'legacy/data_form.html' fields = '__all__' # Use all fields or specify a list of fields def form_valid(self, form): response = super().form_valid(form) messages.success(self.request, "Data has been successfully created!") return response def get_success_url(self): # Redirect to the edit page of the newly created object return reverse('legacy:data-update', kwargs={'pk': self.object.pk}) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Pass model fields to the template context['bs'] = [ {'label': 'Dashboard', 'url': reverse('dashboard:index')}, {'label': 'Data', 'url': reverse('legacy:data-list')}, {'label': 'Data Create', 'url': reverse('legacy:data-create')}, ] return context # Update class DataUpdateView(UpdateView): model = Data template_name = 'legacy/data_form.html' fields = '__all__' # Use all fields or specify a list of fields def get_success_url(self): # Redirect to the edit page of the newly created object return reverse('legacy:data-update', kwargs={'pk': self.object.pk}) def form_valid(self, form): response = super().form_valid(form) messages.success(self.request, "Data has been successfully updated!") return response def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Pass model fields to the template context['bs'] = [ {'label': 'Dashboard', 'url': reverse('dashboard:index')}, {'label': 'Data', 'url': reverse('legacy:data-list')}, {'label': self.object, 'url': reverse('legacy:data-update', kwargs={'pk':self.object.pk})}, ] return context # Delete class DataDeleteView(DeleteView): model = Data template_name = 'legacy/data_confirm_delete.html' success_url = reverse_lazy('legacy:data-list') # Redirect after deletion def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Pass model fields to the template context['bs'] = [ {'label': 'Dashboard', 'url': reverse('dashboard:index')}, {'label': 'Data', 'url': reverse('legacy:data-list')}, {'label': self.object, 'url': reverse('legacy:data-update', kwargs={'pk':self.object.pk})}, ] return context class ConfigurableCRUDView: model = None list_template_name = None detail_template_name = None form_template_name = None confirm_delete_template_name = None fields = '__all__' # Default to all fields paginate_by = 10 filterset_class = None page_title = "Page Title" create_url_name = None update_url_name = None delete_url_name = None list_url_name = None config_fields = "all" # "all" or a list of field names to display config_field_orders = [] # Fields to display first config_excludes = [] # Fields to exclude config_readonly_fields = [] # Fields that should be read-only in update view config_edit_fields = "__all__" # "all" or a list of field names to display ordering = None def get_fields(self): """ Dynamically generate the fields to be displayed in the list view. - Includes all fields if `config_fields` is set to "all". - Respects `config_field_orders` and `config_excludes`. Returns field instances instead of field names. """ model_fields = {f.name: f for f in self.model._meta.get_fields()} # Filter based on `config_fields` configuration fields = [] if self.config_fields != "all": fields = [model_fields[f] for f in self.config_fields if f in model_fields] else: fields = list(model_fields.values()) # pprint("------------------------") # pprint(f"fields = {fields}") # Exclude fields specified in `config_excludes` fields = [f for f in fields if f.name not in self.config_excludes] # Order fields based on `config_field_orders` ordered_fields = [f for f in fields if f.name in self.config_field_orders] remaining_fields = [f for f in fields if f.name not in self.config_field_orders] # Reorder fields to match the order specified in `config_field_orders` ordered_field_names = set(self.config_field_orders) 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)) return ordered_fields + remaining_fields def get_breadcrumbs(self, view_type, obj=None): """ Generate breadcrumbs dynamically based on the view type. :param view_type: The type of view (list, create, update, detail, delete) :param obj: The current object (if applicable) :return: A list of breadcrumb dictionaries """ breadcrumbs = [ {'label': 'Dashboard', 'url': reverse('dashboard:index')}, {'label': self.page_title, 'url': reverse(self.list_url_name)} if self.list_url_name else None, ] if view_type == 'create': breadcrumbs.append({'label': f'Create {self.model._meta.verbose_name}', 'url': None}) elif view_type == 'update' and obj: breadcrumbs.append({'label': obj, 'url': reverse(self.update_url_name, kwargs={'pk': obj.pk})}) elif view_type == 'detail' and obj: breadcrumbs.append({'label': f'Detail of {obj}', 'url': None}) elif view_type == 'delete' and obj: breadcrumbs.append({'label': f'Delete {obj}', 'url': None}) return [b for b in breadcrumbs if b] def get_list_view(self): class ListViewClass(FilterView, ListView): model = self.model template_name = self.list_template_name paginate_by = self.paginate_by filterset_class = self.filterset_class ordering = self.ordering def get_context_data(inner_self, **kwargs): context = super().get_context_data(**kwargs) fields = self.get_fields() context.update({ 'fields': [f for f in fields], # 'fields': [field for field in self.model._meta.get_fields()], 'page_title': self.page_title, 'list_url': self.list_url_name, 'create_url': self.create_url_name, 'update_url': self.update_url_name, 'delete_url': self.delete_url_name, 'bs': self.get_breadcrumbs('list'), }) return context return ListViewClass def get_detail_view(self): class DetailViewClass(DetailView): model = self.model template_name = self.detail_template_name def get_context_data(inner_self, **kwargs): context = super().get_context_data(**kwargs) context.update({ 'page_title': self.page_title, 'bs': self.get_breadcrumbs('detail'), }) return context return DetailViewClass def get_create_view(self): class CreateViewClass(CreateView): model = self.model template_name = self.form_template_name fields = self.config_edit_fields def form_valid(inner_self, form): response = super().form_valid(form) messages.success(inner_self.request, f"{self.model._meta.verbose_name} created successfully!") return response def get_success_url(inner_self): return reverse(self.update_url_name, kwargs={'pk': inner_self.object.pk}) def get_context_data(inner_self, **kwargs): context = super().get_context_data(**kwargs) context.update({ 'list_url_name': self.list_url_name, 'page_title': f"Create {self.model._meta.verbose_name}", 'bs': self.get_breadcrumbs('update', obj=inner_self.object), }) return context return CreateViewClass def get_update_view(self): class UpdateViewClass(UpdateView): model = self.model template_name = self.form_template_name fields = self.config_edit_fields def form_valid(inner_self, form): response = super().form_valid(form) messages.success(inner_self.request, f"{self.model._meta.verbose_name} updated successfully!") return response def get_form(inner_self, *args, **kwargs): """ Customize the form to make specified fields read-only. """ form = super().get_form(*args, **kwargs) for field_name in self.config_readonly_fields: if field_name in form.fields: form.fields[field_name].widget.attrs['readonly'] = True form.fields[field_name].widget.attrs['style'] = 'background-color: #f9f9f9; cursor: not-allowed;' form.fields[field_name].disabled = True # Optional: Completely disable the field return form def get_success_url(inner_self): return reverse(self.update_url_name, kwargs={'pk': inner_self.object.pk}) def get_context_data(inner_self, **kwargs): context = super().get_context_data(**kwargs) context.update({ 'list_url_name': self.list_url_name, 'page_title': f"Update {self.model._meta.verbose_name}", 'bs': self.get_breadcrumbs('update', obj=inner_self.object), }) return context return UpdateViewClass def get_delete_view(self): class DeleteViewClass(DeleteView): model = self.model template_name = self.confirm_delete_template_name success_url = reverse_lazy(self.delete_url_name) def get_context_data(inner_self, **kwargs): context = super().get_context_data(**kwargs) context.update({ 'list_url_name': self.list_url_name, 'page_title': f"Delete {self.model._meta.verbose_name}", 'bs': self.get_breadcrumbs('delete', obj=inner_self.object), }) return context return DeleteViewClass class DataMsCRUDView(ConfigurableCRUDView): model = DataMs list_template_name = 'legacy/datacrud_list.html' detail_template_name = 'legacy/datacrud_detail.html' form_template_name = 'legacy/datacrud_form.html' confirm_delete_template_name = 'legacy/datacrud_confirm_delete.html' filterset_class = DataMsFilter page_title = "Data Measurement" # URL name mappings list_url_name = 'legacy:datams-list' create_url_name = 'legacy:datams-create' update_url_name = 'legacy:datams-update' delete_url_name = 'legacy:datams-delete' excludes = ["splitdata"] config_field_orders = ["id", "lot_no", "code"] # Display these fields first class TbFgPressInfoLotListCRUDView(ConfigurableCRUDView): model = TbFgPressinfoLotlist list_template_name = 'legacy/datacrud_list.html' detail_template_name = 'legacy/datacrud_detail.html' form_template_name = 'legacy/datacrud_form.html' confirm_delete_template_name = 'legacy/datacrud_confirm_delete.html' filterset_class = TbFgPressFilter page_title = "Fg Press" # URL name mappings list_url_name = 'legacy:fg-list' create_url_name = 'legacy:fg-create' update_url_name = 'legacy:fg-update' delete_url_name = 'legacy:fg-delete' config_field_orders = ["productcode", "product_year"] # Display these fields first class LotSummaryCRUDView(ConfigurableCRUDView): model = LotSummary list_template_name = 'legacy/datacrud_list.html' detail_template_name = 'legacy/datacrud_detail.html' form_template_name = 'legacy/datacrud_form.html' confirm_delete_template_name = 'legacy/datacrud_confirm_delete.html' filterset_class = DataMsFilter page_title = "Lot Summary" # URL name mappings list_url_name = 'legacy:ls-list' create_url_name = 'legacy:ls-create' update_url_name = 'legacy:ls-update' delete_url_name = 'legacy:ls-delete' config_fields = ["id", "lot_no", "code", "avg", "start_time", "end_time", "grade", "created_at"] # Display these fields first config_field_orders = ["id", "lot_no", "code", "avg", "start_time", "end_time", "grade", "created_at"] # Display these fields first config_readonly_fields = ["lot_no"] # config_edit_fields = ["lot_no", "code"] ordering = ["-created_at", "-id",]