-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit c2d70b9
Showing
20 changed files
with
2,543 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
|
||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
env/ | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
wheels/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg | ||
|
||
# PyInstaller | ||
# Usually these files are written by a python script from a template | ||
# before PyInstaller builds the exe, so as to inject date/other infos into it. | ||
*.manifest | ||
*.spec | ||
|
||
# Installer logs | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
|
||
# Unit test / coverage reports | ||
htmlcov/ | ||
.tox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*.cover | ||
.hypothesis/ | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
local_settings.py | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
target/ | ||
|
||
# Jupyter Notebook | ||
.ipynb_checkpoints | ||
|
||
# pyenv | ||
.python-version | ||
|
||
# celery beat schedule file | ||
celerybeat-schedule | ||
|
||
# SageMath parsed files | ||
*.sage.py | ||
|
||
# dotenv | ||
.env | ||
|
||
# virtualenv | ||
.venv | ||
venv/ | ||
ENV/ | ||
.vscode | ||
# Spyder project settings | ||
.spyderproject | ||
.spyproject | ||
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
# mkdocs documentation | ||
/site | ||
|
||
# mypy | ||
.mypy_cache/ | ||
|
||
.DS_Store | ||
*.sqlite3 | ||
media/ | ||
*.pyc | ||
*.db | ||
*.pid | ||
# django migrations | ||
**/migrations/** | ||
!**/migrations | ||
!**/migrations/__init__.py |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
## Description | ||
|
||
> Sales Records API endpoint with Django Rest Framework and Django Filters | ||
## System Requirements | ||
|
||
- Python 3.6+ | ||
- pip3 | ||
- virtualenv | ||
|
||
## Dependencies | ||
|
||
<!-- > See [requirements.txt](https://github.com/talented/djangoAPI_task/blob/master/requirements.txt) for more information. --> | ||
|
||
## Build Instructions | ||
|
||
1. Create a virtual environment | ||
|
||
``` | ||
(OSX) | ||
python3 -m venv .env | ||
(Linux) | ||
virtualenv .env | ||
``` | ||
|
||
2. Activate virtual environment | ||
|
||
``` | ||
. .venv/bin/Activate | ||
``` | ||
|
||
3. Install modules by running 'requirements.txt' | ||
|
||
``` | ||
pip3 install -r requirements.txt | ||
``` | ||
|
||
4. Configure settings for postgresql database | ||
|
||
## API filters | ||
|
||
> GET {website}/api/sales display a DRF List API view. Avaliable filter types are listed below: | ||
### Filter by Field name | ||
|
||
- for filtering by field names like `country=Germany`, `region=Europe` or same values for sale price like `price=500` | ||
|
||
### Filter by date | ||
|
||
- for exact date filtering like `date=01.06.2017` | ||
- `date_to` - # filter by date as "is_less_than_or_equal_to" in format "%d.%m.%Y" | ||
- `date_from` - # filter by date as "is_greater_than_or_equal_to" in format "%d.%m.%Y" | ||
|
||
### Filter by 'LESS THAN OR EQUAL TO' & 'GREATER THAN OR EQUAL TO' | ||
|
||
- Defining minimum and maximum value filters in a row for numeric fields ('quantity', 'price', 'cost', 'revenue', 'profit', 'profit_percentage') to be used in filtering as "is_less_than_or_equal_to" and "is_greater_than_or_equal_to" | ||
- Usage is as `min_revenue=10000` or `max_price` | ||
|
||
### Ordering Filter | ||
|
||
- `ordering` - to order queryset in ascending or descending as `ordering=quantity` ASC or `ordering=-quantity` DESC | ||
|
||
### Grouping Filter | ||
|
||
- `groupby` - to group by one or more columns: date, region, country, ptype, channel (not numeric columns) with a result of total values of quantity, price, cost, revenue, profit and calculated profit_percentage of total revenue and total profit | ||
|
||
### Search Filter | ||
|
||
- `search` - to make a case insensitive search in values for all items in a queryset | ||
- Usage is as `search=Meat` or even `search=Me`. First search will return items with ptype=Meat, second one will also return items like region=North America | ||
|
||
## USE-CASE TESTS | ||
|
||
1. Show the number of quantity and total cost of sales before 1st of June 2015, broken down by channel and country, sorted by profit_percentage in descending order. | ||
|
||
> GET {website}/api/sales?groupby=country&groupby=channel&date_to=01.06.2015&ordering=-profit_percentage | ||
2. Show the total cost of products in May of 2017 on ptype, broken down by date, sorted by date in ascending order. | ||
|
||
> GET {website}/api/sales?groupby=ptype&groupby=date&date_from=01.03.2010&date_to=31.03.2010&ordering=date | ||
3. Show revenue, earned in 2015 in Europe region, broken down by country and sorted by revenue in descending order. | ||
|
||
> GET {website}/api/sales?region=Europe&groupby=country&date_from=01.01.2015&date_to=31.12.2015&ordering=-revenue | ||
4. Show profit percentage for Turkey broken down by channel ordered by profit percentage in descending order. | ||
|
||
> GET {website}/api/sales?country=Turkey&groupby=channel&ordering=-profit_percentage |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
""" | ||
Django settings for apitest project. | ||
Generated by 'django-admin startproject' using Django 2.2.2. | ||
For more information on this file, see | ||
https://docs.djangoproject.com/en/2.2/topics/settings/ | ||
For the full list of settings and their values, see | ||
https://docs.djangoproject.com/en/2.2/ref/settings/ | ||
""" | ||
|
||
import os | ||
|
||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) | ||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | ||
|
||
|
||
# Quick-start development settings - unsuitable for production | ||
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ | ||
|
||
# SECURITY WARNING: keep the secret key used in production secret! | ||
SECRET_KEY = '#t!-)3h)7-fe23+$4n760%-_(*e$k#o1d()6e+dgmeta2q!$lv' | ||
|
||
# SECURITY WARNING: don't run with debug turned on in production! | ||
DEBUG = True | ||
|
||
ALLOWED_HOSTS = [] | ||
|
||
|
||
# Application definition | ||
|
||
INSTALLED_APPS = [ | ||
'django.contrib.admin', | ||
'django.contrib.auth', | ||
'django.contrib.contenttypes', | ||
'django.contrib.sessions', | ||
'django.contrib.messages', | ||
'django.contrib.staticfiles', | ||
'app', | ||
'rest_framework', | ||
'django_filters', | ||
] | ||
|
||
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 = 'apitest.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 = 'apitest.wsgi.application' | ||
|
||
|
||
# Database | ||
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases | ||
|
||
DATABASES = { | ||
'default': { | ||
'ENGINE': 'django.db.backends.postgresql', | ||
'NAME': 'postgres', | ||
'USER': 'postgres', | ||
'PASSWORD': 'admin', | ||
'HOST': '127.0.0.1', | ||
'PORT': '5432', | ||
} | ||
} | ||
|
||
|
||
# Password validation | ||
# https://docs.djangoproject.com/en/2.2/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/2.2/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/2.2/howto/static-files/ | ||
|
||
STATIC_URL = '/static/' | ||
|
||
REST_FRAMEWORK = { | ||
'DEFAULT_RENDERER_CLASSES': ( | ||
'rest_framework.renderers.JSONRenderer', | ||
'rest_framework.renderers.BrowsableAPIRenderer', | ||
), | ||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', | ||
'PAGE_SIZE': 20 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from django.contrib import admin | ||
from django.urls import path, include | ||
|
||
urlpatterns = [ | ||
path('admin/', admin.site.urls), | ||
path('', include('app.api.urls')) | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
""" | ||
WSGI config for apitest 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/2.2/howto/deployment/wsgi/ | ||
""" | ||
|
||
import os | ||
|
||
from django.core.wsgi import get_wsgi_application | ||
|
||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'apitest.settings') | ||
|
||
application = get_wsgi_application() |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from django.contrib import admin | ||
|
||
# Register your models here. |
Empty file.
Oops, something went wrong.