Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to Django 1.9 #283

Merged
merged 1 commit into from
Jul 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ install:
- sudo su - postgres -c "psql -c \"alter user round password 'round'\""
- sudo su - postgres -c "psql roundware -c 'create extension postgis'"
- pip install -r requirements/dev.txt
- sudo apt-get install --reinstall python-setuptools
before_script:
# Setup Roundware log file.
- sudo touch /var/log/roundware
Expand All @@ -24,4 +25,4 @@ before_script:
- sudo mkdir /var/www
- sudo chmod 777 /var/www
- export PYTHONPATH=.:/usr/lib/python2.7/dist-packages/
script: python roundware/manage.py test --settings=roundware.settings.testing
script: python roundware/manage.py test --settings=roundware.settings.testing
53 changes: 53 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,59 @@ Done!
The following instructions describe modifications to the standard upgrade process required due to
specific changes. Items are listed in reverse chronological order.

### 6/13/16 - Upgrade Django from 1.7 to 1.9
Related Github issue: https://github.com/roundware/roundware-server/pull/283

The time has come to upgrade Django and other required apps to their newest versions. If you are
installing Roundware from scratch, there is no need to take extra steps. However, if your
installation is based on a commit prior to the Django 1.9 migration, some manual setup is needed.

#### Detailed Steps (for production machines, not vagrant)

