diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index ccdca1389a..f5f5802278 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -35,6 +35,7 @@ INSTALLED_APPS = [ 'django_filters', 'rest_framework', 'simple_history', + 'crispy_forms', # Core django modules 'django.contrib.admin', @@ -144,3 +145,4 @@ MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') +CRISPY_TEMPLATE_PACK = 'bootstrap' diff --git a/InvenTree/part/forms.py b/InvenTree/part/forms.py new file mode 100644 index 0000000000..deaac66d30 --- /dev/null +++ b/InvenTree/part/forms.py @@ -0,0 +1,31 @@ +from django import forms +from crispy_forms.helper import FormHelper +from crispy_forms.layout import Submit + +from .models import Part + + +class EditPartForm(forms.ModelForm): + + def __init__(self, *args, **kwargs): + super(EditPartForm, self).__init__(*args, **kwargs) + self.helper = FormHelper() + + self.helper.form_id = 'id-edit-part-form' + self.helper.form_class = 'blueForms' + self.helper.form_method = 'post' + #self.helper.form_action = 'submit' + + self.helper.add_input(Submit('submit', 'Submit')) + + class Meta: + model = Part + fields = [ + 'category', + 'name', + 'description', + 'IPN', + 'URL', + 'minimum_stock', + 'trackable', + ] \ No newline at end of file diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index b1c9ac214e..5b057f74c5 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -73,6 +73,9 @@ class Part(models.Model): and can be combined to form other parts """ + def get_absolute_url(self): + return '/part/{id}/'.format(id=self.id) + # Short name of the part name = models.CharField(max_length=100) diff --git a/InvenTree/part/templates/part/delete.html b/InvenTree/part/templates/part/delete.html new file mode 100644 index 0000000000..94c5b29144 --- /dev/null +++ b/InvenTree/part/templates/part/delete.html @@ -0,0 +1,2 @@ +{% extends 'part/part_base.html' %} + diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index bbed508675..dc2629ae47 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -6,5 +6,10 @@ Part details go here... +
+ + + + {% endblock %} \ No newline at end of file diff --git a/InvenTree/part/templates/part/edit.html b/InvenTree/part/templates/part/edit.html new file mode 100644 index 0000000000..d8eb692e3b --- /dev/null +++ b/InvenTree/part/templates/part/edit.html @@ -0,0 +1,11 @@ +{% extends "part/part_base.html" %} + +{% block details %} + +Edit part information: + +{% load crispy_forms_tags %} + +{% crispy form %} + +{% endblock %} \ No newline at end of file diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index 97ee069a67..a17459b7a6 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -39,12 +39,17 @@ bom_api_urls = [ ] part_detail_urls = [ - url(r'^track/?', views.track, name='part-track'), - url(r'^bom/?', views.bom, name='part-bom'), - url(r'^stock/?', views.stock, name='part-stock'), - url(r'^used/?', views.used, name='part-used-in'), - url(r'^suppliers/?', views.suppliers, name='part-suppliers'), - url('', views.detail, name='part-detail'), + url(r'^edit/?', views.PartEdit.as_view(), name='part-edit'), + url(r'^delete/?', views.delete, name='part-delete'), + url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'), + url(r'^bom/?', views.PartDetail.as_view(template_name='part/bom.html'), name='part-bom'), + url(r'^stock/?', views.PartDetail.as_view(template_name='part/stock.html'), name='part-stock'), + url(r'^used/?', views.PartDetail.as_view(template_name='part/used_in.html'), name='part-used-in'), + url(r'^suppliers/?', views.PartDetail.as_view(template_name='part/supplier.html'), name='part-suppliers'), + + # Any other URLs go to the part detail page + #url(r'^.*$', views.detail, name='part-detail'), + url(r'^.*$', views.PartDetail.as_view(), name='part-detail'), ] # URL list for part web interface @@ -52,7 +57,7 @@ part_urls = [ # Individual url(r'^(?P\d+)/', include(part_detail_urls)), - url('list', views.index, name='part-index'), + url('list', views.PartIndex.as_view(), name='part-index'), # ex: /part/5/ url(r'^.*$', RedirectView.as_view(url='list', permanent=False), name='part-index'), diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index cccd91be98..43c26d1cc5 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -1,76 +1,50 @@ - -# Template stuff (WIP) -from django.http import HttpResponse -from django.template import loader - from InvenTree.models import FilterChildren from .models import PartCategory, Part from django.shortcuts import get_object_or_404, render from django.http import HttpResponseRedirect from django.urls import reverse -from django.views import generic -def index(request): - template = loader.get_template('part/index.html') +from django.views.generic import DetailView, ListView +from django.views.generic.edit import UpdateView - parts = Part.objects.all() +from .forms import EditPartForm - cat = None +class PartIndex(ListView): + model = Part + template_name = 'part/index.html' + context_object_name = 'parts' - if 'category' in request.GET: - cat_id = request.GET['category'] + def get_queryset(self): + self.category = self.request.GET.get('category', None) - cat = get_object_or_404(PartCategory, pk=cat_id) + return Part.objects.filter(category=self.category) - parts = parts.filter(category = cat_id) - children = PartCategory.objects.filter(parent = cat_id) + def get_context_data(self, **kwargs): - else: - parts = parts.filter(category__isnull=True) - children = PartCategory.objects.filter(parent__isnull=True) + context = super(PartIndex, self).get_context_data(**kwargs) - context = { - 'parts' : parts.order_by('category__name'), - 'category' : cat, - 'children' : children, - } + children = PartCategory.objects.filter(parent=self.category) - return HttpResponse(template.render(context, request)) + context['children'] = children + + if self.category: + context['category'] = get_object_or_404(PartCategory, pk=self.category) + + return context -def detail(request, pk): - #template = loader.get_template('detail.html') - - part = get_object_or_404(Part, pk=pk) - - return render(request, 'part/detail.html', {'part' : part}) - - #return HttpResponse("You're looking at part %s." % pk) +class PartDetail(DetailView): + context_object_name = 'part' + queryset = Part.objects.all() + template_name = 'part/detail.html' -def bom(request, pk): - part = get_object_or_404(Part, pk=pk) - - return render(request, 'part/bom.html', {'part': part}) - -def used(request, pk): - part = get_object_or_404(Part, pk=pk) - - return render(request, 'part/used_in.html', {'part': part}) - -def stock(request, pk): - part = get_object_or_404(Part, pk=pk) - - return render(request, 'part/stock.html', {'part': part}) - -def track(request, pk): - part = get_object_or_404(Part, pk=pk) - - return render(request, 'part/track.html', {'part': part}) +class PartEdit(UpdateView): + model = Part + form_class = EditPartForm + template_name = 'part/edit.html' -def suppliers(request, pk): - part = get_object_or_404(Part, pk=pk) - - return render(request, 'part/supplier.html', {'part' : part}) +def delete(request, pk): + return HttpResponseRedirect('/part/{pk}/'.format(pk=pk)) diff --git a/requirements/base.txt b/requirements/base.txt index d9c16d5ecc..f471d3db94 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -4,3 +4,4 @@ django_filter==1.0.2 django-simple-history==1.8.2 coreapi==2.3.0 pygments==2.2.0 +django-crispy-forms==1.7.2 \ No newline at end of file