Skip to content

Commit d69c9e8

Browse files
committed
Upgrade to django 1.11, upgrade django pipeline, use whitenoise for static
Based on LeoVerto's work at #11 thanks Leo! Running in docker means that using whitenoise for static files is easier than serving static files with nginx or other.
1 parent d639b85 commit d69c9e8

File tree

18 files changed

+71
-71
lines changed

18 files changed

+71
-71
lines changed

botbot/apps/bots/migrations/0001_initial.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from __future__ import unicode_literals
33

44
from django.db import models, migrations
5-
import djorm_pgarray.fields
5+
import django.contrib.postgres.fields
66

77

88
class Migration(migrations.Migration):
@@ -57,7 +57,7 @@ class Migration(migrations.Migration):
5757
fields=[
5858
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, help_text='', auto_created=True)),
5959
('dt', models.DateField(help_text='')),
60-
('counts', djorm_pgarray.fields.ArrayField(blank=True, null=True, default=None, help_text='')),
60+
('counts', django.contrib.postgres.fields.ArrayField(base_field=models.IntegerField(blank=True), blank=True, size=None)),
6161
('channel', models.ForeignKey(help_text='', to='bots.Channel')),
6262
],
6363
options={

botbot/apps/bots/models.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
import random
33
import string
44
import uuid
5+
from collections import OrderedDict
56

67
from django.core.cache import cache
78
from django.db import models
89
from django.db.models import Max, Min
910
from django.db.models.aggregates import Count
10-
from django.utils.datastructures import SortedDict
1111
from django.utils.text import slugify
12-
from djorm_pgarray.fields import ArrayField
12+
from django.contrib.postgres.fields.array import ArrayField
1313

1414
from botbot.apps.plugins import models as plugins_models
1515
from botbot.apps.plugins.models import Plugin, ActivePlugin
@@ -259,7 +259,7 @@ def filtered_logs(self):
259259

260260
def get_months_active(self):
261261
"""
262-
Creates a SortedDict of the format:
262+
Creates a OrderedDict of the format:
263263
{
264264
...
265265
'2010': {
@@ -277,14 +277,14 @@ def get_months_active(self):
277277
last_log=Max("timestamp"),
278278
first_log=Min("timestamp"))
279279
if not minmax_dict['first_log']:
280-
return SortedDict()
280+
return OrderedDict()
281281
# cache for 10 days
282282
cache.set(minmax_dict_key, minmax_dict, 864000)
283283
first_log = minmax_dict['first_log'].date()
284284
last_log = minmax_dict['last_log'].date()
285285
last_log = datetime.date(last_log.year, last_log.month, 1)
286286
current = datetime.date(first_log.year, first_log.month, 1)
287-
months_active = SortedDict()
287+
months_active = OrderedDict()
288288
while current <= last_log:
289289
months_active.setdefault(current.year, []).append(current)
290290
if current.month == 12:
@@ -337,7 +337,7 @@ class UserCount(models.Model):
337337

338338
channel = models.ForeignKey(Channel)
339339
dt = models.DateField()
340-
counts = ArrayField(dbtype="int")
340+
counts = ArrayField(models.IntegerField(blank=True), blank=True)
341341

342342
def __unicode__(self):
343343
return "{} on {}: {}".format(self.channel, self.dt, self.counts)

botbot/apps/bots/urls.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
from django.conf.urls import patterns, url
1+
from django.conf.urls import url
22

33
from . import views
44

5-
urlpatterns = patterns('',
5+
urlpatterns = [
66
url(r'^manage/$', views.ManageChannel.as_view(), name='manage_channel'),
77
url(r'^delete/$', views.DeleteChannel.as_view(), name='delete_channel'),
8-
)
8+
]

botbot/apps/logs/templatetags/logs_tags.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
"""Near duplicate of Django's `urlizetrunc` with support for image classes"""
22
import urlparse
33

4-
from django.template.base import Library, Node
4+
from django.template.base import Node
5+
from django.template.library import Library
56
from django.template.defaultfilters import stringfilter
67
from django.utils.safestring import mark_safe, SafeData
78
from django.utils.encoding import force_text
89
from django.utils.functional import allow_lazy
910
from django.utils import six
10-
from django.utils.html import (TRAILING_PUNCTUATION, WRAPPING_PUNCTUATION,
11+
from django.utils.html import (TRAILING_PUNCTUATION_CHARS, WRAPPING_PUNCTUATION,
1112
word_split_re, simple_url_re, smart_urlquote,
12-
simple_url_2_re, simple_email_re, escape)
13+
simple_url_2_re, escape)
1314
import re
1415

1516

@@ -19,6 +20,8 @@
1920
IMAGE = 1
2021
YOUTUBE = 2
2122

23+
email_re = re.compile(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)")
24+
2225

2326
@register.filter(is_safe=True, needs_autoescape=True)
2427
@stringfilter
@@ -176,7 +179,7 @@ def urlize_impl(text, trim_url_limit=None, nofollow=False, autoescape=False):
176179
if '.' in word or '@' in word or ':' in word:
177180
# Deal with punctuation.
178181
lead, middle, trail = '', word, ''
179-
for punctuation in TRAILING_PUNCTUATION:
182+
for punctuation in TRAILING_PUNCTUATION_CHARS:
180183
if middle.endswith(punctuation):
181184
middle = middle[:-len(punctuation)]
182185
trail = punctuation + trail

botbot/apps/logs/urls.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
from django.conf.urls import patterns, url
1+
from django.conf.urls import url
22

33
from . import views
44

5-
urlpatterns = patterns('',
5+
urlpatterns = [
66
url(r'(?P<year>\d{4})-(?P<month>0[1-9]|1[0-2])-(?P<day>0[1-9]|[1-2][0-9]|3[0-1])/$',
77
views.DayLogViewer.as_view(), name="log_day"),
88
url(r'(?P<year>\d{4})-(?P<month>0[1-9]|1[0-2])-(?P<day>0[1-9]|[1-2][0-9]|3[0-1]).log$',
@@ -18,4 +18,4 @@
1818
url(r'^stream/$', views.LogStream.as_view(), name='log_stream'),
1919
url(r'^$', views.DayLogViewer.as_view(),
2020
name="log_current"),
21-
)
21+
]

botbot/apps/logs/views.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def _timeline_context(timeline):
171171

172172
# the last month in the timeline needs special treatment so it
173173
# doesn't get ordered ahead of the last/current weeks
174-
last_month = timeline[timeline.keyOrder[-1]].pop()
174+
last_month = timeline.popitem(last=True)[1][-1]
175175
if last_month >= last_week:
176176
last_month_adjusted = (last_week -
177177
datetime.timedelta(days=1))

botbot/apps/plugins/migrations/0002_auto_20140912_1656.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
from __future__ import unicode_literals
33

44
from django.db import models, migrations
5-
from django.db.models.loading import get_model
5+
from django.apps import apps
66

77

88
def initial_plugins(*args):
9-
Plugin = get_model('plugins', 'Plugin')
9+
Plugin = apps.get_model('plugins', 'Plugin')
1010

1111
intial = [
1212
{

botbot/apps/plugins/models.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from django.core.cache import cache
22
from django.contrib.admindocs.utils import trim_docstring
33
from django.db import models
4-
from django.utils.importlib import import_module
4+
from importlib import import_module
55

66
from botbot.core.fields import JSONField
77

botbot/apps/sitemap/urls.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""
22
Site map URLs
33
"""
4-
from django.conf.urls import patterns, url
4+
from django.conf.urls import url
55
from django.contrib import sitemaps
66
from django.contrib.sitemaps.views import sitemap
77
from django.core.urlresolvers import reverse
@@ -27,9 +27,9 @@ def location(self, item):
2727
'static': StaticSitemap,
2828
}
2929

30-
urlpatterns = patterns('',
30+
urlpatterns = [
3131
url(r'^$', cache_page(86400)(sitemap), {'sitemaps': sitemaps},
3232
name='sitemap'),
33-
)
33+
]
3434

3535

botbot/core/fields.py

-14
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,10 @@
33
from django.db import models
44
from django.core.serializers.json import DjangoJSONEncoder
55

6-
from django.forms import fields
7-
from django.forms.util import ValidationError
8-
9-
10-
116
class JSONField(models.TextField):
127
"""JSONField is a generic textfield that neatly serializes/unserializes
138
JSON objects seamlessly"""
149

15-
# Used so to_python() is called
16-
__metaclass__ = models.SubfieldBase
17-
1810
def to_python(self, value):
1911
"""Convert our string value to JSON after we load it from the DB"""
2012
if value == "":
@@ -42,9 +34,3 @@ def value_from_object(self, obj):
4234
if self.null and value is None:
4335
return None
4436
return json.dumps(value)
45-
46-
try:
47-
from south.modelsinspector import add_introspection_rules
48-
add_introspection_rules([], ["^botbot\.core\.fields\.JSONField"])
49-
except ImportError:
50-
pass

botbot/jinja2.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def environment(**options):
2121
"jinja2.ext.autoescape",
2222
"jinja2.ext.with_",
2323
"jinja2.ext.i18n",
24-
'pipeline.templatetags.ext.PipelineExtension',
24+
'pipeline.jinja2.PipelineExtension',
2525
'django_jinja.builtins.extensions.CacheExtension',
2626
]
2727
env = Environment(**options)

botbot/settings/_asset_pipeline.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
PIPELINE_CSS_COMPRESSOR = ''
2-
PIPELINE_JS_COMPRESSOR = ''
3-
41
PIPELINE_CSS = {
52
'screen': {
63
'source_filenames': ('css/screen.css',),
@@ -47,3 +44,10 @@
4744
'output_filename': 'channel.js',
4845
},
4946
}
47+
48+
PIPELINE = {
49+
'CSS_COMPRESSOR': 'pipeline.compressors.NoopCompressor',
50+
'JS_COMPRESSOR': 'pipeline.compressors.NoopCompressor',
51+
'STYLESHEETS': PIPELINE_CSS,
52+
'JAVASCRIPT': PIPELINE_JS,
53+
}

botbot/settings/base.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
'botbot.core',
3636

3737
'pipeline',
38+
'whitenoise.runserver_nostatic',
3839

3940
'django.contrib.auth',
4041
'django.contrib.contenttypes',
@@ -167,6 +168,7 @@
167168
'django.contrib.messages.middleware.MessageMiddleware',
168169
'django.middleware.clickjacking.XFrameOptionsMiddleware',
169170
'botbot.core.middleware.TimezoneMiddleware',
171+
'whitenoise.middleware.WhiteNoiseMiddleware',
170172
]
171173

172174
#==============================================================================
@@ -199,7 +201,7 @@
199201
'handlers': {
200202
'null': {
201203
'level': 'DEBUG',
202-
'class': 'django.utils.log.NullHandler',
204+
'class': 'logging.NullHandler',
203205
},
204206
'console': {
205207
'level': 'DEBUG',

botbot/urls/admin.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
from django.conf.urls import patterns, include
1+
from django.conf.urls import include, url
22
from django.contrib import admin
33

44
admin.autodiscover()
55

6-
urlpatterns = patterns('',
7-
(r'^admin/doc/', include('django.contrib.admindocs.urls')),
8-
(r'^admin/', include(admin.site.urls)),
9-
)
6+
urlpatterns = [
7+
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
8+
url(r'^admin/', include(admin.site.urls)),
9+
]

botbot/urls/base.py

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,30 @@
11
from django.conf import settings
2-
from django.conf.urls import patterns, url, include
2+
from django.conf.urls import url, include
3+
from django.shortcuts import render
34

45
from botbot.apps.bots.views import ChannelList
56
from botbot.apps.preview.views import LandingPage
67

7-
channel_patterns = patterns('',
8+
channel_patterns = [
89
url(r'', include('botbot.apps.logs.urls')),
9-
)
10+
]
1011

11-
urlpatterns = patterns('',
12-
(r'^$', LandingPage.as_view()),
13-
url(r'^sitemap\.xml$', include('botbot.apps.sitemap.urls')),
12+
urlpatterns = [
13+
url(r'^$', LandingPage.as_view()),
14+
url(r'^sitemap\.xml', include('botbot.apps.sitemap.urls')),
1415

1516
url(r'^(?P<bot_slug>[\-\w\:\.]+(\@[\w]+)?)/(?P<channel_slug>[\-\w\.]+)/',
1617
include(channel_patterns)),
1718
url(r'^(?P<network_slug>[\-\w\.]+)/$', ChannelList.as_view())
18-
)
19+
]
1920

2021
if settings.INCLUDE_DJANGO_ADMIN:
2122
from .admin import urlpatterns as admin_urlpatterns
2223
# Prepend the admin urls.
2324
urlpatterns = admin_urlpatterns + urlpatterns
2425

2526
if settings.DEBUG:
26-
urlpatterns += patterns('django.shortcuts',
27-
url(r'^404/$', 'render', {'template_name': '404.html'}),
28-
url(r'^500/$', 'render', {'template_name': '500.html'}),
29-
)
27+
urlpatterns += [
28+
url(r'^404/$', lambda r: render(r, template_name='404.html')),
29+
url(r'^500/$', lambda r: render(r, template_name='500.html')),
30+
]

docker/services/uwsgi/consul-template-uwsgi.conf

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ template {
44
}
55

66
exec {
7-
command = "env $(cat /srv/botbot-web/environment | grep -v ^# | xargs) uwsgi --die-on-term /etc/uwsgi/uwsgi.ini"
7+
command = "env $(cat /srv/botbot-web/environment | grep -v ^# | xargs) python /srv/botbot-web/manage.py collectstatic --noinput && env $(cat /srv/botbot-web/environment | grep -v ^# | xargs) uwsgi --die-on-term /etc/uwsgi/uwsgi.ini"
88
splay = "5s"
99
reload_signal = "SIGHUP"
1010
kill_signal = "SIGTERM"

environment.ctmpl

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,5 @@ DJANGO_SETTINGS_MODULE=botbot.settings
3636
ALLOWED_HOSTS=chatlogs.metabrainz.org,test-chatlogs.metabrainz.org
3737
PYTHONIOENCODING=utf8
3838
LANG=en_US.UTF-8
39-
DEBUG=False
39+
DEBUG=False
40+
VAR_ROOT=/data

requirements.txt

+12-9
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
1-
django==1.8.4
1+
django==1.11.29
22

33
pytz
44
Jinja2==2.7.3
5-
django-jinja==1.4.1
5+
django-jinja==2.6.0
66
psycopg2==2.7.3.2
77
dj-database-url==0.2.2
88
# TODO (yml): Remove hstore when we squash the migration
99
django-hstore==1.2.5
1010

1111
markdown==2.3.1
1212
redis==2.9.1
13-
django-pipeline==1.5.1
13+
django-pipeline==1.7.0
1414
honcho==0.5.0
1515

16-
djorm-ext-pgfulltext==0.9.0
17-
djorm-ext-pgarray==0.9.0
16+
djorm-ext-pgfulltext==0.10
17+
djorm-pgarray==1.2
1818

19-
django-allauth==0.20.0
20-
requests==2.7.0
21-
oauthlib==0.7.2
22-
requests-oauthlib==0.5.0
19+
django-allauth==0.40.0
20+
requests==2.23.0
21+
oauthlib==3.1.0
22+
requests-oauthlib==1.3.0
2323
django-bootstrap-toolkit==2.15.0
2424

2525
geoip2==2.1.0
@@ -30,3 +30,6 @@ geoip2==2.1.0
3030
# For plugins
3131
-e git+https://github.com/metabrainz/brainzbot-plugins.git#egg=brainzbot-plugins
3232

33+
# For production
34+
uwsgi==2.0.21
35+
whitenoise==4.1.4

0 commit comments

Comments
 (0)