.. _create_new_project: Creating a new MarineMap project ================================= .. note:: Though lingcod includes several example projects, you are encouraged to create your MarineMap instance as a seperate python package outside of the lingcod source tree. This will allow for clear seperation between the underlying libraries (lingcod) and your implementation of MarineMap (the "project") Install Dependencies --------------------- You will need to install lingcod's dependencies and lingcod itself. For detailed instructions, please follow :ref:`Getting Started `. Create new django project -------------------------- In this example, we'll set up a new MarineMap instance for the state of Oregon. We use django-admin.py to create a standard django project:: cd ~/oregon_stuff django-admin.py startproject oregon You should see the following directory structure:: oregon |-- __init__.py |-- manage.py |-- settings.py `-- urls.py We now need to configure the settings and urls for our oregon project. Settings -------- First, while we appreciate django-admin's attempt at an initial settings.py file, it doesn't really work for us in this case. Because lincod contains sensible default settings, we only need to worry about MarineMap specific settings and django settings unique to this project. You can delete all the lines in settings.py *except* for the SECRET_KEY and add the following:: # Django settings for oregon project. from lingcod.common.default_settings import * BASE_DIR = os.path.dirname(os.path.abspath(__file__)) DATABASE_ENGINE = 'postgresql_psycopg2' DATABASE_NAME = 'oregon' DATABASE_USER = 'postgres' TIME_ZONE = 'America/Vancouver' LANGUAGE_CODE = 'en-us' SITE_ID = 1 USE_I18N = True SECRET_KEY = 'keep_the_one_autogenerated_by_django-admin' WAVE_ID = 'wavesandbox.com!q43w5q3w45taesrfgs' # Your Google Wave Account - may not be needed ROOT_URLCONF = 'oregon.urls' TEMPLATE_DIRS = ( os.path.realpath(os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/')), ) INSTALLED_APPS += ( 'mlpa', ) MPA_CLASS = 'mlpa.models.Mpa' ARRAY_CLASS = 'mlpa.models.MpaArray' MPA_FORM = 'mlpa.forms.MpaForm' ARRAY_FORM = 'mlpa.forms.ArrayForm' Notice the final 5 lines; Here we install an app called 'mlpa' and define the classes and forms based on that 'mlpa' app. Let's go ahead and create that app and the proper classes to match our settings. Creating MPA/Array Classes -------------------------- Lingcod is set up so that MPAs and Arrays are not installed by default. Instead we need need to create our own custom MPA and Array classes specific to this project. Luckily python's object inheritance makes it easy to use the default MPA and Array behavior if our project does not require extensive customization of these concepts. First we *must* create an app to hold our custom MPA and Array information:: cd oregon python manage.py startapp mlpa Here we should see the following directory structure created for us:: mlpa |-- __init__.py |-- models.py |-- tests.py `-- views.py We can ignore the tests and views for now; for now we'll focus on creating the Mpa and MpaArray models. Open mlpa/models.py and add:: from lingcod.mpa.models import Mpa as BaseMpa from lingcod.array.models import MpaArray as BaseMpaArray class Mpa(BaseMpa): pass class MpaArray(BaseMpaArray): pass You can see that we merely took the abstract base classes from lingcod which define the default behavior and created our own classes based on them. If you need to customize the behavior, you can extend the models here instead of simply 'pass'ing. Finally we'll need to create some django forms for Mpa and MpaArray objects. These define how the editing interfaces will appear in MarineMap. Create a new file mlpa/forms.py and add:: from lingcod.mpa.forms import MpaForm as BaseMpaForm from lingcod.array.forms import ArrayForm as BaseArrayForm from models import Mpa, MpaArray class ArrayForm(BaseArrayForm): class Meta(BaseArrayForm.Meta): model = MpaArray exclude = ('sharing_groups',) class MpaForm(BaseMpaForm): class Meta: model = Mpa exclude = ('sharing_groups','content_type','object_id',) This is slightly more involved but the concept is similar to the classes - we take the default behavior of lingcod's Mpa and Array forms and extend them for this project. Urls ---- In order for django to successfully route requests, we need to define URL patterns for the common lingcod operations. Modify your urls.py to show the following:: from django.conf.urls.defaults import * from django.conf import settings from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', url(r'^$', 'lingcod.common.views.map', {'template_name': 'common/map.html'}, name="map"), (r'^tests/', 'django.views.generic.simple.direct_to_template', {'template': 'common/tests.html', 'extra_context': {'api_key': settings.GOOGLE_API_KEY}}), (r'^layers/', include('lingcod.layers.urls')), (r'^studyregion/', include('lingcod.studyregion.urls')), (r'^faq/', include('lingcod.simplefaq.urls')), (r'^help/', include('lingcod.help.urls')), (r'^kml/', include('lingcod.kmlapp.urls')), (r'^manipulators/', include('lingcod.manipulators.urls')), (r'^mpas/', include('lingcod.mpa.urls')), (r'^arrays/', include('lingcod.array.urls')), url(r'^accounts/logout/$', 'django.contrib.auth.views.logout', {'next_page': settings.LOGIN_REDIRECT_URL}, name='auth_logout'), (r'^accounts/profile/', include('lingcod.user_profile.urls')), (r'^accounts/', include('lingcod.common.registration_backend.urls')), (r'^intersection/', include('lingcod.intersection.urls')), (r'^screencasts/', include('lingcod.screencasts.urls')), (r'^sharing/', include('lingcod.sharing.urls')), (r'^staticmap/', include('lingcod.staticmap.urls')), (r'^news/', include('lingcod.news.urls')), (r'^admin/', include(admin.site.urls)), ) # Useful for serving files when using the django dev server urlpatterns += patterns('', (r'^media/(?P.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT, 'show_indexes': True }), ) Databases ---------- Next we'll create a new postgis-enabled database for this project and use django's syncdb command to create the necessary tables. Assuming you installed postgis functions, etc into your postgres template1, this is as simple as:: createdb oregon -U postgres Study Region ------------- Every project needs to define a :ref:`study region`. This is a (multi)polygon shape which defines where shapes can be created. Because new shapes are clipped to this study region boundary, it is highly recomended to give this step great consideration up front; changing the study region boundary at a later date is MUCH more complicated. Let's assume that we have created a shapefile containing a single polyon feature representing the waters within 5 kilometers of the oregon coast. This shapefile is in UTM Zone 10N, WGS84 datum which corresponds to the SRID 32610 (see http://www.spatialreference.org/ref/epsg/32610/). This is also the projection we want to use for storing our shapes so we'll add this to our settings.py:: GEOMETRY_DB_SRID = 32610 First we have to create some necessary table in the database:: python manage.py syncdb python manage.py migrate Next, we'll use some custom lingcod management commands to load up our carefully and meticulously created study region:: python manage.py create_study_region --name oregon_coast data/oregon_study_region.shp python manage.py change_study_region 1 Migrating our MLPA app ---------------------- We need to put our mlpa app under migration which ensures that future changes to the MLPA models' schema get reflected in the database:: python manage.py schemamigration --initial mlpa python manage.py migrate mlpa --fake Static Media ------------ All static media is split between the project and the lingcod library. The project media goes in a 'media' directory at the same level as your project directory. (ie ~/oregon_stuff/oregon/ is your django project, ~/oregon_stuff/media is your oregon media dir). First you must define the MEDIA_ROOT in our settings.py file:: MEDIA_ROOT = '/var/www/oregon_media' The install_media command will then take all files from lingcod media and oregon media directories and combine them into this directory. It is safe to assume that when you deploy marinemap you'll want this directory to be fully web accessible:: python manage.py install_media This step also compresses all js and css using the django-compress app to ensure that your js and css are single compact files to maximize performance. Deployment ---------- For now, we'll just test our new project using django's built-in development server. First we need to set up the sites framework so that our domain is accurate for any absolute urls created by our MarineMap project. Then run the dev server to test it:: python manage.py site_setup_for_dev python manage.py sharing_setup python manage.py runserver Our Oregon MarineMap project should now be accessible at http://localhost:8000/ Next steps ---------- MarineMap has fixtures containing test data that is installed on database setup like an example :ref:`Study Region ` and :ref:`layers`. This makes it easy to verify the installation and learn how the tool works. For use in an actual planning session these default datasets will need to be replaced. See the documentation in the following sections to customize MarineMap as needed: .. toctree:: :maxdepth: 1 study_region layers managing_users marine_protected_areas static_map_configuration sharing_configuration kml_configuration template_customization The setup this guide has walked through only specifies how to run the django development server. To setup a public facing website using Apache, consult the :ref:`deployment` notes.