commit
c3bed2fc65
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class CoreConfig(AppConfig):
|
||||
name = 'core'
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,17 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
from core.models import CalgaryAddress
|
||||
|
||||
class Command(BaseCommand):
|
||||
def handle(self, *args, **kwargs):
|
||||
addresses = CalgaryAddress.objects.all()
|
||||
length = len(addresses)
|
||||
counter = 0
|
||||
perc = 0
|
||||
for addr in addresses:
|
||||
street_type = addr.street_type
|
||||
long_street_type = street_type_mapping[street_type]
|
||||
addr.long_street_type = long_street_type
|
||||
counter += 1
|
||||
perc = round((counter / length) * 100, 2)
|
||||
addr.save()
|
||||
print("{0}/{1} ({2}%)".format(counter, lenth, perc))
|
@ -0,0 +1,58 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
from core.models import CalgaryAddress
|
||||
import json
|
||||
|
||||
street_type_mapping = {'AL': 'Alley', 'AV': 'Avenue',
|
||||
'BA': 'Bay', 'BV': 'Boulevard',
|
||||
'CA': 'Cape', 'CE': 'Centre', 'CI': 'Circle', 'CL': 'Close', 'CM': 'Common', 'CO': 'Court', 'CR': 'Crescent', 'CV': 'Cove',
|
||||
'DR': 'Drive',
|
||||
'GA': 'Gate', 'GD': 'Gardens', 'GR': 'Green', 'GV': 'Grove',
|
||||
'HE': 'Heath', 'HI': 'Highway', 'HL': 'Hill', 'HT': 'Heights',
|
||||
'IS': 'Island',
|
||||
'LD': 'Landing', 'LI': 'Link', 'LN': 'Lane',
|
||||
'ME': 'Mews', 'MR': 'Manor', 'MT': 'Mount',
|
||||
'PA': 'Park', 'PH': 'Path', 'PL': 'Place', 'PR': 'Parade', 'PS': 'Passage', 'PT': 'Point', 'PY': 'Parkway', 'PZ': 'Plaza',
|
||||
'RD': 'Road', 'RI': 'Rise', 'RO': 'Row',
|
||||
'SQ': 'Square', 'ST': 'Street',
|
||||
'TC': 'Terrace', 'TR': 'Trail',
|
||||
'VI': 'Villas', 'VW': 'View',
|
||||
#'WK': 'Walk', ### UNCLEAN DATA! Be careful. Watch your WKs
|
||||
'WK': 'Walkway',
|
||||
'WY': 'Way'}
|
||||
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Import from $PROJECT_ROOT/addresses.json the addresses for the database.'
|
||||
def handle(self, *args, **kwargs):
|
||||
with open('addresses.json') as addresses:
|
||||
data = json.load(addresses)
|
||||
length = len(data['data'])
|
||||
counter = 0
|
||||
perc = 0
|
||||
for addr_row in data['data']:
|
||||
row_id = addr_row[0]
|
||||
address = addr_row[8]
|
||||
neighbourhood = addr_row[9]
|
||||
street_abbr = addr_row[10]
|
||||
quadrant = addr_row[11]
|
||||
ext = addr_row[13]
|
||||
lng = addr_row[15]
|
||||
lat = addr_row[16]
|
||||
long_street = street_type_mapping[street_abbr]
|
||||
CalgaryAddress.objects.create(address=address,
|
||||
quardrant=quadrant,
|
||||
street_type=street_abbr,
|
||||
nieghbourhood=neighbourhood,
|
||||
extention=ext,
|
||||
long_cord=lng,
|
||||
lat_cord=lat,
|
||||
row_id=row_id,
|
||||
long_street_type=long_street,
|
||||
long_address=address.replace(' ' + street_abbr + ' ', ' ' + long_street +' '))
|
||||
counter += 1
|
||||
perc = round((counter/length) * 100, 2)
|
||||
if counter % 1000 == 0:
|
||||
print("{0}/{1} ({2}%)".format(counter, length, perc))
|
||||
# print 100% after done
|
||||
print("{0}/{1} ({2}%)".format(counter, length, perc))
|
@ -0,0 +1,25 @@
|
||||
# Generated by Django 3.1.2 on 2020-10-15 02:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CalgaryAddress',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('address', models.CharField(max_length=32)),
|
||||
('house_alpha', models.CharField(max_length=1)),
|
||||
('street_quad', models.CharField(max_length=2)),
|
||||
('street_name', models.CharField(max_length=16)),
|
||||
('street_type', models.CharField(max_length=2)),
|
||||
],
|
||||
),
|
||||
]
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,15 @@
|
||||
import json
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
class CalgaryAddress(models.Model):
|
||||
address = models.CharField(max_length=32)
|
||||
house_alpha = models.CharField(max_length=1)
|
||||
street_quad = models.CharField(max_length=2)
|
||||
street_name = models.CharField(max_length=16)
|
||||
street_type = models.CharField(max_length=2)
|
||||
|
||||
def toDict(self):
|
||||
return {
|
||||
'address': self.address
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
@ -0,0 +1,6 @@
|
||||
# my.cnf
|
||||
[client]
|
||||
database = quote_test
|
||||
user = quote
|
||||
password = quote
|
||||
default-character-set = utf8
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class DownloadConfig(AppConfig):
|
||||
name = 'download'
|
@ -0,0 +1,4 @@
|
||||
from django import forms
|
||||
|
||||
class CodeForm(forms.Form):
|
||||
code = forms.CharField(label='Code', max_length=8, required=True)
|
@ -0,0 +1,26 @@
|
||||
# Generated by Django 3.1.2 on 2020-10-15 02:25
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('core', '__first__'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='PDF',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('path', models.CharField(max_length=64)),
|
||||
('code', models.CharField(max_length=8)),
|
||||
('upload_file', models.FileField(upload_to='uploads/%Y/%m/%d/')),
|
||||
('address', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pdfs', to='core.calgaryaddress')),
|
||||
],
|
||||
),
|
||||
]
|
@ -0,0 +1,19 @@
|
||||
# Generated by Django 3.1.2 on 2020-10-15 03:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('download', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='pdf',
|
||||
name='address_string',
|
||||
field=models.CharField(default=0, max_length=32),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -0,0 +1,19 @@
|
||||
# Generated by Django 3.1.2 on 2020-10-15 13:37
|
||||
|
||||
from django.db import migrations
|
||||
import download.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('download', '0002_pdf_address_string'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='pdf',
|
||||
name='upload_file',
|
||||
field=download.validators.RestrictedFileField(upload_to='uploads/%Y/%m/%d/'),
|
||||
),
|
||||
]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,11 @@
|
||||
from django.db import models
|
||||
from core.models import CalgaryAddress
|
||||
from .validators import RestrictedFileField
|
||||
|
||||
# Create your models here.
|
||||
class PDF(models.Model):
|
||||
path = models.CharField(max_length=64)
|
||||
code = models.CharField(max_length=8)
|
||||
address_string = models.CharField(max_length=32)
|
||||
address = models.ForeignKey(CalgaryAddress, related_name='pdfs', on_delete=models.CASCADE)
|
||||
upload_file = RestrictedFileField(max_upload_size=1024*1024*1024*50, content_types=['pdf', 'application/pdf'], upload_to='uploads/%Y/%m/%d/')
|
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
</head>
|
||||
<body>
|
||||
{% block body %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1 @@
|
||||
<h1>Quote Not Found</h1>
|
@ -0,0 +1 @@
|
||||
<h1>Code is wrong</h1>
|
@ -0,0 +1,8 @@
|
||||
{% block body %}
|
||||
<h1>Type In Your Code</h1>
|
||||
<form action="" method="POST">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
{% endblock %}
|
@ -0,0 +1,7 @@
|
||||
{% extends 'common/master.html' %}
|
||||
{% block body %}
|
||||
<h1>Download Your Quote</h1>
|
||||
{% for thing in things %}
|
||||
<p><a href="./d/{{ thing.id }}">{{ thing.address.address }}</a></p>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
@ -0,0 +1,7 @@
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.starter, name='lookup'),
|
||||
path('d/<pdfid>/', views.download, name='download'),
|
||||
]
|
@ -0,0 +1,25 @@
|
||||
from django.db.models import FileField
|
||||
from django.forms import forms
|
||||
from django.template.defaultfilters import filesizeformat
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
class RestrictedFileField(FileField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.content_types = kwargs.pop('content_types', [])
|
||||
self.max_upload_size = kwargs.pop('max_upload_size', [])
|
||||
super(RestrictedFileField, self).__init__(*args, **kwargs)
|
||||
|
||||
def clean(self, *args, **kwargs):
|
||||
data = super(RestrictedFileField, self).clean(*args, **kwargs)
|
||||
file = data.file
|
||||
try:
|
||||
content_type = file.content_type
|
||||
if content_type in self.content_types:
|
||||
if file._size > self.max_upload_size:
|
||||
raise forms.ValidationError("File too big")
|
||||
else:
|
||||
raise forms.ValidationError("Wrong file type")
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
return data
|
@ -0,0 +1,28 @@
|
||||
from django.shortcuts import render, HttpResponse
|
||||
from django.http import FileResponse
|
||||
from . import models
|
||||
from .forms import CodeForm
|
||||
|
||||
# Create your views here.
|
||||
def starter(request):
|
||||
return render(request, 'download/download-page.html', {
|
||||
'things': list(models.PDF.objects.all())
|
||||
});
|
||||
|
||||
def download(request, pdfid):
|
||||
if request.method == 'POST':
|
||||
form = CodeForm(request.POST)
|
||||
if form.is_valid():
|
||||
pdfs = models.PDF.objects.filter(id=pdfid)
|
||||
if len(pdfs) == 0:
|
||||
return render(request, 'common/not-found.html')
|
||||
pdf = pdfs.filter(code=form.cleaned_data['code'])
|
||||
if len(pdf) == 0:
|
||||
return render(request, 'common/password-incorrect.html')
|
||||
pdf = pdf[0]
|
||||
return FileResponse(pdf.upload_file, as_attachment=True)
|
||||
else:
|
||||
form = CodeForm()
|
||||
return render(request, 'download/code-form.html', {
|
||||
'form': form
|
||||
})
|
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
"""Django's command-line utility for administrative tasks."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
"""Run administrative tasks."""
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'quote_pdf.settings')
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
) from exc
|
||||
execute_from_command_line(sys.argv)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,16 @@
|
||||
"""
|
||||
ASGI config for quote_pdf project.
|
||||
|
||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'quote_pdf.settings')
|
||||
|
||||
application = get_asgi_application()
|
@ -0,0 +1,136 @@
|
||||
"""
|
||||
Django settings for quote_pdf project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 3.1.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/3.1/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/3.1/ref/settings/
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve(strict=True).parent.parent
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = ')%#gxkyxmq)0zgigqiti54n(jn)2iv1tuo09t6i#!%&&&8@ig*'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'core',
|
||||
'download',
|
||||
'upload',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'quote_pdf.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'quote_pdf.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
|
||||
|
||||
#DATABASES = {
|
||||
# 'default': {
|
||||
# 'ENGINE': 'django.db.backends.sqlite3',
|
||||
# 'NAME': BASE_DIR / 'db.sqlite3',
|
||||
# }
|
||||
#}
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'CONN_MAX_AGE': 36000,
|
||||
'OPTIONS': {
|
||||
'read_default_file': '/home/tarf/Documents/code/self-written/web-based/quote-pdf/db.cnf',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/3.1/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
# Make default max file size bigger
|
||||
FILE_UPLOAD_MAX_MEMORY_SIZE = 1024*1024*1024*50
|
||||
|
@ -0,0 +1,25 @@
|
||||
"""quote_pdf URL Configuration
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/3.1/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('download/', include('download.urls')),
|
||||
path('upload/', include('upload.urls')),
|
||||
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
@ -0,0 +1,16 @@
|
||||
"""
|
||||
WSGI config for quote_pdf project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'quote_pdf.settings')
|
||||
|
||||
application = get_wsgi_application()
|
@ -0,0 +1,23 @@
|
||||
street_type_mapping = {'AL': 'Alley', 'AV': 'Avenue',
|
||||
'BA': 'Bay', 'BV': 'Boulevard',
|
||||
'CA': 'Cape', 'CE': 'Centre', 'CI': 'Circle', 'CL': 'Close', 'CM': 'Common', 'CO': 'Court', 'CR': 'Crescent', 'CV': 'Cove',
|
||||
'DR': 'Drive',
|
||||
'GA': 'Gate', 'GD': 'Gardens', 'GR': 'Green', 'GV': 'Grove',
|
||||
'HE': 'Heath', 'HI': 'Highway', 'HL': 'Hill', 'HT': 'Heights',
|
||||
'IS': 'Island',
|
||||
'LD': 'Landing', 'LI': 'Link', 'LN': 'Lane',
|
||||
'ME': 'Mews', 'MR': 'Manor', 'MT': 'Mount',
|
||||
'PA': 'Park', 'PH': 'Path', 'PL': 'Place', 'PR': 'Parade', 'PS': 'Passage', 'PT': 'Point', 'PY': 'Parkway', 'PZ': 'Plaza',
|
||||
'RD': 'Road', 'RI': 'Rise', 'RO': 'Row',
|
||||
'SQ': 'Square', 'ST': 'Street',
|
||||
'TC': 'Terrace', 'TR': 'Trail',
|
||||
'VI': 'Villas', 'VW': 'View',
|
||||
'WK': 'Walk', ### UNCLEAN DATA! Be careful. Watch your WKs
|
||||
'WK': 'Walkway',
|
||||
'WY': 'Way'}
|
||||
|
||||
new_street_mapping = {}
|
||||
for k,v in street_type_mapping.items():
|
||||
new_street_mapping[v] = k
|
||||
|
||||
print(new_street_mapping)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class UploadConfig(AppConfig):
|
||||
name = 'upload'
|
@ -0,0 +1,7 @@
|
||||
from django import forms
|
||||
from download.models import PDF
|
||||
|
||||
class PDFForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = PDF
|
||||
fields = ['address_string', 'upload_file']
|
@ -0,0 +1,3 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
@ -0,0 +1,38 @@
|
||||
window.onload = () => {
|
||||
const addresses_ul = document.getElementById(UL_ID);
|
||||
const addrinput = document.getElementById(ADDRESS_ID);
|
||||
|
||||
const delete_possible = () => {
|
||||
addresses_ul.innerHTML = "";
|
||||
};
|
||||
const update_input = async (e) => {
|
||||
addrinput.value = e.target.value;
|
||||
};
|
||||
|
||||
const set_founds = (addrs) => {
|
||||
console.log("DEBUG:");
|
||||
console.log(addrs);
|
||||
|
||||
addresses_ul.innerHTML = "";
|
||||
// add a button within an li for each returned address
|
||||
for (addr of addrs) {
|
||||
addri = document.createElement('li');
|
||||
addrb = document.createElement('button');
|
||||
addrb.innerText = addr['address'];
|
||||
addrb.value = addr['address'];
|
||||
addrb.addEventListener('click', update_input);
|
||||
addrb.addEventListener('click', delete_possible);
|
||||
addri.appendChild(addrb);
|
||||
addresses_ul.appendChild(addri);
|
||||
}
|
||||
};
|
||||
const check = async (e) => {
|
||||
const val = e.target.value;
|
||||
console.log(val);
|
||||
|
||||
let response = await fetch('/upload/search/' + val + '/')
|
||||
.then(response => response.json())
|
||||
.then(response => set_founds(response));
|
||||
}
|
||||
addrinput.addEventListener('input', check);
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
{% extends 'common/master.html' %}
|
||||
{% load static %}
|
||||
{% block body %}
|
||||
<h1>Search Addresses</h1>
|
||||
<input type="text" id="addr" placeholder="Address">
|
||||
<ul id="addrs">
|
||||
|
||||
</ul>
|
||||
<script src="{% static "upload/js/search_addresses.js" %}"></script>
|
||||
{% endblock %}
|
@ -0,0 +1,19 @@
|
||||
{% extends 'common/master.html' %}
|
||||
{% load static %}
|
||||
{% block body %}
|
||||
<h1>Upload</h1>
|
||||
<form action="" method="POST" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<label for="{{ form.address_string.id_for_label }}">Address:</label>
|
||||
{{ form.address_string }}
|
||||
<ul id="addr_list"></ul>
|
||||
<label for="{{ form.upload_file.id_for_label }}">File:</label>
|
||||
{{ form.upload_file }}
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
<script>
|
||||
ADDRESS_ID = "{{ form.address_string.id_for_label }}";
|
||||
UL_ID = "addr_list";
|
||||
</script>
|
||||
<script src="{% static 'upload/js/search_addresses.js' %}"></script>
|
||||
{% endblock %}
|
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
@ -0,0 +1,7 @@
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.upload, name='add_addr'),
|
||||
path('search/<address>/', views.search_api, name='search'),
|
||||
]
|
@ -0,0 +1,71 @@
|
||||
from sodapy import Socrata
|
||||
from core.models import CalgaryAddress
|
||||
from download.models import PDF
|
||||
from django.shortcuts import render, HttpResponse
|
||||
import json
|
||||
from .forms import PDFForm
|
||||
from django.forms import formset_factory
|
||||
|
||||
c = Socrata('data.calgary.ca', None)
|
||||
SHORT_NAME_MAPPING = {'ALLEY': 'AL', 'AVENUE': 'AV',
|
||||
'BAY': 'BA', 'BOULEVARD': 'BV',
|
||||
'CAPE': 'CA', 'CENTRE': 'CE', 'CIRCLE': 'CI', 'CLOSE': 'CL', 'COMMON': 'CM', 'COURT': 'CO', 'CRESCENT': 'CR', 'COVE': 'CV',
|
||||
'DRIVE': 'DR',
|
||||
'GATE': 'GA', 'GARDENS': 'GD', 'GREEN': 'GR', 'GROVE': 'GV',
|
||||
'HEATH': 'HE', 'HIGHWAY': 'HI', 'HILL': 'HL', 'HEIGHTS': 'HT',
|
||||
'ISLAND': 'IS', 'LANDING': 'LD', 'LINK': 'LI', 'LANE': 'LN',
|
||||
'MEWS': 'ME', 'MANOR': 'MR', 'MOUNT': 'MT',
|
||||
'PARK': 'PA', 'PATH': 'PH', 'PLACE': 'PL', 'PARADE': 'PR', 'PASSAGE': 'PS', 'POINT': 'PT', 'PARKWAY': 'PY', 'PLAZA': 'PZ',
|
||||
'ROAD': 'RD', 'RISE': 'RI', 'ROW': 'RO',
|
||||
'SQUARE': 'SQ', 'STREET': 'ST',
|
||||
'TERRACE': 'TC', 'TRAIL': 'TR',
|
||||
'VILLAS': 'VI', 'VIEW': 'VW',
|
||||
'WALKWAY': 'WK', 'WALK': 'WK', 'WAY': 'WY'}
|
||||
|
||||
def sanitize_address(addr):
|
||||
new_addr = addr.upper()
|
||||
for k,v in SHORT_NAME_MAPPING.items():
|
||||
new_addr = new_addr.replace(' ' + k, ' ' + v)
|
||||
return new_addr
|
||||
|
||||
def search_api(request, address):
|
||||
addrs = c.get('uwj2-d2wc',
|
||||
where='address like "%{0}%"'.format(sanitize_address(address)),
|
||||
limit=5)
|
||||
return HttpResponse(json.dumps(addrs))
|
||||
|
||||
def upload(request):
|
||||
if request.method == 'POST':
|
||||
upload_form = PDFForm(request.POST, request.FILES)
|
||||
print(upload_form.data)
|
||||
print(request.FILES)
|
||||
print(upload_form.is_valid())
|
||||
print(upload_form.cleaned_data)
|
||||
address = upload_form.cleaned_data['address_string']
|
||||
code = 'XYZ'
|
||||
name = 'quote_'+code+'.pdf'
|
||||
pdf_file = upload_form.cleaned_data['upload_file']
|
||||
addr = c.get('uwj2-d2wc',
|
||||
where='address = "{0}"'.format(address),
|
||||
limit=1)[0]
|
||||
|
||||
# Save address
|
||||
addr = CalgaryAddress.objects.create(
|
||||
address=addr['address'],
|
||||
house_alpha=addr['house_alpha'] if 'house_alpha' in addr else '',
|
||||
street_quad=addr['street_quad'],
|
||||
street_name=addr['street_name'],
|
||||
street_type=addr['street_type']
|
||||
)
|
||||
pdf = PDF.objects.create(
|
||||
path=name,
|
||||
address=addr,
|
||||
code=code,
|
||||
upload_file=pdf_file
|
||||
)
|
||||
pdf.save()
|
||||
return HttpResponse("File saved")
|
||||
elif request.method == "GET":
|
||||
return render(request, 'upload/upload.html', {
|
||||
'form': PDFForm()
|
||||
})
|
@ -0,0 +1,59 @@
|
||||
from sodapy import Socrata
|
||||
from core.models import CalgaryAddress
|
||||
from django.shortcuts import render, HttpResponse
|
||||
import json
|
||||
c = Socrata('data.calgary.ca', None)
|
||||
SHORT_NAME_MAPPING = {'ALLEY': 'AL', 'AVENUE': 'AV',
|
||||
'BAY': 'BA', 'BOULEVARD': 'BV',
|
||||
'CAPE': 'CA', 'CENTRE': 'CE', 'CIRCLE': 'CI', 'CLOSE': 'CL', 'COMMON': 'CM', 'COURT': 'CO', 'CRESCENT': 'CR', 'COVE': 'CV',
|
||||
'DRIVE': 'DR',
|
||||
'GATE': 'GA', 'GARDENS': 'GD', 'GREEN': 'GR', 'GROVE': 'GV',
|
||||
'HEATH': 'HE', 'HIGHWAY': 'HI', 'HILL': 'HL', 'HEIGHTS': 'HT',
|
||||
'ISLAND': 'IS', 'LANDING': 'LD', 'LINK': 'LI', 'LANE': 'LN',
|
||||
'MEWS': 'ME', 'MANOR': 'MR', 'MOUNT': 'MT',
|
||||
'PARK': 'PA', 'PATH': 'PH', 'PLACE': 'PL', 'PARADE': 'PR', 'PASSAGE': 'PS', 'POINT': 'PT', 'PARKWAY': 'PY', 'PLAZA': 'PZ',
|
||||
'ROAD': 'RD', 'RISE': 'RI', 'ROW': 'RO',
|
||||
'SQUARE': 'SQ', 'STREET': 'ST',
|
||||
'TERRACE': 'TC', 'TRAIL': 'TR',
|
||||
'VILLAS': 'VI', 'VIEW': 'VW',
|
||||
'WALKWAY': 'WK', 'WALK': 'WK', 'WAY': 'WY'}
|
||||
|
||||
def sanitize_address(addr):
|
||||
new_addr = addr.upper()
|
||||
for k,v in SHORT_NAME_MAPPING.items():
|
||||
new_addr = new_addr.replace(' ' + k, ' ' + v)
|
||||
return new_addr
|
||||
|
||||
# Create your views here.
|
||||
def search(request):
|
||||
return render(request, 'upload/search.html', {})
|
||||
|
||||
def search_api(request, address):
|
||||
addrs = c.get('uwj2-d2wc',
|
||||
where='address like "%{0}%"'.format(sanitize_address(address)),
|
||||
limit=5)
|
||||
return HttpResponse(json.dumps(addrs))
|
||||
|
||||
def save_file(file):
|
||||
with open('pdfs/test.pdf', 'wb+') as destination:
|
||||
for chunk in file.chunks():
|
||||
destination.write(chunk)
|
||||
|
||||
def upload(request, address):
|
||||
if request.method == 'POST':
|
||||
# addr = c.get('uwj2-d2wc',
|
||||
# where='address = "{0}"'.format(address),
|
||||
# limit=1)[0]
|
||||
# CalgaryAddress.objects.create(
|
||||
# address=addr['address'],
|
||||
# house_alpha=addr['house_alpha'] if 'house_alpha' in addr else '',
|
||||
# street_quad=addr['street_quad'],
|
||||
# street_name=addr['street_name'],
|
||||
# street_type=addr['street_type']
|
||||
# )
|
||||
file = request.FILES['file']
|
||||
save_file(file)
|
||||
return HttpResponse("File saved")
|
||||
return render(request, 'upload/upload.html', {
|
||||
'address': address
|
||||
})
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue