from django.shortcuts import render from django.contrib import messages # 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 core.models import MgMasterView, VMasterView, BelMasterView, EMasterView 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 = 50 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 = ["-id","-created_at"] form_class = 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 form_class = self.form_class 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 form_class = self.form_class 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 def queryFromMaster(lot_no): models = [MgMasterView, VMasterView, BelMasterView, EMasterView] value_to_filter = lot_no results = [] for model in models: queryset = model.objects.filter(PRO2=value_to_filter) results.extend(queryset) return results