Fix inline product forms POST, Add limits to default page, add all orders menu entry and GET option, fix imported modules

This commit is contained in:
Argiris Deligiannidis 2023-08-09 21:01:34 +00:00
parent cd206988ac
commit 7cb48152a0
13 changed files with 458 additions and 101 deletions

View File

@ -1,5 +1,5 @@
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Field, Fieldset, Div, HTML, ButtonHolder, Submit from crispy_forms.layout import Layout, Field, Fieldset, Div, Row, HTML, ButtonHolder, Submit
from django import forms from django import forms
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.forms.models import inlineformset_factory from django.forms.models import inlineformset_factory
@ -8,6 +8,11 @@ from django_addanother.widgets import AddAnotherWidgetWrapper
from orders_app.custom_layout_object import Formset from orders_app.custom_layout_object import Formset
from orders_app.models import Order, OrderProduct, Customer, Product, Store from orders_app.models import Order, OrderProduct, Customer, Product, Store
from .models import *
from .custom_layout_object import Formset
import re
class CustomerForm(forms.ModelForm): class CustomerForm(forms.ModelForm):
class Meta: class Meta:
@ -78,6 +83,7 @@ class StoreForm(forms.ModelForm):
class OrderLine(forms.ModelForm): class OrderLine(forms.ModelForm):
class Meta: class Meta:
model = OrderProduct model = OrderProduct
exclude = ()
fields = ['id', 'order', 'product', 'amount', 'cake_type', 'cake_type_num', 'cake_color', 'cake_color_other', 'fyt_color', 'fyt_color_other', 'cake_flavor', 'cake_img', 'cream_cake_3d', 'cream_cake_height', 'cream_cake_img', 'engagement_cake_type', 'engagement_cake_base', 'engagement_cake_pcs', 'engagement_cake_pcs_other', 'engagement_cake_glaze', 'cup_flavor', 'cup_color', 'cup_color_other', 'cup_type', 'candy_bar_type', 'candy_bar_decor', 'candy_bar_decor_other', 'candy_bar_wrap', 'info'] fields = ['id', 'order', 'product', 'amount', 'cake_type', 'cake_type_num', 'cake_color', 'cake_color_other', 'fyt_color', 'fyt_color_other', 'cake_flavor', 'cake_img', 'cream_cake_3d', 'cream_cake_height', 'cream_cake_img', 'engagement_cake_type', 'engagement_cake_base', 'engagement_cake_pcs', 'engagement_cake_pcs_other', 'engagement_cake_glaze', 'cup_flavor', 'cup_color', 'cup_color_other', 'cup_type', 'candy_bar_type', 'candy_bar_decor', 'candy_bar_decor_other', 'candy_bar_wrap', 'info']
widgets = { widgets = {
'product': AddAnotherWidgetWrapper( 'product': AddAnotherWidgetWrapper(
@ -92,9 +98,13 @@ class OrderLine(forms.ModelForm):
'info': forms.Textarea(attrs={'rows': 2, 'cols': 30}), 'info': forms.Textarea(attrs={'rows': 2, 'cols': 30}),
} }
def __init__(self, *arg, **kwarg): def __init__(self, *args, **kwargs):
super(OrderLine, self).__init__(*arg, **kwarg) super().__init__(*args, **kwargs)
self.empty_permitted = False
formtag_prefix = re.sub('-[0-9]+$', '', kwargs.get('prefix', ''))
self.helper = FormHelper()
self.helper.form_tag = False
self.fields['product'].label = "Προϊόν" self.fields['product'].label = "Προϊόν"
self.fields['amount'].label = "Ποσότητα" self.fields['amount'].label = "Ποσότητα"
self.fields['cake_type'].label = "Τύπος" self.fields['cake_type'].label = "Τύπος"
@ -122,6 +132,40 @@ class OrderLine(forms.ModelForm):
self.fields['candy_bar_decor_other'].label = "Ντεκόρ CandyBar Άλλο" self.fields['candy_bar_decor_other'].label = "Ντεκόρ CandyBar Άλλο"
self.fields['candy_bar_wrap'].label = "Τύλιγμα CandyBar" self.fields['candy_bar_wrap'].label = "Τύλιγμα CandyBar"
self.fields['info'].label = "Πληροφορίες" self.fields['info'].label = "Πληροφορίες"
self.helper.layout = Layout(
Row(
Field('product'),
Field('amount'),
Field('cake_type'),
Field('cake_type_num'),
Field('cake_color'),
Field('cake_color_other'),
Field('fyt_color'),
Field('fyt_color_other'),
Field('cake_flavor'),
Field('cake_img'),
Field('cream_cake_3d'),
Field('cream_cake_height'),
Field('cream_cake_img'),
Field('engagement_cake_type'),
Field('engagement_cake_base'),
Field('engagement_cake_pcs'),
Field('engagement_cake_pcs_other'),
Field('engagement_cake_glaze'),
Field('cup_flavor'),
Field('cup_color'),
Field('cup_color_other'),
Field('cup_type'),
Field('candy_bar_type'),
Field('candy_bar_decor'),
Field('candy_bar_decor_other'),
Field('candy_bar_wrap'),
Field('info'),
Field('DELETE'),
css_class='formset_row-{}'.format(formtag_prefix)
)
)
OrderLineFormSet = inlineformset_factory( OrderLineFormSet = inlineformset_factory(
@ -138,6 +182,7 @@ OrderLineFormSetEdit = inlineformset_factory(
class OrderForm(forms.ModelForm): class OrderForm(forms.ModelForm):
class Meta: class Meta:
model = Order model = Order
exclude = ()
fields = ['order_status', 'customer_name', 'customer_address', 'customer_telephone', 'customer_email', 'delivery', 'delivery_date', 'store', 'order_info', 'order_products'] fields = ['order_status', 'customer_name', 'customer_address', 'customer_telephone', 'customer_email', 'delivery', 'delivery_date', 'store', 'order_info', 'order_products']
widgets = { widgets = {
'delivery_date': forms.DateInput(attrs={'type': 'text', 'id': 'delivery_date', 'class': 'datepicker'}), 'delivery_date': forms.DateInput(attrs={'type': 'text', 'id': 'delivery_date', 'class': 'datepicker'}),
@ -153,7 +198,7 @@ class OrderForm(forms.ModelForm):
super(OrderForm, self).__init__(*args, **kwargs) super(OrderForm, self).__init__(*args, **kwargs)
self.helper = FormHelper() self.helper = FormHelper()
self.helper.form_tag = True self.helper.form_tag = True
self.helper.render_hidden_fields = True #self.helper.render_hidden_fields = True
self.helper.form_class = 'form-horizontal' self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-md-3 create-label' self.helper.label_class = 'col-md-3 create-label'
self.helper.field_class = 'col-md-9' self.helper.field_class = 'col-md-9'

View File

@ -3,7 +3,6 @@ from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import models from django.db import models
from phonenumber_field.modelfields import PhoneNumberField from phonenumber_field.modelfields import PhoneNumberField
class Store(models.Model): class Store(models.Model):
name = models.CharField(max_length=128) name = models.CharField(max_length=128)
address = models.CharField(max_length=128) address = models.CharField(max_length=128)
@ -190,7 +189,7 @@ class OrderProduct(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE) product = models.ForeignKey(Product, on_delete=models.CASCADE)
amount = models.FloatField(validators=[MinValueValidator(0.01), MaxValueValidator(999)]) amount = models.FloatField(validators=[MinValueValidator(0.01), MaxValueValidator(999)])
#az = 'ΚΙΛΑ ΓΕΥΣΗ KARDASIS Νο ΧΡΩΜΑ ΦΥΤΙΛΑΚΙ ΠΑΡΑΤΗΡΗΣΕΙΣ' #vars = 'ΚΙΛΑ ΓΕΥΣΗ KARDASIS Νο ΧΡΩΜΑ ΦΥΤΙΛΑΚΙ ΠΑΡΑΤΗΡΗΣΕΙΣ'
cake_type = models.CharField(max_length=45, choices=CAKE_TYPES, blank=True, null=True) cake_type = models.CharField(max_length=45, choices=CAKE_TYPES, blank=True, null=True)
cake_type_num = models.FloatField(max_length=128, default="0", blank=True, null=True) cake_type_num = models.FloatField(max_length=128, default="0", blank=True, null=True)
cake_color = models.CharField(max_length=45, choices=COLOR_OPTIONS, blank=True, null=True) cake_color = models.CharField(max_length=45, choices=COLOR_OPTIONS, blank=True, null=True)
@ -199,19 +198,19 @@ class OrderProduct(models.Model):
fyt_color_other = models.CharField(max_length=128, blank=True, null=True) fyt_color_other = models.CharField(max_length=128, blank=True, null=True)
cake_flavor = models.CharField(max_length=45, choices=CAKE_FLAVORS, blank=True, null=True) cake_flavor = models.CharField(max_length=45, choices=CAKE_FLAVORS, blank=True, null=True)
cake_img = models.ImageField(blank=True, null=True) cake_img = models.ImageField(blank=True, null=True)
#az = 'ΜΕΓΕΘΟΣ ΥΨΟΣ ΓΕΥΣΗ ΠΑΡΑΤΗΡΗΣΕΙΣ' #vars = 'ΜΕΓΕΘΟΣ ΥΨΟΣ ΓΕΥΣΗ ΠΑΡΑΤΗΡΗΣΕΙΣ'
cream_cake_3d = models.CharField(max_length=45, choices=CREAM_3D, default="ΟΧΙ", blank=True) cream_cake_3d = models.CharField(max_length=45, choices=CREAM_3D, default="ΟΧΙ", blank=True)
cream_cake_height = models.FloatField(max_length=128, default="0", blank=True, null=True) cream_cake_height = models.FloatField(max_length=128, default="0", blank=True, null=True)
cream_cake_img = models.ImageField(blank=True, null=True) cream_cake_img = models.ImageField(blank=True, null=True)
#az = 'ΓΑΜΟΣ ΒΑΣΗ ΤΕΜΑΧΙΑ ΓΕΥΣΗ ΠΑΡΑΤΗΡΗΣΕΙΣ' #vars = 'ΓΑΜΟΣ ΒΑΣΗ ΤΕΜΑΧΙΑ ΓΕΥΣΗ ΠΑΡΑΤΗΡΗΣΕΙΣ'
engagement_cake_type = models.CharField(max_length=45, choices=ENGAMENT_TYPE, blank=True, null=True) engagement_cake_type = models.CharField(max_length=45, choices=ENGAMENT_TYPE, blank=True, null=True)
engagement_cake_base = models.CharField(max_length=128, blank=True, null=True) engagement_cake_base = models.CharField(max_length=128, blank=True, null=True)
engagement_cake_pcs = models.CharField(max_length=45, choices=ENGAMENT_CAKE_PIECES, blank=True, null=True) engagement_cake_pcs = models.CharField(max_length=45, choices=ENGAMENT_CAKE_PIECES, blank=True, null=True)
engagement_cake_pcs_other = models.CharField(max_length=128, blank=True, null=True) engagement_cake_pcs_other = models.CharField(max_length=128, blank=True, null=True)
engagement_cake_glaze = models.CharField(max_length=45, choices=ENGAMENT_CAKE_GLAZE, blank=True, null=True) engagement_cake_glaze = models.CharField(max_length=45, choices=ENGAMENT_CAKE_GLAZE, blank=True, null=True)
#az = 'ΤΕΜΑΧΙΑ ΓΕΥΣΗ ΚΥΠΕΛΛΟ ΧΡΩΜΑ ΤΕΜΑΧΙΑ ΧΡΩΜΑ ΔΙΑΚΟΣΜΗΣΗ ΤΥΛΙΓΜΕΝΑ ΠΑΡΑΤΗΡΗΣΕΙΣ' #vars = 'ΤΕΜΑΧΙΑ ΓΕΥΣΗ ΚΥΠΕΛΛΟ ΧΡΩΜΑ ΤΕΜΑΧΙΑ ΧΡΩΜΑ ΔΙΑΚΟΣΜΗΣΗ ΤΥΛΙΓΜΕΝΑ ΠΑΡΑΤΗΡΗΣΕΙΣ'
cup_flavor = models.CharField(max_length=45, choices=CUP_FLAVORS, blank=True, null=True) cup_flavor = models.CharField(max_length=45, choices=CUP_FLAVORS, blank=True, null=True)
cup_color = models.CharField(max_length=45, choices=COLOR_OPTIONS, blank=True, null=True) cup_color = models.CharField(max_length=45, choices=COLOR_OPTIONS, blank=True, null=True)
cup_color_other = models.CharField(max_length=128, blank=True, null=True) cup_color_other = models.CharField(max_length=128, blank=True, null=True)

View File

@ -7,6 +7,9 @@ sp1!glk2
spiti3 spiti3
sp4$glku3 sp4$glku3
spiti4
sp5%glku4
pronorth pronorth
pro1!north123!@# pro1!north123!@#

View File

@ -15,6 +15,10 @@ from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas from reportlab.pdfgen import canvas
from textwrap import wrap from textwrap import wrap
from .models import *
from .forms import *
from django.views.generic.edit import CreateView, UpdateView
from django.db import transaction
from orders_app.forms import OrderForm, OrderLineFormSet, CustomerForm, ProductForm, StoreForm,\ from orders_app.forms import OrderForm, OrderLineFormSet, CustomerForm, ProductForm, StoreForm,\
@ -270,14 +274,36 @@ class DashboardPageView(LoginRequiredMixin, TemplateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
time_delta = datetime.today() - timedelta(days=30) time_delta = datetime.today() - timedelta(days=90)
try:
all_orders = self.request.GET['all_orders']
except KeyError:
all_orders = False
if self.request.user.id == 3: if self.request.user.id == 3:
context["DB_Objects"] = Order.objects.filter(store=1).filter(order_date__gte=time_delta).order_by('id').reverse() if all_orders:
context["DB_Objects"] = Order.objects.filter(store_id=3).order_by('id').reverse()
else:
context["DB_Objects"] = Order.objects.filter(store_id=3).filter(order_date__gte=time_delta).order_by('id').reverse()
elif self.request.user.id == 4: elif self.request.user.id == 4:
context["DB_Objects"] = Order.objects.filter(store=2).filter(order_date__gte=time_delta).order_by('id').reverse() if all_orders:
context["DB_Objects"] = Order.objects.filter(store_id=4).order_by('id').reverse()
else:
context["DB_Objects"] = Order.objects.filter(store_id=4).filter(order_date__gte=time_delta).order_by('id').reverse()
elif self.request.user.id == 5: elif self.request.user.id == 5:
context["DB_Objects"] = Order.objects.filter(store=3).filter(order_date__gte=time_delta).order_by('id').reverse() if all_orders:
context["DB_Objects"] = Order.objects.filter(store_id=5).order_by('id').reverse()
else:
context["DB_Objects"] = Order.objects.filter(store_id=5).filter(order_date__gte=time_delta).order_by('id').reverse()
elif self.request.user.id == 6:
if all_orders:
context["DB_Objects"] = Order.objects.filter(store_id=6).order_by('id').reverse()
else:
context["DB_Objects"] = Order.objects.filter(store_id=6).filter(order_date__gte=time_delta).order_by('id').reverse()
elif self.request.user.id == 7:
if all_orders:
context["DB_Objects"] = Order.objects.filter(store_id=7).order_by('id').reverse()
else:
context["DB_Objects"] = Order.objects.filter(store_id=7).filter(order_date__gte=time_delta).order_by('id').reverse()
else: else:
context["DB_Objects"] = Order.objects.filter(order_date__gte=time_delta).order_by('id').reverse() context["DB_Objects"] = Order.objects.filter(order_date__gte=time_delta).order_by('id').reverse()
context["active_page"] = 'dashboard' context["active_page"] = 'dashboard'
@ -297,24 +323,32 @@ class ProductPageView(LoginRequiredMixin, TemplateView):
class OrderProductsPageView(LoginRequiredMixin, TemplateView): class OrderProductsPageView(LoginRequiredMixin, TemplateView):
template_name = "diaxeirisi/Dashboard.OrderProducts.html" template_name = "diaxeirisi/Dashboard.OrderProducts.html"
time_delta = datetime.today() - timedelta(days=30)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
print(self.request.user.id)
if self.request.user.id == 3: if self.request.user.id == 3:
order_ids = Order.objects.filter(store=1).filter(order_date__gte=time_delta).order_by('id').reverse() order_ids = Order.objects.filter(store_id=3).order_by('-id')[:200]
order_ids = list(answer.id for answer in order_ids) order_ids = list(answer.id for answer in order_ids)
context["DB_Objects"] = OrderProduct.objects.filter(order_id__in=order_ids) context["DB_Objects"] = OrderProduct.objects.filter(order_id__in=order_ids)
elif self.request.user.id == 4: elif self.request.user.id == 4:
order_ids = Order.objects.filter(store=2).filter(order_date__gte=time_delta).order_by('id').reverse() order_ids = Order.objects.filter(store_id=4).order_by('-id')[:200]
order_ids = list(answer.id for answer in order_ids) order_ids = list(answer.id for answer in order_ids)
context["DB_Objects"] = OrderProduct.objects.filter(order_id__in=order_ids) context["DB_Objects"] = OrderProduct.objects.filter(order_id__in=order_ids)
elif self.request.user.id == 5: elif self.request.user.id == 5:
order_ids = Order.objects.filter(store=3).filter(order_date__gte=time_delta).order_by('id').reverse() order_ids = Order.objects.filter(store_id=5).order_by('-id')[:200]
order_ids = list(answer.id for answer in order_ids)
context["DB_Objects"] = OrderProduct.objects.filter(order_id__in=order_ids)
elif self.request.user.id == 6:
order_ids = Order.objects.filter(store_id=6).order_by('-id')[:200]
order_ids = list(answer.id for answer in order_ids)
context["DB_Objects"] = OrderProduct.objects.filter(order_id__in=order_ids)
elif self.request.user.id == 7:
order_ids = Order.objects.filter(store_id=7).order_by('-id')[:200]
order_ids = list(answer.id for answer in order_ids) order_ids = list(answer.id for answer in order_ids)
context["DB_Objects"] = OrderProduct.objects.filter(order_id__in=order_ids) context["DB_Objects"] = OrderProduct.objects.filter(order_id__in=order_ids)
else: else:
context["DB_Objects"] = OrderProduct.objects.all().filter(order_date__gte=time_delta).order_by('id').reverse() context["DB_Objects"] = OrderProduct.objects.all().order_by('-id')[:200]
context["active_page"] = 'products' context["active_page"] = 'products'
return context return context
@ -449,6 +483,7 @@ class OrderUpdate(UpdateView):
form_class = OrderForm form_class = OrderForm
template_name = 'orders/order_create.html' template_name = 'orders/order_create.html'
def get_success_url(self): def get_success_url(self):
return reverse_lazy('orders_app:order_update', kwargs={'pk': self.object.pk}) return reverse_lazy('orders_app:order_update', kwargs={'pk': self.object.pk})
@ -458,25 +493,27 @@ class OrderUpdate(UpdateView):
def get_order_id(self): def get_order_id(self):
return self.kwargs['pk'] return self.kwargs['pk']
def get_context_data(self, **kwargs):
context = super(OrderUpdate, self).get_context_data(**kwargs) def get_context_data(self, *args, **kwargs):
data = super(OrderUpdate, self).get_context_data(**kwargs)
if self.request.POST: if self.request.POST:
context['order_products'] = OrderLineFormSetEdit(self.request.POST, self.request.FILES, instance=self.object) data['order_products'] = OrderLineFormSetEdit(self.request.POST, instance=self.object)
else: else:
context['order_products'] = OrderLineFormSetEdit(instance=self.object) data['order_products'] = OrderLineFormSetEdit(instance=self.object)
return context return data
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
order_data = Order.objects.get(id=self.get_order_id()) order_data = Order.objects.get(id=self.get_order_id())
#order_line_data = OrderProduct.objects.filter(order=self.get_order_id()) #order_line_data = OrderProduct.objects.filter(order=self.get_order_id())
form = OrderForm(self.request.POST, self.request.FILES, instance=order_data) #, initial={model_to_dict(order_data)} form = OrderForm(self.request.POST, self.request.FILES, instance=order_data) #, initial={model_to_dict(order_data)}
order_products = OrderLineFormSetEdit(self.request.POST, self.request.FILES, instance=form.instance) order_products = OrderLineFormSetEdit(self.request.POST, self.request.FILES, instance=form.instance)
if form.is_valid() and order_products.is_valid(): if form.is_valid() and order_products.is_valid():
form.save() form.save()
for inline_form in order_products: for inline_form in order_products:
if not inline_form.cleaned_data['DELETE']:
inline_form.save() inline_form.save()
messages.success(self.request, "Η παραγγελία αποθηκευτηκέ") messages.success(self.request, "Η παραγγελία αποθηκευτηκέ")
return HttpResponseRedirect(request.META['HTTP_REFERER']) return HttpResponseRedirect(request.META['HTTP_REFERER'])
else: else:

View File

@ -0,0 +1,248 @@
/**
* jQuery Formset 1.5-pre
* @author Stanislaus Madueke (stan DOT madueke AT gmail DOT com)
* @requires jQuery 1.2.6 or later
*
* Copyright (c) 2009, Stanislaus Madueke
* All rights reserved.
*
* Licensed under the New BSD License
* See: http://www.opensource.org/licenses/bsd-license.php
*/
;(function($) {
$.fn.formset = function(opts)
{
var options = $.extend({}, $.fn.formset.defaults, opts),
flatExtraClasses = options.extraClasses.join(' '),
totalForms = $('#id_' + options.prefix + '-TOTAL_FORMS'),
maxForms = $('#id_' + options.prefix + '-MAX_NUM_FORMS'),
minForms = $('#id_' + options.prefix + '-MIN_NUM_FORMS'),
childElementSelector = 'input,select,textarea,label,div',
$$ = $(this),
applyExtraClasses = function(row, ndx) {
if (options.extraClasses) {
row.removeClass(flatExtraClasses);
row.addClass(options.extraClasses[ndx % options.extraClasses.length]);
}
},
updateElementIndex = function(elem, prefix, ndx) {
var idRegex = new RegExp(prefix + '-(\\d+|__prefix__)-'),
replacement = prefix + '-' + ndx + '-';
if (elem.attr("for")) elem.attr("for", elem.attr("for").replace(idRegex, replacement));
if (elem.attr('id')) elem.attr('id', elem.attr('id').replace(idRegex, replacement));
if (elem.attr('name')) elem.attr('name', elem.attr('name').replace(idRegex, replacement));
},
hasChildElements = function(row) {
return row.find(childElementSelector).length > 0;
},
showAddButton = function() {
return maxForms.length == 0 || // For Django versions pre 1.2
(maxForms.val() == '' || (maxForms.val() - totalForms.val() > 0));
},
/**
* Indicates whether delete link(s) can be displayed - when total forms > min forms
*/
showDeleteLinks = function() {
return minForms.length == 0 || // For Django versions pre 1.7
(minForms.val() == '' || (totalForms.val() - minForms.val() > 0));
},
insertDeleteLink = function(row) {
var delCssSelector = $.trim(options.deleteCssClass).replace(/\s+/g, '.'),
addCssSelector = $.trim(options.addCssClass).replace(/\s+/g, '.');
var delButtonHTML = '<a class="' + options.deleteCssClass + '" href="javascript:void(0);">' + options.deleteText +'</a>';
if (options.deleteContainerClass) {
// If we have a specific container for the remove button,
// place it as the last child of that container:
row.find('[class*="' + options.deleteContainerClass + '"]').append(delButtonHTML);
} else if (row.is('TR')) {
// If the forms are laid out in table rows, insert
// the remove button into the last table cell:
row.children(':last').append(delButtonHTML);
} else if (row.is('UL') || row.is('OL')) {
// If they're laid out as an ordered/unordered list,
// insert an <li> after the last list item:
row.append('<li>' + delButtonHTML + '</li>');
} else {
// Otherwise, just insert the remove button as the
// last child element of the form's container:
row.append(delButtonHTML);
}
// Check if we're under the minimum number of forms - not to display delete link at rendering
if (!showDeleteLinks()){
row.find('a.' + delCssSelector).hide();
}
row.find('a.' + delCssSelector).click(function() {
var row = $(this).parents('.' + options.formCssClass),
del = row.find('input:hidden[id $= "-DELETE"]'),
buttonRow = row.siblings("a." + addCssSelector + ', .' + options.formCssClass + '-add'),
forms;
if (del.length) {
// We're dealing with an inline formset.
// Rather than remove this form from the DOM, we'll mark it as deleted
// and hide it, then let Django handle the deleting:
del.val('on');
row.hide();
forms = $('.' + options.formCssClass).not(':hidden');
totalForms.val(forms.length);
} else {
row.remove();
// Update the TOTAL_FORMS count:
forms = $('.' + options.formCssClass).not('.formset-custom-template');
totalForms.val(forms.length);
}
for (var i=0, formCount=forms.length; i<formCount; i++) {
// Apply `extraClasses` to form rows so they're nicely alternating:
applyExtraClasses(forms.eq(i), i);
if (!del.length) {
// Also update names and IDs for all child controls (if this isn't
// a delete-able inline formset) so they remain in sequence:
forms.eq(i).find(childElementSelector).each(function() {
updateElementIndex($(this), options.prefix, i);
});
}
}
// Check if we've reached the minimum number of forms - hide all delete link(s)
if (!showDeleteLinks()){
$('a.' + delCssSelector).each(function(){$(this).hide();});
}
// Check if we need to show the add button:
if (buttonRow.is(':hidden') && showAddButton()) buttonRow.show();
// If a post-delete callback was provided, call it with the deleted form:
if (options.removed) options.removed(row);
return false;
});
};
$$.each(function(i) {
var row = $(this),
del = row.find('input:checkbox[id $= "-DELETE"]');
if (del.length) {
// If you specify "can_delete = True" when creating an inline formset,
// Django adds a checkbox to each form in the formset.
// Replace the default checkbox with a hidden field:
if (del.is(':checked')) {
// If an inline formset containing deleted forms fails validation, make sure
// we keep the forms hidden (thanks for the bug report and suggested fix Mike)
del.before('<input type="hidden" name="' + del.attr('name') +'" id="' + del.attr('id') +'" value="on" />');
row.hide();
} else {
del.before('<input type="hidden" name="' + del.attr('name') +'" id="' + del.attr('id') +'" />');
}
// Hide any labels associated with the DELETE checkbox:
$('label[for="' + del.attr('id') + '"]').hide();
del.remove();
}
if (hasChildElements(row)) {
row.addClass(options.formCssClass);
insertDeleteLink(row);
applyExtraClasses(row, i);
}
});
if ($$.length) {
var hideAddButton = !showAddButton(),
addButton, template;
if (options.formTemplate) {
// If a form template was specified, we'll clone it to generate new form instances:
template = (options.formTemplate instanceof $) ? options.formTemplate : $(options.formTemplate);
template.removeAttr('id').addClass(options.formCssClass + ' formset-custom-template');
template.find(childElementSelector).each(function() {
updateElementIndex($(this), options.prefix, '__prefix__');
});
insertDeleteLink(template);
} else {
// Otherwise, use the last form in the formset; this works much better if you've got
// extra (>= 1) forms (thnaks to justhamade for pointing this out):
if (options.hideLastAddForm) $('.' + options.formCssClass + ':last').hide();
template = $('.' + options.formCssClass + ':last').clone(true).removeAttr('id');
template.find('input:hidden[id $= "-DELETE"]').remove();
// Clear all cloned fields, except those the user wants to keep (thanks to brunogola for the suggestion):
template.find(childElementSelector).not(options.keepFieldValues).each(function() {
var elem = $(this);
// If this is a checkbox or radiobutton, uncheck it.
// This fixes Issue 1, reported by Wilson.Andrew.J:
if (elem.is('input:checkbox') || elem.is('input:radio')) {
elem.attr('checked', false);
} else {
elem.val('');
}
});
}
// FIXME: Perhaps using $.data would be a better idea?
options.formTemplate = template;
var addButtonHTML = '<a class="' + options.addCssClass + '" href="javascript:void(0);">' + options.addText + '</a>';
if (options.addContainerClass) {
// If we have a specific container for the "add" button,
// place it as the last child of that container:
var addContainer = $('[class*="' + options.addContainerClass + '"');
addContainer.append(addButtonHTML);
addButton = addContainer.find('[class="' + options.addCssClass + '"]');
} else if ($$.is('TR')) {
// If forms are laid out as table rows, insert the
// "add" button in a new table row:
var numCols = $$.eq(0).children().length, // This is a bit of an assumption :|
buttonRow = $('<tr><td colspan="' + numCols + '">' + addButtonHTML + '</tr>').addClass(options.formCssClass + '-add');
$$.parent().append(buttonRow);
addButton = buttonRow.find('a');
} else {
// Otherwise, insert it immediately after the last form:
$$.filter(':last').after(addButtonHTML);
addButton = $$.filter(':last').next();
}
if (hideAddButton) addButton.hide();
addButton.click(function() {
var formCount = parseInt(totalForms.val()),
row = options.formTemplate.clone(true).removeClass('formset-custom-template'),
buttonRow = $($(this).parents('tr.' + options.formCssClass + '-add').get(0) || this),
delCssSelector = $.trim(options.deleteCssClass).replace(/\s+/g, '.');
applyExtraClasses(row, formCount);
row.insertBefore(buttonRow).show();
row.find(childElementSelector).each(function() {
updateElementIndex($(this), options.prefix, formCount);
});
totalForms.val(formCount + 1);
// Check if we're above the minimum allowed number of forms -> show all delete link(s)
if (showDeleteLinks()){
$('a.' + delCssSelector).each(function(){$(this).show();});
}
// Check if we've exceeded the maximum allowed number of forms:
if (!showAddButton()) buttonRow.hide();
// If a post-add callback was supplied, call it with the added form:
if (options.added) options.added(row);
return false;
});
}
return $$;
};
/* Setup plugin defaults */
$.fn.formset.defaults = {
prefix: 'form', // The form prefix for your django formset
formTemplate: null, // The jQuery selection cloned to generate new form instances
addText: 'add another', // Text for the add link
deleteText: 'remove', // Text for the delete link
addContainerClass: null, // Container CSS class for the add link
deleteContainerClass: null, // Container CSS class for the delete link
addCssClass: 'add-row', // CSS class applied to the add link
deleteCssClass: 'delete-row', // CSS class applied to the delete link
formCssClass: 'dynamic-form', // CSS class applied to each form in a formset
extraClasses: [], // Additional CSS classes, which will be applied to each form in turn
keepFieldValues: '', // jQuery selector for fields whose values should be kept when the form is cloned
added: null, // Function called each time a new form is added
removed: null, // Function called each time a form is deleted
hideLastAddForm: false // When set to true, hide last empty add form (becomes visible when clicking on add button)
};
})(jQuery);

View File

@ -122,14 +122,19 @@
</li> </li>
<li> <li>
<a href="/dx"> <a href="/dx">
<i class="simple-icon-book-open"></i> <span class="d-inline-block">Παραγγελίες Μήνα</span> <i class="simple-icon-book-open"></i> <span class="d-inline-block">Παραγγελίες 3μήνου</span>
</a>
</li>
<li>
<a href="/dx?all_orders=true">
<i class="simple-icon-folder-alt"></i> <span class="d-inline-block">Όλες οι Παραγγελίες</span>
</a> </a>
</li> </li>
</ul> </ul>
<ul class="list-unstyled" data-link="products"> <ul class="list-unstyled" data-link="products">
<li> <li>
<a href="/dx/order_products/"> <a href="/dx/order_products/">
<i class="simple-icon-basket-loaded"></i> <span class="d-inline-block">Προϊόντα Παραγγελιών</span> <i class="simple-icon-basket-loaded"></i> <span class="d-inline-block">Προϊόντα Παραγγελιών (μέχρι 200)</span>
</a> </a>
</li> </li>
<li> <li>

View File

@ -1,69 +1,36 @@
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% load static %} {% load static %}
{% if 'order/update' in current_view %}
<p class="badge badge-outline-warning mb-1">*Για να <b>διαγράψουμε</b> προϊόντα επιλέγουμε τη διαγραφή σε όσα θέλουμε και πατάμε Αποθήκευση. <b>ΔΕΝ</b> πατάμε αφαίρεση.
<button type="button" class="badge badge-pill badge-warning mb-1" data-toggle="modal" data-target="#myModal"> Παράδειγμα</button> {% block css %}
<div id="myModal" class="modal fade" tabindex="-1" role="dialog"> <style>
<div class="modal-dialog"> .delete-row {
<div class="modal-content"> align-self: center;
<div class="modal-body"> }
<p>Παράδειγμα:</p> .form-row {
<hr> margin: 20px;
<img src="{% static 'images/empty_form.png' %}" width="100%" class="img-responsive"> border-bottom: 5px solid #1a0505;
</div> }
</div> .form-group{
</div> margin: 20px;
</div> }
<br>
</p> [id^="id_orderproduct_set"]{
</div> width: 110%;
{% endif %} }
<table class="table table-striped col-md-10" style="margin-left: 10px;"> </style>
{% endblock css %}
{{ formset.management_form|crispy }} {{ formset.management_form|crispy }}
{% for form in formset.forms %} {% for form in formset.forms %}
<tr style="border: solid thin;" class="form-row {% cycle 'row1' 'row2' %} formset_row-{{ formset.prefix }}">
<form method="post" enctype="multipart/form-data">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %} {% for hidden in form.hidden_fields %}
{{ hidden }} {{ hidden|as_crispy_field }}
{% endfor %} {% endfor %}
{% endif %} {% crispy form %}
{% if field.name == "cake_img" or field.name == "cream_cake_img" %}
{{ field|as_crispy_field }}
{% if field.value %}
<img src ="/media/{{field.value}}" alt="" width="200px">
{% endif %}
{% else %}
{{ field|as_crispy_field }}
{% endif %}
</td>
{% endfor %} {% endfor %}
{{ field.errors.as_ul }}
</form>
</tr>
<br>
{% endfor %} <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
</table>
<script src="{% static 'gogo/js/vendor/jquery-3.3.1.min.js' %}"></script>
{% if 'order/update' in current_view %}
<script src="{% static 'formset/formset_update.js' %}"></script>
<script type="text/javascript">
$('.formset_row-{{ formset.prefix }}').formset({
addText: '<span class="badge badge-pill badge-info mb-1">Προσθήκη Προϊόντος</span>',
deleteText: 'Αφαίρεση',
prefix: '{{ formset.prefix }}',
});
</script>
{% else %}
<script src="{% static 'formset/formset.js' %}"></script> <script src="{% static 'formset/formset.js' %}"></script>
<script type="text/javascript"> <script type="text/javascript">
$('.formset_row-{{ formset.prefix }}').formset({ $('.formset_row-{{ formset.prefix }}').formset({
@ -72,6 +39,3 @@
prefix: '{{ formset.prefix }}', prefix: '{{ formset.prefix }}',
}); });
</script> </script>
{% endif %}

View File

@ -0,0 +1,57 @@
{% load crispy_forms_tags %}
{% load static %}
{% if 'order/update' in current_view %}
<p class="badge badge-outline-warning mb-1">*Για να <b>διαγράψουμε</b> προϊόντα επιλέγουμε τη διαγραφή σε όσα θέλουμε και πατάμε Αποθήκευση. <b>ΔΕΝ</b> πατάμε αφαίρεση.
<button type="button" class="badge badge-pill badge-warning mb-1" data-toggle="modal" data-target="#myModal"> Παράδειγμα</button>
<div id="myModal" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<p>Παράδειγμα:</p>
<hr>
<img src="{% static 'images/empty_form.png' %}" width="100%" class="img-responsive">
</div>
</div>
</div>
</div>
<br>
</p>
</div>
{% endif %}
<table class="table table-striped col-md-10" style="margin-left: 10px;">
{{ formset.management_form|crispy }}
{% for form in formset.forms %}
<tr style="border: solid thin;" class="form-row {% cycle 'row1' 'row2' %} formset_row-{{ formset.prefix }}">
<form method="post" enctype="multipart/form-data">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{% if field.name == "cake_img" or field.name == "cream_cake_img" %}
{{ field|as_crispy_field }}
{% if field.value %}
<img src ="/media/{{field.value}}" alt="" width="200px">
{% endif %}
{% else %}
{{ field|as_crispy_field }}
{% endif %}
</td>
{% endfor %}
{{ field.errors.as_ul }}
</form>
</tr>
{% endfor %}
</table>
<script src="{% static 'gogo/js/vendor/jquery-3.3.1.min.js' %}"></script>

View File

@ -1,6 +1,6 @@
{% extends "orders/order_detail.html" %} {% extends "orders/order_detail.html" %}
{% block content %} {% block content %}
<div class="modal-dialog"> <div class="modal-dialog" style="margin-top:150px;">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h3 class="modal-title">Διαγραφή?</h3> <h3 class="modal-title">Διαγραφή?</h3>
@ -15,11 +15,10 @@
<strong> <strong>
<ul> <ul>
<li>Αριθμός: {{ object.id }}</li> <li>Αριθμός: {{ object.id }}</li>
<li>Πελάτης: {{ object.customer }}</li> <li>Πελάτης: {{ object.customer_name }}</li>
<li>Ημ/νία Παραγγελίας: {{ object.order_date }}</li> <li>Ημ/νία Παραγγελίας: {{ object.order_date }}</li>
<li>Ημ/νία Παράδοσης: {{ object.delivery_date }}</li> <li>Ημ/νία Παράδοσης: {{ object.delivery_date }}</li>
<li>Κατάστημα: {{ object.store }}</li> <li>Κατάστημα: {{ object.store }}</li>
<li>Κατάστημα: {{ object.order_products.all| cut:":"| cut:"<QuerySet"| cut:"<Product"| cut:">" }}</li>
</ul> </ul>
</strong> </strong>
<input class="btn btn-danger" type="submit" value="Ναι, Θέλω να τη διαγράψω" /> <input class="btn btn-danger" type="submit" value="Ναι, Θέλω να τη διαγράψω" />