1. Pull the relevant post-upgrade `roundware-server` commit (or newer)
2. Remove obsolete `auth_permission` rows (see issue #291):

```
sudo su - postgres -c 'psql -c "DELETE FROM auth_permission WHERE id IN (SELECT id FROM auth_permission EXCEPT ((SELECT permission_id FROM auth_group_permissions) UNION (SELECT permission_id FROM auth_user_user_permissions)))" roundware'
```

3. Initial deploy: `sudo ./deploy.sh` (this will error on `django-guardian` but don't worry,
we're about to fix that)
4. Run migrations

```
sudo su - roundware -c "/var/www/roundware/source/roundware/manage.py migrate guardian --fake-initial"
sudo su - roundware -c "/var/www/roundware/source/roundware/manage.py migrate"
```
5. Replace apache config (note this will over-write any customizations you may have made)

```
sudo rm -f /etc/apache2/sites-available/roundware.conf
sudo su - -c "sed s/USERNAME/roundware/g /var/www/roundware/source/files/etc-apache2-sites-available-roundware > /etc/apache2/sites-available/roundware.conf"
```
6. Run `sudo ./deploy.sh`

#### Notes / Troubleshooting

* As part of the upgrade process, [django-guardian](http://django-guardian.readthedocs.io/en/stable/)
must be updated from 1.2.4 to 1.4.4. While the old versions of guardian used `syncdb` to populate
the database, newer versions use migrations. The database structures are identical; however, these
migrations do not check if the tables and relationships are already in place. Therefore, you must
suppress guardian's initial migration.
* You might have to manually uninstall `django-chartit`. `django-chartit2` is meant
to be a drop-in replacement, but if `django-chartit` is still installed, it will not work. Ensure
that the `roundware` user can access all new `site-packages`.
* You might also need to uninstall `django-admin-bootstrapped` manually. Symptomatically, if the
Django admin panel has no theme, it's likely that an old version of `django-admin-bootstrapped` was installed globally
(`/usr/local/lib`) and is now interfering with the new `django-admin-bootstrapped` in the `virtualenv`. Old versions
required `django_admin_bootstrapped.bootstrap3` to be in `INSTALLED_APPS` to render the theme.
Otherwise, it would fail silently, and no theme would be rendered. Try running `pip freeze`;
if `django-admin-bootstrapped` is `v2.0.4`, run `pip uninstall django-admin-bootstrapped`.
* Roundware's `wsgi.py` was moved in this commit, and the Apache conf file must be updated. If you
get 404 errors after upgrading, chances are you skipped this step.
* Check the log to ensure that all of the required apps are located in `/var/www/roundware/lib/`.
It isn't necessary, but it might save you some headache with permissions.

### 3/7/16 - Convert from MySQL to Postgresql for GIS speaker upgrades
Related Github issue: https://github.com/roundware/roundware-server/pull/270

Expand Down
7 changes: 1 addition & 6 deletions deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,9 @@ export PYTHONPATH=$CODE_PATH
# Install upgrade pip
pip install -U pip

# Install RoundWare requirements
# Install Roundware requirements
pip install -r $CODE_PATH/requirements.txt --upgrade

# Apply patch to fix M2M field deserializing for Tag relationships, force command to return true.
# Details: https://code.djangoproject.com/ticket/17946
# TODO: Remove when fixed in Django core, probably when upgrading to Django 1.8.
patch -N $WWW_PATH/lib/python2.7/site-packages/django/core/serializers/python.py < $CODE_PATH/files/fix-m2m-deserial.patch || true

# Set $USERNAME to own WWW_PATH files
chown $USERNAME:$USERNAME -R $WWW_PATH

Expand Down
2 changes: 1 addition & 1 deletion files/etc-apache2-sites-available-roundware
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
WSGIDaemonProcess roundware user=USERNAME group=USERNAME umask=002
WSGIApplicationGroup %{GLOBAL}
WSGIProcessGroup roundware
WSGIScriptAlias / /var/www/roundware/source/files/roundware.wsgi
WSGIScriptAlias / /var/www/roundware/source/roundware/wsgi.py
WSGIPassAuthorization On

# allow CORS for listen map, session map etc
Expand Down
15 changes: 0 additions & 15 deletions files/fix-m2m-deserial.patch

This file was deleted.

24 changes: 12 additions & 12 deletions requirements/common.txt
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
Django<1.8
Django==1.9
# Creates REST APIs
djangorestframework==3.2.2
djangorestframework==3.3.3
# Used for DRF filtering
django-filter==0.9
django-filter==0.13
# Used in roundware/rw/chart_functions.py
django-chartit==0.1
django_chartit2
# Used in roundware/rw/admin.py, roundware/rw/forms.py, roundware/rw/views, and more.
django-guardian==1.2.4
django-guardian==1.4.4
# Used by roundware/api1/commands.py
psutil==2.1.3
psutil==3.4.2
# Used by roundwared/db.py
django-cache-utils==0.7.2
# Used by roundware/rw/fields.py
django-validated-file==2.0.1
# Loaded in roundware/settings/common.py
django-admin-bootstrapped==2.0.4
# Used in roundware/rw/views.py
django-braces==1.4.0
# Loaded in roundware/urls.py
django-adminplus==0.2.1
# Used in roundware/rw/forms.py
django-crispy-forms==1.4.0
django-crispy-forms==1.6.0
# Used in roundware/rw/widgets.py
django-floppyforms==1.2
django-floppyforms==1.6.1
# Used in roundware/rw/views.py:
django-extra-views==0.6.5
# Used in roundware/rw/fields.py and roundware/rw/widgets.py
Expand All @@ -42,6 +40,8 @@ django-cors-headers
# fiona is a useful tool for processing geographic files (ETL)
fiona
# geographic extensions for djangorestframework-gis
djangorestframework-gis
djangorestframework-gis==0.10.1
# leaflet map utilities for django admin
django-leaflet
django-leaflet==0.18.0
# Bootstrap admin theme for Django 1.9
https://github.com/roundware/django-admin-bootstrapped/zipball/3.0.0
16 changes: 8 additions & 8 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
-r ./common.txt

django-debug-toolbar
django-debug-toolbar==1.4
django-profiler==2.0

#testing.
coverage==3.7.1
#testing.
coverage==4.0.3
webtest==2.0.9
django-webtest==1.7.5
model_mommy==1.2
mock==1.0.1
python-dbusmock==0.8
django-webtest==1.7.9
model_mommy==1.2.6
mock==2.0.0
python-dbusmock==0.16.3

#interactive interpreter for debugging
ipython
ipython==4.0.3
18 changes: 1 addition & 17 deletions roundware/api2/__init__.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,4 @@
# Roundware Server is released under the GNU Affero General Public License v3.
# See COPYRIGHT.txt, AUTHORS.txt, and LICENSE.txt in the project root directory.

# Contains Roundware DRF REST API V2 signals.
from __future__ import unicode_literals
from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from rest_framework.authtoken.models import Token
import logging

logger = logging.getLogger(__name__)

def create_auth_token(sender, instance=None, created=False, **kwargs):
"""
Create an access Token for every new user
"""
if created:
Token.objects.create(user=instance)

post_save.connect(create_auth_token, get_user_model)
default_app_config = 'api2.apps.RoundwareApi2Config'
10 changes: 10 additions & 0 deletions roundware/api2/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Roundware Server is released under the GNU Affero General Public License v3.
# See COPYRIGHT.txt, AUTHORS.txt, and LICENSE.txt in the project root directory.

from django.apps import AppConfig
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add the standard licensing lines that should be in all code files (including __init.py__ above)

# Roundware Server is released under the GNU Affero General Public License v3.
# See COPYRIGHT.txt, AUTHORS.txt, and LICENSE.txt in the project root directory.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Now that I look around, however, it seems that many files are missing these licensing lines. If I make other changes to this pull request, I will certainly address this. For the more general case, see #284

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool...since this PR doesn't pass Travis.ci, there will certainly need to be some updates, so you can add these changes then, as you say.


class RoundwareApi2Config(AppConfig):
name = 'api2'

def ready(self):
import roundware.api2.signals
20 changes: 20 additions & 0 deletions roundware/api2/signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Roundware Server is released under the GNU Affero General Public License v3.
# See COPYRIGHT.txt, AUTHORS.txt, and LICENSE.txt in the project root directory.

# Contains Roundware DRF REST API V2 signals.
from __future__ import unicode_literals
from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from rest_framework.authtoken.models import Token
import logging

logger = logging.getLogger(__name__)

def create_auth_token(sender, instance=None, created=False, **kwargs):
"""
Create an access Token for every new user
"""
if created:
Token.objects.create(user=instance)

post_save.connect(create_auth_token, get_user_model)
35 changes: 28 additions & 7 deletions roundware/rw/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,30 @@ def get_queryset(self, request):
return qset

accessible_projects = get_objects_for_user(
request.user, 'rw.access_project')
request.user, 'rw.access_project', Project)
authorized_objects = model_class.objects.filter(
project__in=accessible_projects)
return qset.filter(**{field_name + "__in": authorized_objects})

return get_queryset


class ProjectProtectedThroughAssetModelAdmin(admin.ModelAdmin):
queryset = project_restricted_queryset_through(Asset, 'asset')

def get_queryset(self, request):
return project_restricted_queryset_through(Asset, 'asset')(self, request)


class ProjectProtectedThroughSessionModelAdmin(admin.ModelAdmin):
queryset = project_restricted_queryset_through(Session, 'session')

def get_queryset(self, request):
return project_restricted_queryset_through(Session, 'session')(self, request)


class ProjectProtectedThroughUIModelAdmin(admin.ModelAdmin):
queryset = project_restricted_queryset_through(MasterUI, 'master_ui')

def get_queryset(self, request):
return project_restricted_queryset_through(MasterUI, 'master_ui')(self, request)


class ProjectProtectedModelAdmin(admin.ModelAdmin):
Expand All @@ -89,7 +96,22 @@ def get_queryset(self, request):
if request.user.is_superuser:
return qset

return qset.filter(project__in=get_objects_for_user(request.user, 'rw.access_project'))
# TODO: Consider using an M2M field instead, if more complex permissions not needed:
# models.py: user = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True)
# admin.py: accessible_projects = Project.objects.filter(user=request.user)

accessible_projects = get_objects_for_user(request.user, 'rw.access_project', Project)

return qset.filter(project__in=accessible_projects)

class ProjectModelAdmin(GuardedModelAdmin):

def get_queryset(self, request):

if request.user.is_superuser:
return super(admin.ModelAdmin, self).get_queryset(request)

return get_objects_for_user(request.user, 'rw.access_project', Project)


def copy_asset(modeladmin, request, queryset):
Expand Down Expand Up @@ -267,7 +289,7 @@ class VoteAdmin(ProjectProtectedThroughAssetModelAdmin):
ordering = ['id']


class ProjectAdmin(GuardedModelAdmin):
class ProjectAdmin(ProjectModelAdmin):
list_display = ('id', 'name', 'latitude', 'longitude',
'max_recording_length', 'recording_radius')
ordering = ['id']
Expand Down Expand Up @@ -295,7 +317,6 @@ class ProjectAdmin(GuardedModelAdmin):
}),
)


class SessionAdmin(ProjectProtectedModelAdmin):
list_display = ('id', 'project', 'starttime', 'device_id', 'language')
list_filter = ('project', 'language', 'starttime')
Expand Down
2 changes: 1 addition & 1 deletion roundware/rw/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from __future__ import unicode_literals
from django.contrib.admin import DateFieldListFilter, RelatedFieldListFilter
from django.contrib.admin.util import (get_model_from_relation,
from django.contrib.admin.utils import (get_model_from_relation,
prepare_lookup_value)
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_unicode
Expand Down
Loading