shimatta-kenkyusho/shimatta_kenkyusho/parts/views.py

1027 lines
39 KiB
Python

from django.shortcuts import render, redirect
from django.urls import resolve, reverse
from django.contrib.auth import logout, login
from django.contrib.auth.models import User
from django.utils.http import urlencode
from django.http import HttpResponse
from .navbar import NavBar
from django.contrib.auth.forms import AuthenticationForm as AuthForm
from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth import update_session_auth_hash
from django.views import View
import django.forms as forms
from django.views.generic import TemplateView, DetailView
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from .models import Storage, Stock, Component, Distributor, Manufacturer, Package
from .models import ComponentParameter, ComponentParameterType, DistributorNum, PackageParameter
from .models import ComponentType
from .qr_parser import QrCodeValidator
from django.core.paginator import Paginator
from django.core.exceptions import ValidationError
from django.db import IntegrityError
from django.db.models import ProtectedError
from .forms import *
from django.db.models import Q
from django.db.models import Prefetch
from django.db.models.functions import Lower
from django.forms import formset_factory
import uuid
ParameterSearchFormSet = formset_factory(ComponentParameterSearchForm, extra=0)
class QrSearchForm(forms.Form):
my_qr_validator = QrCodeValidator()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
qr_search = forms.CharField(label='qr_search', validators=[my_qr_validator])
class KeepSearchParamMixin(object):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
search = self.request.GET.get('search', default=None)
if search:
context['additional_params'] = urlencode({'search': search})
return context
class BaseTemplateMixin(object):
navbar_selected = ''
base_title = ''
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
base_context = {
'navbar': NavBar.get_navbar(self.navbar_selected, self.request.user),
'title': NavBar.get_brand()+' / '+ self.base_title,
'login_active': False,
}
context['base'] = base_context
return context
def post(self, request, *args, **kwargs):
data = request.POST
if 'qr_search' not in data:
super().post(request, *args, **kwargs)
print('QR',data['qr_search'])
f = QrSearchForm(data)
if f.is_valid():
return redirect(f.my_qr_validator.get_redirect_url(f.cleaned_data['qr_search']))
return self.get(request)
class ChangePasswordView(LoginRequiredMixin, BaseTemplateMixin, TemplateView):
template_name = 'parts/change-pw.html'
navbar_selected = 'Main'
base_title = 'Change Password'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['form'] = PasswordChangeForm(self.request.user)
return context
def post(self, request, *args, **kwargs):
if 'submit-change-pw' not in request.POST:
return super().post(request, *args, **kwargs)
form = PasswordChangeForm(request.user, data=request.POST)
if form.is_valid():
user = form.save()
update_session_auth_hash(request, user)
return redirect('parts-main')
else:
pass
context = self.get_context_data(**kwargs)
if form.errors:
context['form'] = form
return self.render_to_response(context)
class MainView(BaseTemplateMixin, TemplateView):
template_name = 'parts/main.html'
navbar_selected = 'Main'
base_title = 'Main'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['user'] = self.request.user
return context
def logout_view(request):
logout(request)
return redirect('parts-main')
def login_view(request):
base_context = {
'navbar': NavBar.get_navbar('Login', request.user),
'title': NavBar.get_brand()+' / '+'Login',
'login_active': True,
}
if request.user.is_authenticated:
next_param = request.GET.get('next')
if next_param is not None:
return redirect(next_param)
else:
return redirect('parts-main')
if request.method == 'POST':
form = AuthForm(data=request.POST)
if form.is_valid():
valid_user = form.get_user()
login(request, valid_user)
next_param = request.GET.get('next')
if next_param is not None:
return redirect(next_param)
else:
return redirect('parts-main')
else:
form = AuthForm()
context = {
'base': base_context,
'form': form,
}
return render(request, 'parts/login.html', context)
# Create your views here.
class ComponentTypeView(LoginRequiredMixin, BaseTemplateMixin, TemplateView):
template_name = 'parts/component-types.html'
base_title = 'Component Types'
default_page_size = 25
def filter_queryset(self, queryset, search_string):
if search_string is None or search_string == '':
return queryset
search_fragments = search_string.strip().split()
for search in search_fragments:
queryset = queryset.filter(Q(class_name__icontains = search))
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
search = self.request.GET.get('search', default=None)
page_num = self.request.GET.get('page', default=1)
context['search_string'] = search
queryset = ComponentType.objects.all()
types = self.filter_queryset(queryset, search)
comptypes = Paginator(types, self.default_page_size)
context['comptypes'] = comptypes.get_page(page_num)
return context
def post(self, request, *args, **kwargs):
return super().post(request, *args, **kwargs)
class ComponentTypeDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView):
model = ComponentType
base_title = ''
pk_url_kwarg = 'uuid'
template_name = 'parts/component-types-detail.html'
def get_breadcrumbs(self):
crumbs = self.object.get_path_components()
# Reverse list and drop the last element of the reversed list
crumbs = crumbs[::-1][:-1]
return crumbs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['breadcrumbs'] = self.get_breadcrumbs()
return context
class ComponentView(LoginRequiredMixin, KeepSearchParamMixin, BaseTemplateMixin, TemplateView):
template_name = 'parts/components.html'
base_title = 'Components'
navbar_selected = 'Components'
default_page_size = 25
def get_component_query_set(self, search_string):
queryset = Component.objects.select_related('package', 'manufacturer', 'component_type').prefetch_related('componentparameter_set').all()
if search_string is None or search_string == '':
return queryset
search_fragments = search_string.strip().split()
for search in search_fragments:
queryset = queryset.filter(Q(name__icontains = search) | Q(manufacturer__name__icontains = search) | Q(package__name__icontains = search))
return queryset
def get_component_queryset_from_advanced_search(self, cleaned_data):
queryset = Component.objects.select_related('manufacturer', 'package', 'component_type').prefetch_related('componentparameter_set').all()
if cleaned_data['name']:
queryset = queryset.filter(Q(name__icontains=cleaned_data['name']))
if cleaned_data['package']:
queryset = queryset.filter(package=cleaned_data['package'])
if cleaned_data['package_pin_count']:
queryset = queryset.filter(package__pin_count=cleaned_data['package_pin_count'])
if cleaned_data['component_type']:
queryset = queryset.filter(component_type=cleaned_data['component_type'])
if cleaned_data['distributor_num']:
if cleaned_data['distributor']:
distri = cleaned_data['distributor']
queryset = queryset.filter(Q(distributornum__distributor_part_number__icontains=cleaned_data['distributor_num']) & Q(distributornum__distributor=distri))
else:
queryset = queryset.filter(Q(distributornum__distributor_part_number__icontains=cleaned_data['distributor_num']))
if cleaned_data['manufacturer']:
queryset = queryset.filter(manufacturer=cleaned_data['manufacturer'])
return queryset
def filter_queryset_with_parameters(self, queryset, parameter, value, compare_method):
if parameter and (value is None or value == ''):
return queryset.filter(Q(componentparameter__parameter_type=parameter))
elif parameter and value is not None:
if parameter.parameter_type == 'F':
return queryset.filter(Q(componentparameter__text_value__icontains=value) & Q(componentparameter__parameter_type=parameter))
else:
if compare_method == 'lte': # <=
return queryset.filter(Q(componentparameter__value__lte=value) & Q(componentparameter__parameter_type=parameter))
elif compare_method == 'gte': # >=
return queryset.filter(Q(componentparameter__value__gte=value) & Q(componentparameter__parameter_type=parameter))
else:
return queryset.filter(Q(componentparameter__value=value) & Q(componentparameter__parameter_type=parameter))
return queryset
def get_context_data_int(self, advanced_search, parameter_formset : ParameterSearchFormSet, **kwargs):
context = super().get_context_data(**kwargs)
comp_page_num = self.request.GET.get('comp_page', default=1)
if advanced_search and parameter_formset:
search = None
context['advanced_search_shown'] = True
context['advanced_search_form'] = advanced_search
context['advanced_search_param_formset'] = parameter_formset
if advanced_search.is_valid():
paginator_queryset = self.get_component_queryset_from_advanced_search(advanced_search.cleaned_data)
else:
paginator_queryset = self.get_component_query_set(None)
# Process parameters
for f in parameter_formset:
# If the form is valid and has changed compared to its initial empty state
if f.is_valid() and f.has_changed():
paginator_queryset = self.filter_queryset_with_parameters(paginator_queryset, f.cleaned_data['parameter'], f.cleaned_data['value'], f.cleaned_data['compare_method'])
else:
search = self.request.GET.get('search', default=None)
paginator_queryset = self.get_component_query_set(search)
comp_paginator = Paginator(paginator_queryset, self.default_page_size)
context['components'] = comp_paginator.get_page(comp_page_num)
context['comp_form'] = ComponentForm()
context['search_string'] = search
if not parameter_formset:
context['advanced_search_param_formset'] = ParameterSearchFormSet()
if not advanced_search:
context['advanced_search_form'] = AdvancedComponentSearchForm(auto_id='adv_search_%s')
return context
def get_context_data(self, **kwargs):
adv_search_form = None
adv_param_search_formset = None
if 'submit-advanced-search' in self.request.GET:
adv_search_form = AdvancedComponentSearchForm(auto_id='adv_search_%s', data=self.request.GET)
adv_param_search_formset = ParameterSearchFormSet(data=self.request.GET)
if adv_search_form.is_valid():
pass
if adv_param_search_formset.is_valid():
pass
return self.get_context_data_int(advanced_search = adv_search_form, parameter_formset=adv_param_search_formset, **kwargs)
def handle_new_component_post(self, request, open=False, **kwargs):
cform = ComponentForm(data=request.POST, files=request.FILES)
new_component = None
if cform.is_valid():
new_component = cform.save()
context = self.get_context_data(**kwargs)
if not cform.is_valid():
context['comp_form'] = cform
if open and new_component:
return redirect(reverse('parts-components-detail', kwargs={'uuid':new_component.id}))
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
if 'submit-edit-component' in request.POST:
return self.handle_new_component_post(request, open=False, **kwargs)
elif 'submit-edit-component-open' in request.POST:
return self.handle_new_component_post(request, open=True, **kwargs)
else:
return super().post(request, *args, **kwargs)
class PackageView(LoginRequiredMixin, KeepSearchParamMixin, BaseTemplateMixin, TemplateView):
template_name = 'parts/packages.html'
base_title = 'Packages'
navbar_selected = 'Packages'
default_page_size = 25
def search_packages(self, search):
qs = Package.objects.all()
if not search:
return qs
search_fragments = search.strip().split()
for search in search_fragments:
if search.lower() == 'smd':
s_filter = Q(name__icontains = search) | Q(smd = True)
else:
try:
pin_count = int(search)
s_filter = Q(name__icontains = search) | Q(pin_count=pin_count)
except:
s_filter = Q(name__icontains = search)
qs = qs.filter(s_filter)
return qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
page_num = self.request.GET.get('page', default=1)
search_string = self.request.GET.get('search', default=None)
package_queryset = self.search_packages(search_string)
paginator = Paginator(package_queryset, self.default_page_size)
context['search_string'] = search_string
context['packages'] = paginator.get_page(page_num)
context['new_pkg_form'] = PackageForm()
return context
def handle_add_new_package(self, request):
form = PackageForm(data=request.POST, files=request.FILES)
if form.is_valid():
form.save()
context = self.get_context_data()
if not form.is_valid():
context['new_pkg_form'] = form
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
if 'submit-pkg-add-new' in request.POST:
return self.handle_add_new_package(request)
return super().post(request, *args, **kwargs)
class DistributorView(LoginRequiredMixin, KeepSearchParamMixin, BaseTemplateMixin, TemplateView):
template_name = 'parts/distributors.html'
base_title = 'Distributors'
navbar_selected = 'Distributors'
default_page_size = 25
def search_distributors(self, search):
qs = Distributor.objects.all()
if not search:
return qs
search_fragments = search.strip().split()
for search in search_fragments:
qs = qs.filter(Q(name__icontains = search) | Q(website__icontains = search))
return qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
page_num = self.request.GET.get('page', default=1)
search_string = self.request.GET.get('search', default=None)
queryset = self.search_distributors(search_string)
paginator = Paginator(queryset, self.default_page_size)
context['search_string'] = search_string
context['distributors'] = paginator.get_page(page_num)
context['new_distri_form'] = DistributorForm()
return context
def handle_add_new_distributor(self, request):
form = DistributorForm(data=request.POST, files=request.FILES)
if form.is_valid():
form.save()
context = self.get_context_data()
if not form.is_valid():
context['new_distri_form'] = form
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
if 'submit-distri-add-new' in request.POST:
return self.handle_add_new_distributor(request)
return super().post(request, *args, **kwargs)
class StockView(LoginRequiredMixin, BaseTemplateMixin, TemplateView):
template_name = 'parts/stocks.html'
base_title = 'Stocks'
navbar_selected = 'Stocks'
default_pagination_size = 25
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
storage_page = self.request.GET.get('storage_page')
if storage_page is None:
storage_page = 1
low_stock_page = self.request.GET.get('low_stock_page')
if low_stock_page is None:
low_stock_page = 1
storage_paginator = Paginator(Storage.objects.filter(parent_storage=None), self.default_pagination_size)
low_stock_paginator = Paginator(Stock.get_under_watermark(),
self.default_pagination_size)
context['low_stocks'] = low_stock_paginator.get_page(low_stock_page)
context['storages'] = storage_paginator.get_page(storage_page)
add_stor_form = AddSubStorageForm()
add_stor_form.fields['responsible'].initial = self.request.user.username
context['add_storage_form'] = add_stor_form
return context
def handle_add_storage(self, request, **kwargs):
return_invalid_form = False
f = AddSubStorageForm(data=request.POST)
if f.is_valid():
new_storage_name = f.cleaned_data['storage_name']
try:
resp_user = User.objects.get(username=f.cleaned_data['responsible'])
except Exception as _:
resp_user = None
f.add_error('responsible', 'Invalid Responsible User')
return_invalid_form = True
if resp_user is not None:
try:
Storage.objects.create(name=new_storage_name, responsible=resp_user, parent_storage=None)
except ValidationError as verr:
return_invalid_form = True
f.add_error('storage_name', ' .'.join(verr.messages))
else:
return_invalid_form = True
context = self.get_context_data(**kwargs)
if return_invalid_form:
context['add_storage_form'] = f
return self.render_to_response(context)
def post(self, request, **kwargs):
if 'submit-add-storage' in request.POST:
return self.handle_add_storage(request, **kwargs)
return super().post(request, **kwargs)
class StockViewDetail(LoginRequiredMixin, KeepSearchParamMixin, BaseTemplateMixin, DetailView):
template_name = 'parts/stocks-detail.html'
model = Storage
pk_url_kwarg = 'uuid'
base_title = ''
navbar_selected = 'Stocks'
default_pagination_size = 8
def get_breadcrumbs(self):
crumbs = self.object.get_path_components()
# Reverse list and drop the last element of the reversed list
crumbs = crumbs[::-1][:-1]
return crumbs
def search_stock_queryset(self, search):
stocks_in_storage = Stock.objects.filter(storage=self.object).order_by(Lower('component__name'))
if search is None or search == '':
return stocks_in_storage
if search.startswith('[comp_uuid]'):
search = search.replace('[comp_uuid]', '')
# Check if the searhc equals a UUID
test_uuid = None
try:
test_uuid = uuid.UUID(search)
except:
pass
if test_uuid is not None:
stocks_in_storage = stocks_in_storage.filter(Q(component__id = test_uuid) | Q(id= test_uuid))
else:
stocks_in_storage = stocks_in_storage.filter(Q(component__name__icontains = search) |
Q(component__package__name__icontains = search) |
Q(component__manufacturer__name__icontains = search))
return stocks_in_storage
def get_context_data(self, **kwargs):
self.base_title = 'Stocks / ' + self.object.name
context = super().get_context_data(**kwargs)
context['breadcrumbs'] = self.get_breadcrumbs()
storage_page = self.request.GET.get('storage_page', default=1)
storage_paginator = Paginator(Storage.objects.filter(parent_storage=self.object), self.default_pagination_size)
stock_search_input = self.request.GET.get('search')
componente_stock_page = self.request.GET.get('stock_page', default=1)
stock_paginator = Paginator(self.search_stock_queryset(stock_search_input), self.default_pagination_size)
context['storages'] = storage_paginator.get_page(storage_page)
stocks = stock_paginator.get_page(componente_stock_page)
context['stocks'] = stocks
context['stock_search'] = stock_search_input
add_storage_form = AddSubStorageForm()
add_storage_form.fields['responsible'].initial = self.request.user.username
context['add_storage_form'] = add_storage_form
context['delete_storage_error'] = None
context['add_stock_form'] = AddStockForm()
return context
def handle_add_storage_post(self, request, **kwargs):
f = AddSubStorageForm(data=request.POST)
if f.is_valid():
sub_name = f.cleaned_data['storage_name']
try:
user = User.objects.get(username=f.cleaned_data['responsible'])
try:
Storage.objects.create(name=sub_name, parent_storage=self.object, responsible=user)
except ValidationError as v_err:
f.add_error('storage_name', '. '.join(v_err.messages))
except:
f.add_error('responsible', 'Invalid user')
context = self.get_context_data(**kwargs)
context['add_storage_form'] = f
return self.render_to_response(context)
def handle_del_storage_post(self, request, **kwargs):
parent = self.object.parent_storage
try:
self.object.delete()
except:
context = self.get_context_data(**kwargs)
context['delete_storage_errors'] = ['Error deleting Storage '+str(self.object)]
return self.render_to_response(context)
if parent is None:
return redirect('parts-stocks')
else:
return redirect(reverse('parts-stocks-detail', kwargs={'uuid':parent.id}))
def handle_del_stock_post(self, request, **kwargs):
del_error = None
if 'stock_uuid' in request.POST:
f = DeleteStockForm(data=request.POST)
if f.is_valid():
try:
s = Stock.objects.get(id=f.cleaned_data['stock_uuid'])
print(s.storage)
print(self.object)
if s.storage == self.object:
s.delete()
else:
del_error = 'Cannot delete stock from another storage.'
except:
del_error = 'Could not find requested stock in this storage.'
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
def handle_update_watermark(self, request, **kwargs):
edit_form = EditWatermarkForm(data=request.POST)
update_watermark_error = None
if edit_form.is_valid():
edit_form.save()
else:
pass
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
def handle_amount_change_post(self, request, increase, **kwargs):
edit_form = EditStockAmountForm(data=request.POST)
if edit_form.is_valid():
edit_form.save(increase)
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
def handle_add_stock_post(self, request, **kwargs):
f = AddStockForm(data=request.POST)
error_occured = False
if f.is_valid():
try:
f.save(self.object)
except Exception as ex:
f.add_error('', str(ex))
error_occured = True
else:
error_occured = True
context = self.get_context_data(**kwargs)
if error_occured:
context['add_stock_form'] = f
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
if 'submit-add-storage' in request.POST:
return self.handle_add_storage_post(request, **kwargs)
elif 'submit-delete-storage' in request.POST:
return self.handle_del_storage_post(request, **kwargs)
elif 'submit-delete-stock' in request.POST:
return self.handle_del_stock_post(request, **kwargs)
elif 'submit-edit-watermark' in request.POST:
return self.handle_update_watermark(request, **kwargs)
elif 'submit-amount-reduce' in request.POST:
return self.handle_amount_change_post(request, False, **kwargs)
elif 'submit-amount-increase' in request.POST:
return self.handle_amount_change_post(request, True, **kwargs)
elif 'submit-add-stock' in request.POST:
return self.handle_add_stock_post(request, **kwargs)
return super().post(request, *args, **kwargs)
class ComponentDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView):
template_name = 'parts/components-detail.html'
queryset = Component.objects.select_related('component_type', 'package', 'manufacturer').prefetch_related('componentparameter_set', 'distributornum_set')
pk_url_kwarg = 'uuid'
base_title = ''
navbar_selected = 'Components'
def get_context_data(self, **kwargs):
self.base_title = 'Component / '+self.object.name
context = super().get_context_data(**kwargs)
context['component'] = self.object
context['stocks'] = Stock.objects.filter(component=self.object)
context['comp_form'] = ComponentForm(instance=self.object)
context['new_distri_num_form'] = DistributorNumberCreateForm()
context['new_param_form'] = ComponentParameterCreateForm()
context['distri_nums'] = self.object.distributornum_set.select_related('distributor').order_by('distributor__name')
context['parameters'] = self.object.componentparameter_set.order_by('parameter_type__parameter_name')
if self.object.package:
context['package_parameters'] = PackageParameter.objects.filter(package=self.object.package).order_by('parameter_type__parameter_name')
parameter_texts = self.object.get_key_parameters_as_text()
context['key_parameter_string'] = ', '.join(parameter_texts)
return context
def handle_submit_edit_component_post(self, request, **kwargs):
cform = ComponentForm(instance=self.object, data=request.POST, files=request.FILES)
if cform.is_valid():
cform.save()
context = self.get_context_data(**kwargs)
if not cform.is_valid():
context['comp_form'] = cform
return self.render_to_response(context)
def handle_submit_delete_post(self, request, **kwargs):
delete_error = None
protected_stuff = None
try:
self.object.delete()
except ProtectedError as pe:
delete_error = 'Component is protected'
protected_stuff = pe.protected_objects
except:
delete_error = 'Cannot delete component. Unknown error'
if delete_error is None:
return redirect('parts-components')
else:
context = self.get_context_data(**kwargs)
context['delete_error'] = delete_error
context['protected_stuff'] = protected_stuff
return self.render_to_response(context)
def handle_submit_new_distri_num_post(self, request, **kwargs):
form = DistributorNumberCreateForm(data=request.POST)
if form.is_valid():
new_number = form.save(commit=False)
new_number.component = self.object
try:
new_number.save()
except IntegrityError as ie:
form.add_error('__all__', 'Number for given distributor already exists')
context = self.get_context_data(**kwargs)
if not form.is_valid():
context['new_distri_num_form'] = form
return self.render_to_response(context)
def handle_submit_delete_distri_num_post(self, request, **kwargs):
form = DistributorNumberDeleteForm(data=request.POST)
if form.is_valid():
form.cleaned_data['distributor_num'].delete()
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
def handle_submit_delete_param_post(self, request, **kwargs):
form = ComponentParameterDeleteForm(data=request.POST)
if form.is_valid():
form.cleaned_data['param_num'].delete()
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
def handle_submit_new_param_post(self, request, **kwargs):
form = ComponentParameterCreateForm(data=request.POST)
if form.is_valid():
try:
form.save(self.object)
except IntegrityError:
form.add_error('__all__', 'This parameter is already set')
context = self.get_context_data(**kwargs)
if not form.is_valid():
context['new_param_form'] = form
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
if 'submit-edit-component' in request.POST:
return self.handle_submit_edit_component_post(request, **kwargs)
elif 'submit-component-delete' in request.POST:
return self.handle_submit_delete_post(request, **kwargs)
elif 'submit-create-new-distri-num' in request.POST:
return self.handle_submit_new_distri_num_post(request, **kwargs)
elif 'submit-delete-distributor-num' in request.POST:
return self.handle_submit_delete_distri_num_post(request, **kwargs)
elif 'submit-delete-param' in request.POST:
return self.handle_submit_delete_param_post(request, **kwargs)
elif 'submit-create-new-param' in request.POST:
return self.handle_submit_new_param_post(request, **kwargs)
else:
return super().post(request, *args, **kwargs)
class PackageDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView):
template_name = 'parts/packages-detail.html'
model = Package
pk_url_kwarg = 'uuid'
base_title = ''
navbar_selected = 'Packages'
def get_context_data(self, **kwargs):
self.base_title = 'Package / '+self.object.name
context = super().get_context_data(**kwargs)
context['package'] = self.object
context['edit_form'] = PackageForm(instance=self.object)
return context
def handle_delete_package(self, request):
delete_error = None
protected_objects = None
# Try to delete this instance
try:
self.object.delete()
except ProtectedError as pe:
delete_error = 'Cannot delete this package. It is referenced by a component.'
protected_objects = pe.protected_objects
except:
delete_error = 'Cannot delete this package. Unknown error'
if delete_error:
context = self.get_context_data()
context['delete_error'] = delete_error
context['protected_components'] = protected_objects
return self.render_to_response(context)
else:
return redirect('parts-packages')
def edit_package(self, request):
edit_form = PackageForm(data=request.POST, files=request.FILES, instance=self.object)
if edit_form.is_valid():
edit_form.save()
context = self.get_context_data()
if not edit_form.is_valid():
context['edit_form'] = edit_form
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
if 'submit-pkg-delete' in request.POST:
return self.handle_delete_package(request)
elif 'submit-pkg-edit' in request.POST:
return self.edit_package(request)
return super().post(request, *args, **kwargs)
class DistributorDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView):
template_name = 'parts/distributors-detail.html'
model = Distributor
pk_url_kwarg = 'uuid'
base_title = ''
navbar_selected = 'Distributors'
def get_context_data(self, **kwargs):
self.base_title = 'Distributor / '+self.object.name
context = super().get_context_data(**kwargs)
context['distributor'] = self.object
context['edit_form'] = DistributorForm(instance=self.object)
return context
def handle_delete_distributor(self, request):
delete_error = None
protected_objects = None
# Try to delete this instance
try:
self.object.delete()
except ProtectedError as pe:
delete_error = 'Cannot delete this distributor. It is referenced by a component.'
protected_objects = pe.protected_objects
except:
delete_error = 'Cannot delete this distributor. Unknown error'
if delete_error:
context = self.get_context_data()
context['delete_error'] = delete_error
context['protected_components'] = protected_objects
return self.render_to_response(context)
else:
return redirect('parts-distributors')
def edit_distributor(self, request):
edit_form = DistributorForm(data=request.POST, files=request.FILES, instance=self.object)
if edit_form.is_valid():
edit_form.save()
context = self.get_context_data()
if not edit_form.is_valid():
context['edit_form'] = edit_form
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
if 'submit-distri-delete' in request.POST:
return self.handle_delete_distributor(request)
elif 'submit-distri-edit' in request.POST:
return self.edit_distributor(request)
return super().post(request, *args, **kwargs)
class ManufacturersViewSet(LoginRequiredMixin, KeepSearchParamMixin, BaseTemplateMixin, TemplateView):
template_name = 'parts/manufacturers.html'
base_title = 'Manufacturers'
navbar_selected = 'Manufacturers'
default_page_size = 25
def search_manufacturers(self, search):
qs = Manufacturer.objects.all()
if not search:
return qs
search_fragements = search.strip().split()
for search in search_fragements:
qs = qs.filter(Q(name__icontains = search) | Q(website__icontains = search))
return qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
page_num = self.request.GET.get('page', default=1)
search_string = self.request.GET.get('search', default=None)
queryset = self.search_manufacturers(search_string)
paginator = Paginator(queryset, self.default_page_size)
context['search_string'] = search_string
context['manufacturers'] = paginator.get_page(page_num)
context['new_manufacturer_form'] = ManufacturerForm()
return context
def handle_add_new_manufacturer(self, request):
form = ManufacturerForm(data=request.POST, files=request.FILES)
if form.is_valid():
form.save()
context = self.get_context_data()
if not form.is_valid():
context['new_manufacturer_form'] = form
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
if 'submit-manufacturer-add-new' in request.POST:
return self.handle_add_new_manufacturer(request)
return super().post(request, *args, **kwargs)
class ManufacturerDetailViewSet(LoginRequiredMixin, BaseTemplateMixin, DetailView):
template_name = 'parts/manufacturers-detail.html'
model = Manufacturer
pk_url_kwarg = 'uuid'
base_title = ''
navbar_selected = 'Manufacturers'
def get_context_data(self, **kwargs):
self.base_title = 'Manufacturer / '+self.object.name
context = super().get_context_data(**kwargs)
context['manufacturer'] = self.object
context['edit_form'] = ManufacturerForm(instance=self.object)
return context
def handle_delete_manufacturer(self, request):
delete_error = None
protected_objects = None
# Try to delete this instance
try:
self.object.delete()
except ProtectedError as pe:
delete_error = 'Cannot delete this distributor. It is referenced by a component.'
protected_objects = pe.protected_objects
except:
delete_error = 'Cannot delete this distributor. Unknown error'
if delete_error:
context = self.get_context_data()
context['delete_error'] = delete_error
context['protected_components'] = protected_objects
return self.render_to_response(context)
else:
return redirect('parts-manufacturers')
def edit_manufacturer(self, request):
edit_form = ManufacturerForm(data=request.POST, files=request.FILES, instance=self.object)
if edit_form.is_valid():
edit_form.save()
context = self.get_context_data()
if not edit_form.is_valid():
context['edit_form'] = edit_form
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
if 'submit-manufacturer-delete' in request.POST:
return self.handle_delete_manufacturer(request)
elif 'submit-manufacturer-edit' in request.POST:
return self.edit_manufacturer(request)
return super().post(request, *args, **kwargs)