Merge pull request #19 from overshard/master

Add ability to upload picture of child with thumbnailing capabilities.
This commit is contained in:
Christopher Charbonneau Wells 2017-11-18 06:27:10 -05:00 committed by GitHub
commit ebf42acf87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 104 additions and 28 deletions

1
.gitignore vendored
View File

@ -14,3 +14,4 @@
# static files # static files
/babybuddy/static /babybuddy/static
/static /static
/media

10
Pipfile
View File

@ -1,8 +1,11 @@
[[source]] [[source]]
verify_ssl = true verify_ssl = true
url = "https://pypi.python.org/simple" url = "https://pypi.python.org/simple"
[packages] [packages]
django = "*" django = "*"
djangorestframework = "*" djangorestframework = "*"
django-filter = "*" django-filter = "*"
@ -13,9 +16,12 @@ faker = "*"
dj-database-url = "*" dj-database-url = "*"
gunicorn = "*" gunicorn = "*"
whitenoise = "*" whitenoise = "*"
psycopg2 = "*" "psycopg2" = "*"
easy-thumbnails = "*"
[dev-packages] [dev-packages]
coveralls = "*" coveralls = "*"
flake8 = "*" "flake8" = "*"
ipaddress = "*" ipaddress = "*"

35
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "8ecb16e5e548134a5bdee9b54f0f792890b2e92ebc47d219b9dfef3ea7b9dcfb" "sha256": "4ff4dd2c2df1b4b46d5dc1872aa1a240f519915b1e0bf2a64b3ee650d1489fd2"
}, },
"requires": {}, "requires": {},
"sources": [ "sources": [
@ -13,7 +13,7 @@
}, },
"default": { "default": {
"certifi": { "certifi": {
"version": "==2017.7.27.1" "version": "==2017.11.5"
}, },
"chardet": { "chardet": {
"version": "==3.0.4" "version": "==3.0.4"
@ -25,7 +25,7 @@
"version": "==0.4.2" "version": "==0.4.2"
}, },
"django": { "django": {
"version": "==1.11.6" "version": "==1.11.7"
}, },
"django-filter": { "django-filter": {
"version": "==1.1.0" "version": "==1.1.0"
@ -34,10 +34,13 @@
"version": "==1.4.1" "version": "==1.4.1"
}, },
"djangorestframework": { "djangorestframework": {
"version": "==3.7.1" "version": "==3.7.3"
},
"easy-thumbnails": {
"version": "==2.5"
}, },
"faker": { "faker": {
"version": "==0.8.6" "version": "==0.8.7"
}, },
"gunicorn": { "gunicorn": {
"version": "==19.7.1" "version": "==19.7.1"
@ -52,7 +55,7 @@
"version": "==2.6.0" "version": "==2.6.0"
}, },
"jupyter-core": { "jupyter-core": {
"version": "==4.3.0" "version": "==4.4.0"
}, },
"nbformat": { "nbformat": {
"version": "==4.4.0" "version": "==4.4.0"
@ -60,20 +63,26 @@
"numpy": { "numpy": {
"version": "==1.13.3" "version": "==1.13.3"
}, },
"olefile": {
"version": "==0.44"
},
"pandas": { "pandas": {
"version": "==0.20.3" "version": "==0.21.0"
},
"pillow": {
"version": "==4.3.0"
}, },
"plotly": { "plotly": {
"version": "==2.1.0" "version": "==2.2.1"
}, },
"psycopg2": { "psycopg2": {
"version": "==2.7.3.1" "version": "==2.7.3.2"
}, },
"python-dateutil": { "python-dateutil": {
"version": "==2.6.1" "version": "==2.6.1"
}, },
"pytz": { "pytz": {
"version": "==2017.2" "version": "==2017.3"
}, },
"requests": { "requests": {
"version": "==2.18.4" "version": "==2.18.4"
@ -82,7 +91,7 @@
"version": "==1.11.0" "version": "==1.11.0"
}, },
"text-unidecode": { "text-unidecode": {
"version": "==1.0" "version": "==1.1"
}, },
"traitlets": { "traitlets": {
"version": "==4.3.2" "version": "==4.3.2"
@ -96,13 +105,13 @@
}, },
"develop": { "develop": {
"certifi": { "certifi": {
"version": "==2017.7.27.1" "version": "==2017.11.5"
}, },
"chardet": { "chardet": {
"version": "==3.0.4" "version": "==3.0.4"
}, },
"coverage": { "coverage": {
"version": "==4.4.1" "version": "==4.4.2"
}, },
"coveralls": { "coveralls": {
"version": "==1.2.0" "version": "==1.2.0"

View File

@ -28,6 +28,7 @@ INSTALLED_APPS = [
'django_filters', 'django_filters',
'rest_framework', 'rest_framework',
'widget_tweaks', 'widget_tweaks',
'easy_thumbnails',
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
@ -122,8 +123,12 @@ STATICFILES_FINDERS = [
STATIC_URL = '/static/' STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static') STATIC_ROOT = os.path.join(BASE_DIR, 'static')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
WHITENOISE_ROOT = os.path.join(BASE_DIR, 'static', 'root') WHITENOISE_ROOT = os.path.join(BASE_DIR, 'static', 'root')

View File

@ -1,7 +1,7 @@
{% load widget_tweaks %} {% load widget_tweaks %}
<div class="container-fluid"> <div class="container-fluid">
<form role="form" method="post"> <form role="form" method="post" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
{% if form.non_field_errors %} {% if form.non_field_errors %}
{% for error in form.non_field_errors %} {% for error in form.non_field_errors %}
@ -21,4 +21,4 @@
{% endfor %} {% endfor %}
<button type="submit" class="btn btn-primary">Submit</button> <button type="submit" class="btn btn-primary">Submit</button>
</form> </form>
</div> </div>

View File

@ -2,6 +2,8 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf.urls import url, include from django.conf.urls import url, include
from django.conf.urls.static import static
from django.conf import settings
from django.contrib import admin from django.contrib import admin
from django.contrib.auth import views as auth_views from django.contrib.auth import views as auth_views
@ -25,3 +27,9 @@ urlpatterns = [
url(r'', include('dashboard.urls')), url(r'', include('dashboard.urls')),
url(r'', include('reports.urls', namespace='reports')), url(r'', include('reports.urls', namespace='reports')),
] ]
if settings.DEBUG:
urlpatterns += static(
settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT
)

View File

@ -40,7 +40,7 @@ def set_default_duration(kwargs):
class ChildForm(forms.ModelForm): class ChildForm(forms.ModelForm):
class Meta: class Meta:
model = models.Child model = models.Child
fields = ['first_name', 'last_name', 'birth_date'] fields = ['first_name', 'last_name', 'birth_date', 'picture']
widgets = { widgets = {
'birth_date': forms.DateInput(attrs={ 'birth_date': forms.DateInput(attrs={
'class': 'datepicker-input', 'class': 'datepicker-input',

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-18 09:00
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0003_weight'),
]
operations = [
migrations.AddField(
model_name='child',
name='picture',
field=models.ImageField(blank=True, null=True, upload_to='child/picture/'),
),
]

View File

@ -75,6 +75,11 @@ class Child(models.Model):
last_name = models.CharField(max_length=255) last_name = models.CharField(max_length=255)
birth_date = models.DateField(blank=False, null=False) birth_date = models.DateField(blank=False, null=False)
slug = models.SlugField(max_length=100, unique=True, editable=False) slug = models.SlugField(max_length=100, unique=True, editable=False)
picture = models.ImageField(
upload_to='child/picture/',
blank=True,
null=True
)
objects = models.Manager() objects = models.Manager()

View File

@ -1,5 +1,5 @@
{% extends 'babybuddy/page.html' %} {% extends 'babybuddy/page.html' %}
{% load static %} {% load static thumbnail %}
{% block title %}{{ object }}{% endblock %} {% block title %}{{ object }}{% endblock %}
@ -12,7 +12,12 @@
<div class="child-detail-column"> <div class="child-detail-column">
<div class="row"> <div class="row">
<div class="col-lg-4 col-md-6 pb-3 text-center"> <div class="col-lg-4 col-md-6 pb-3 text-center">
<img src="{% static 'babybuddy/img/core/child-placeholder.png' %}" class="child-photo img-fluid rounded-circle" /> {% if object.picture %}
{% thumbnail object.picture 150x150 upscale crop as thumb %}
<img src="{{ thumb.url }}" class="child-photo img-fluid rounded-circle" />
{% else %}
<img src="{% static 'babybuddy/img/core/child-placeholder.png' %}" class="child-photo img-fluid rounded-circle" />
{% endif %}
<div class="child-name display-4">{{ object }}</div> <div class="child-name display-4">{{ object }}</div>
<p class="lead"> <p class="lead">
Born <span class="text-secondary">{{ object.birth_date }}</span><br/> Born <span class="text-secondary">{{ object.birth_date }}</span><br/>
@ -58,4 +63,4 @@
</ul> </ul>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -1,5 +1,5 @@
{% extends 'babybuddy/page.html' %} {% extends 'babybuddy/page.html' %}
{% load widget_tweaks %} {% load widget_tweaks static thumbnail %}
{% block title %}Children{% endblock %} {% block title %}Children{% endblock %}
@ -14,6 +14,7 @@
<table class="table table-striped table-hover"> <table class="table table-striped table-hover">
<thead class="thead-inverse"> <thead class="thead-inverse">
<tr> <tr>
<th><i class="fa fa-camera" aria-hidden="true"></i></th>
<th>First Name</th> <th>First Name</th>
<th>Last Name</th> <th>Last Name</th>
<th>Birth Date</th> <th>Birth Date</th>
@ -23,10 +24,20 @@
<tbody> <tbody>
{% for child in object_list %} {% for child in object_list %}
<tr> <tr>
<th scope="row"><a href="{% url 'child' child.slug %}">{{ child.first_name }}</a></th> <td>
<td>{{ child.last_name }}</td> {% if child.picture %}
<td>{{ child.birth_date }}</td> {% thumbnail child.picture 40x40 upscale crop as thumb %}
<td class="text-center"> <img src="{{ thumb.url }}" class="img-fluid rounded-circle" />
{% else %}
<img src="{% static 'babybuddy/img/core/child-placeholder.png' %}" width="40" height="40" class="img-fluid rounded-circle" />
{% endif %}
</td>
<th scope="row" class="align-middle">
<a href="{% url 'child' child.slug %}">{{ child.first_name }}</a>
</th>
<td class="align-middle">{{ child.last_name }}</td>
<td class="align-middle">{{ child.birth_date }}</td>
<td class="text-center align-middle">
<div class="btn-group btn-group-sm" role="group" aria-label="Actions"> <div class="btn-group btn-group-sm" role="group" aria-label="Actions">
{% if perms.core.change_child %} {% if perms.core.change_child %}
@ -60,4 +71,4 @@
</a> </a>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View File

@ -21,6 +21,12 @@ gulp.task('migrate', function(cb) {
spawn('pipenv', command, { stdio: 'inherit' }).on('exit', cb); spawn('pipenv', command, { stdio: 'inherit' }).on('exit', cb);
}); });
gulp.task('makemigrations', function(cb) {
var command = ['run', 'python', 'manage.py', 'makemigrations'];
command = command.concat(process.argv.splice(3));
spawn('pipenv', command, { stdio: 'inherit' }).on('exit', cb);
});
gulp.task('reset', function(cb) { gulp.task('reset', function(cb) {
spawn( spawn(
@ -42,4 +48,4 @@ gulp.task('runserver', function(cb) {
var command = ['run', 'python', 'manage.py', 'runserver']; var command = ['run', 'python', 'manage.py', 'runserver'];
command = command.concat(process.argv.splice(3)); command = command.concat(process.argv.splice(3));
spawn('pipenv', command, { stdio: 'inherit' }).on('exit', cb); spawn('pipenv', command, { stdio: 'inherit' }).on('exit', cb);
}); });