diff --git a/gpp/settings.py b/gpp/settings.py index 98e0a5c..336e62b 100644 --- a/gpp/settings.py +++ b/gpp/settings.py @@ -39,7 +39,8 @@ INSTALLED_APPS = [ 'django.contrib.messages', 'django.contrib.staticfiles', 'django_countries', - 'phonenumber_field' + 'phonenumber_field', + 'datetimewidget' ] MIDDLEWARE = [ @@ -50,6 +51,7 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'django.middleware.locale.LocaleMiddleware' ] ROOT_URLCONF = 'gpp.urls' diff --git a/gpp/urls.py b/gpp/urls.py index 9a4093b..e0b7360 100644 --- a/gpp/urls.py +++ b/gpp/urls.py @@ -20,5 +20,6 @@ urlpatterns = [ #path('', include('port.urls', namespace='index')), path('port/', include('port.urls.port', namespace='port')), path('person/', include('port.urls.person', namespace='person')), + path('boat/', include('port.urls.boat', namespace='boat')), path('admin/', admin.site.urls), ] diff --git a/port/forms.py b/port/forms.py index b8e6518..f111d10 100644 --- a/port/forms.py +++ b/port/forms.py @@ -3,11 +3,12 @@ from django.forms import Form, ModelForm, \ BooleanField, EmailField, DateTimeField, ImageField, \ formset_factory from django_countries.fields import CountryField -from phonenumber_field.formfields import PhoneNumberField +from phonenumber_field.formfields import PhoneNumberField +from datetimewidget.widgets import DateTimeWidget from .models import * -class PersonForm(Form): +class PersonForm(ModelForm): class Meta: model = Person @@ -26,7 +27,7 @@ class PersonForm(Form): phone = PhoneNumberField(label='Phone Number') """ -class AddressForm(Form): +class AddressForm(ModelForm): class Meta: model = Address @@ -86,7 +87,7 @@ class PortForm(ModelForm): company = CharField(label='Company', max_length=50) """ -class PlugForm(Form): +class PlugForm(ModelForm): class Meta: model = Plug @@ -112,7 +113,7 @@ class PlugForm(Form): PlugFormSet = formset_factory(PlugForm) -class TapForm(Form): +class TapForm(ModelForm): class Meta: model = Tap @@ -129,8 +130,10 @@ class BoatForm(ModelForm): class Meta: model = Boat - fields = ['name', - 'length', 'beam', + fields = ['name', + 'registration_num', + 'length', + 'beam', 'water_draught', 'tonnage', 'water_tank', @@ -138,3 +141,31 @@ class BoatForm(ModelForm): 'heating', 'passenger_capacity', 'picture'] + +class StayForm(ModelForm): + + class Meta: + model = Stay + fields = ['arrival', + 'departure', + 'coming_from', + 'going_to', + 'no_mooring'] + widgets = { + #Use localization and bootstrap 3 + 'datetime': DateTimeWidget( + attrs={'id':"yourdatetimeid"}, + usel10n = True) + } + + +class MooringForm(ModelForm): + + class Meta: + model = Mooring + fields = ['date', + 'dock', + 'tap', + 'plug'] + +MooringFormSet = formset_factory(MooringForm) diff --git a/port/migrations/0003_auto_20190608_1839.py b/port/migrations/0003_auto_20190608_1839.py new file mode 100644 index 0000000..a3c002d --- /dev/null +++ b/port/migrations/0003_auto_20190608_1839.py @@ -0,0 +1,186 @@ +# Generated by Django 2.2.1 on 2019-06-08 16:39 + +from django.db import migrations, models +import django.db.models.deletion +import django_countries.fields +import phonenumber_field.modelfields + + +class Migration(migrations.Migration): + + dependencies = [ + ('port', '0002_auto_20190607_1129'), + ] + + operations = [ + migrations.AddField( + model_name='stay', + name='no_mooring', + field=models.BooleanField(blank=True, default=False, verbose_name='Set moorings later'), + ), + migrations.AlterField( + model_name='boat', + name='beam', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True), + ), + migrations.AlterField( + model_name='boat', + name='company', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='port.Company'), + ), + migrations.AlterField( + model_name='boat', + name='heating', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='boat', + name='length', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True, verbose_name='Length'), + ), + migrations.AlterField( + model_name='boat', + name='model', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='boat', + name='passenger_capacity', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='boat', + name='picture', + field=models.ImageField(blank=True, null=True, upload_to='uploads/'), + ), + migrations.AlterField( + model_name='boat', + name='registration_num', + field=models.CharField(blank=True, max_length=20, null=True, verbose_name='Registration number'), + ), + migrations.AlterField( + model_name='boat', + name='tonnage', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True), + ), + migrations.AlterField( + model_name='boat', + name='water_draught', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True), + ), + migrations.AlterField( + model_name='boat', + name='water_tank', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True, verbose_name='Water tank capacity'), + ), + migrations.AlterField( + model_name='boatinsurance', + name='contract', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='company', + name='address', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='port.Address'), + ), + migrations.AlterField( + model_name='company', + name='email', + field=models.EmailField(blank=True, max_length=200, null=True), + ), + migrations.AlterField( + model_name='company', + name='phone', + field=phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, null=True, region=None), + ), + migrations.AlterField( + model_name='company', + name='registration_num', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='dock', + name='depth_max', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True), + ), + migrations.AlterField( + model_name='dock', + name='depth_min', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True), + ), + migrations.AlterField( + model_name='dock', + name='length', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True), + ), + migrations.AlterField( + model_name='dock', + name='width', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True), + ), + migrations.AlterField( + model_name='employee', + name='position', + field=models.CharField(blank=True, max_length=20, null=True, verbose_name='Job'), + ), + migrations.AlterField( + model_name='mooring', + name='plug', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='port.Plug'), + ), + migrations.AlterField( + model_name='mooring', + name='tap', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='port.Tap'), + ), + migrations.AlterField( + model_name='person', + name='address', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='port.Address'), + ), + migrations.AlterField( + model_name='person', + name='email', + field=models.EmailField(blank=True, max_length=254, null=True), + ), + migrations.AlterField( + model_name='person', + name='name', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='person', + name='nationality', + field=django_countries.fields.CountryField(blank=True, max_length=2, null=True), + ), + migrations.AlterField( + model_name='person', + name='phone', + field=phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, null=True, region=None), + ), + migrations.AlterField( + model_name='person', + name='surname', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='stay', + name='bill', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='port.Bill'), + ), + migrations.AlterField( + model_name='stay', + name='coming_from', + field=models.CharField(blank=True, max_length=200, null=True), + ), + migrations.AlterField( + model_name='stay', + name='departure', + field=models.DateTimeField(blank=True, null=True), + ), + migrations.AlterField( + model_name='stay', + name='going_to', + field=models.CharField(blank=True, max_length=200, null=True), + ), + ] diff --git a/port/models.py b/port/models.py index f71c101..76f5967 100644 --- a/port/models.py +++ b/port/models.py @@ -5,6 +5,15 @@ from django.db.models import Model, CharField, EmailField, \ CASCADE, SET_NULL, PROTECT from django_countries.fields import CountryField from phonenumber_field.modelfields import PhoneNumberField +from django.core.exceptions import ValidationError +from django.utils.translation import gettext_lazy as _ + +def validate_positive(value): + if value < 0: + raise ValidationError( + _('%(value)s is not a positive number'), + params={'value': value}, + ) class Address(Model): address = CharField(max_length=200) @@ -17,26 +26,26 @@ class Address(Model): self.city, self.country) class Person(Model): - name = CharField(max_length=50,null=True) - surname = CharField(max_length=50,null=True) - nationality = CountryField(null=True) - email = EmailField(max_length=254,null=True) - phone = PhoneNumberField(null=True) + name = CharField(max_length=50,blank=True,null=True) + surname = CharField(max_length=50,blank=True,null=True) + nationality = CountryField(blank=True,null=True) + email = EmailField(max_length=254,blank=True,null=True) + phone = PhoneNumberField(blank=True,null=True) # Foreign keys - address = ForeignKey(Address,on_delete=SET_NULL,null=True) + address = ForeignKey(Address,on_delete=SET_NULL,blank=True,null=True) def __str__(self): return '{} {}'.format(self.name, self.surname) class Company(Model): name = CharField(max_length=50) - email = EmailField(max_length=200,null=True) - phone = PhoneNumberField(null=True) - registration_num = CharField(max_length=50,null=True) + email = EmailField(max_length=200,blank=True,null=True) + phone = PhoneNumberField(blank=True,null=True) + registration_num = CharField(max_length=50,blank=True,null=True) # Foreign keys - address = ForeignKey(Address,on_delete=SET_NULL,null=True) + address = ForeignKey(Address,on_delete=SET_NULL,blank=True,null=True) def __str__(self): return '{}'.format(self.name) @@ -45,20 +54,21 @@ class Insurance(Company): class Boat(Model): name = CharField(max_length=50) - registration_num = CharField('Registration number', max_length=20,null=True) - length = DecimalField('Length', max_digits=7, decimal_places=2, null=True) - beam = DecimalField(, max_digits=7, decimal_places=2, null=True) - water_draught = DecimalField(max_digits=7, decimal_places=2, null=True) - tonnage = DecimalField(max_digits=7, decimal_places=2, null=True) - water_tank = DecimalField('Water tank capacity', max_digits=7, decimal_places=2, null=True) - model = CharField(max_length=50,null=True) - heating = CharField(max_length=50,null=True) - passenger_capacity = IntegerField(null=True) + registration_num = CharField('Registration number', max_length=20,blank=True,null=True) + length = DecimalField('Length', max_digits=7, decimal_places=2, blank=True,null=True, validators=[validate_positive]) + beam = DecimalField(max_digits=7, decimal_places=2, blank=True,null=True, validators=[validate_positive]) + water_draught = DecimalField(max_digits=7, decimal_places=2, blank=True,null=True, validators=[validate_positive]) + tonnage = DecimalField(max_digits=7, decimal_places=2, blank=True,null=True, validators=[validate_positive]) + water_tank = DecimalField('Water tank capacity', max_digits=7, decimal_places=2, + blank=True,null=True, validators=[validate_positive]) + model = CharField(max_length=50,blank=True,null=True) + heating = CharField(max_length=50,blank=True,null=True) + passenger_capacity = IntegerField(blank=True,null=True) picture = ImageField(upload_to='uploads/', height_field=None, - width_field=None, max_length=100, null=True) + width_field=None, max_length=100, blank=True,null=True) # Foreign keys - company = ForeignKey(Company,on_delete=SET_NULL,null=True,related_name='+') + company = ForeignKey(Company,on_delete=SET_NULL,blank=True,null=True,related_name='+') boat_insurance = ManyToManyField( Insurance, @@ -84,7 +94,7 @@ class SailsOn(Model): is_pet = BooleanField() class BoatInsurance(Model): - contract = IntegerField(null=True) + contract = IntegerField(blank=True,null=True) date = DateTimeField(auto_now_add=True) # Foreign keys @@ -107,7 +117,7 @@ class Port(Model): class Employee(Model): - position = CharField('Job', max_length=20, null=True) + position = CharField('Job', max_length=20, blank=True,null=True) # Foreign keys port = ForeignKey(Port,on_delete=PROTECT) @@ -118,10 +128,10 @@ class Employee(Model): class Dock(Model): name = CharField(max_length=10) - length = DecimalField(max_digits=7, decimal_places=2, null=True) - width = DecimalField(max_digits=7, decimal_places=2, null=True) - depth_min = DecimalField(max_digits=7, decimal_places=2, null=True) - depth_max = DecimalField(max_digits=7, decimal_places=2, null=True) + length = DecimalField(max_digits=7, decimal_places=2, blank=True,null=True, validators=[validate_positive]) + width = DecimalField(max_digits=7, decimal_places=2, blank=True,null=True, validators=[validate_positive]) + depth_min = DecimalField(max_digits=7, decimal_places=2, blank=True,null=True, validators=[validate_positive]) + depth_max = DecimalField(max_digits=7, decimal_places=2, blank=True,null=True, validators=[validate_positive]) # Foreign keys port = ForeignKey(Port,on_delete=PROTECT) @@ -130,8 +140,8 @@ class Dock(Model): class Plug(Model): name = CharField(max_length=10) - amperage = DecimalField(max_digits=7, decimal_places=2) - voltage = DecimalField(max_digits=7, decimal_places=2) + amperage = DecimalField(max_digits=7, decimal_places=2, validators=[validate_positive]) + voltage = DecimalField(max_digits=7, decimal_places=2, validators=[validate_positive]) # Foreign keys port = ForeignKey(Port,on_delete=PROTECT) @@ -202,13 +212,14 @@ class BillPayment(Model): class Stay(Model): arrival = DateTimeField() - departure = DateTimeField(null=True) - coming_from = CharField(max_length=200,null=True) - going_to = CharField(max_length=200,null=True) + departure = DateTimeField(blank=True,null=True) + coming_from = CharField(max_length=200,blank=True,null=True) + going_to = CharField(max_length=200,blank=True,null=True) + no_mooring = BooleanField('Set moorings later',default=False,blank=True) # Foreign keys boat = ForeignKey(Boat,on_delete=PROTECT) - bill = ForeignKey(Bill,on_delete=PROTECT,null=True) + bill = ForeignKey(Bill,on_delete=PROTECT,blank=True,null=True) def __str__(self): return '{} - {} : {}'.format(self.arrival, self.departure, str(self.boat)) @@ -218,8 +229,8 @@ class Mooring(Model): # Foreign keys stay = ForeignKey(Stay,on_delete=CASCADE) dock = ForeignKey(Dock,on_delete=PROTECT) - tap = ForeignKey(Tap,on_delete=PROTECT,null=True) - plug = ForeignKey(Plug,on_delete=PROTECT,null=True) + tap = ForeignKey(Tap,on_delete=PROTECT,blank=True,null=True) + plug = ForeignKey(Plug,on_delete=PROTECT,blank=True,null=True) # Methods def __str__(self): diff --git a/port/templates/base.html b/port/templates/base.html index 97dcbb6..ad83992 100644 --- a/port/templates/base.html +++ b/port/templates/base.html @@ -20,6 +20,11 @@ +
diff --git a/port/templates/boat/form.html b/port/templates/boat/form.html index bc51402..87e2889 100644 --- a/port/templates/boat/form.html +++ b/port/templates/boat/form.html @@ -1,32 +1,24 @@ {% extends "base.html" %} {% block content %} -
+ {% csrf_token %}
- Port - {{ port_form }} + Boat + {{ boat_form }}
- Dock - - {% for dock_form in dock_forms %} - {{ dock_form.as_table }} - {% endfor %} -
+ Person + {{ person_form }}
- Plug - - {% for plug_form in plug_forms %} - {{ plug_form.as_table }} - {% endfor %} -
+ Stay + {{ stay_form }}
- Tap + Mooring - {% for tap_form in tap_forms %} - {{ tap_form.as_table }} + {% for mooring_form in mooring_forms %} + {{ mooring_form.as_table }} {% endfor %}
diff --git a/port/templates/boat/list.html b/port/templates/boat/list.html index 636f12a..4498676 100644 --- a/port/templates/boat/list.html +++ b/port/templates/boat/list.html @@ -1,8 +1,8 @@ {% extends "base.html" %} {% block content %} {% endblock %} diff --git a/port/urls/boat.py b/port/urls/boat.py index e69de29..0e15c42 100644 --- a/port/urls/boat.py +++ b/port/urls/boat.py @@ -0,0 +1,11 @@ +from django.urls import path + +from ..views.boat import * + +app_name = 'boat' +urlpatterns = [ + path('', index, name='index'), + path('list', list_boats, name='list'), + path('form', form, name='form'), + path('add', add_boat, name='add'), +] diff --git a/port/views/boat.py b/port/views/boat.py index e69de29..ee9106f 100644 --- a/port/views/boat.py +++ b/port/views/boat.py @@ -0,0 +1,49 @@ +from django.shortcuts import render +from django.http import HttpResponse + +from pprint import pprint + +from ..models import * +from ..forms import * + +def index(request): + return HttpResponse("Hello Boat") + + +def list_boats(request): + return render(request, 'boat/list.html', + {'boats': boat.objects.all}) + +def form(request): + boat_form = BoatForm() + person_form = PersonForm() + stay_form = StayForm() + mooring_forms = MooringFormSet() + + return render(request, 'boat/form.html', + {'boat_form': boat_form, + 'person_form': person_form, + 'stay_form': stay_form, + 'mooring_forms': mooring_forms}) + +def add_boat(request): + if request.method == 'POST': + boat_form = BoatForm(request.POST) + if not boat_form.is_valid(): + return form(request) + + person_form = PersonForm(request.POST) + if not person_form.is_valid(): + return form(request) + + stay_form = StayForm(request.POST) + if not stay_form.is_valid(): + return form(request) + + if stay_form.no_mooring is not True: + mooring_forms = MooringFormSet(request.POST) + mooring_forms_data = mooring_forms.save(commit=False) + for mooring_data in mooring_forms_data: + pass + + return form(request) diff --git a/static/fonts/glyphicons-halflings-regular.eot b/static/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000..b93a495 Binary files /dev/null and b/static/fonts/glyphicons-halflings-regular.eot differ diff --git a/static/fonts/glyphicons-halflings-regular.svg b/static/fonts/glyphicons-halflings-regular.svg new file mode 100644 index 0000000..94fb549 --- /dev/null +++ b/static/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/static/fonts/glyphicons-halflings-regular.ttf b/static/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000..1413fc6 Binary files /dev/null and b/static/fonts/glyphicons-halflings-regular.ttf differ diff --git a/static/fonts/glyphicons-halflings-regular.woff b/static/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 0000000..9e61285 Binary files /dev/null and b/static/fonts/glyphicons-halflings-regular.woff differ diff --git a/static/fonts/glyphicons-halflings-regular.woff2 b/static/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000..64539b5 Binary files /dev/null and b/static/fonts/glyphicons-halflings-regular.woff2 differ