Skip to content
josmas edited this page Apr 27, 2012 · 37 revisions

This page is a work in progress: I started it to put my personal notes while I go through the source code. Feel free to add/amend/delete as needed. Disclaimer: I'm new to Django so information here can be wrong. If anyone can contrast this information, please feel free to delete this disclaimer!

Introduction

Lernanta is the code that makes P2PU run. It is based on the Python web development framework Django.

This is an open source project and as such it welcomes contributions from the community. To get started you will need to download the source code. Instructions can be found in the Development Documentation section of this wiki. You can also follow the fantastic course Introduction to Lernanta from the P2PU site.

Project structure

As it is common in Django projects, Lernanta is divided into several applications and it also re-uses third party ones.

Code for the different applications in Lernanta can be found in the module structure lernanta.apps.application-name, where application-name is one of the specific applications created for the system (for instance badges, dashboard, or schools). The templates for those applications can be found in lernanta/templates/application-name.

Inside each of the applications the following files can be found (Note that not all applications need all these files):

  • models.py : contains the models to be persisted to the database

  • views.py : contains code to handle user requests. This is generally considered as controller code in other frameworks

  • urls.py : contains the routes that map actions in the views

  • admin.py : contains code for the admin site for the particular application

  • decorators.py : contains decorators that can be used in the views

  • forms.py : contains code to use in forms in the templates section

  • tests.py : contains tests for the app

  • tasks.py : celery task that happens asynchronously

  • utils.py : ???

Diving into the code

Classes and stuff

Most classes inherit from ModelBase in the Drumbeat application. From this they inherit models.Model so that they can be persisted to the DB through Django's own ORM.

A Project can be a Course, a Study Group, or a Challenge. This property is stored in the category field of the Project model.

All types of content have been abstracted as Page models in the content app. It seems to model Tasks and other functionality in the form of an abstract page (to be presented to the user).

As far as I can see the default Django templates are used. Although Jinja2 is installed as a development dependency to use test_utils.

Querying objects in Django is done through the object's Manager. At least one Manager exists, objects, which is only accessible through the model class (not from instances). Some models in Lernanta provide their own custom Manager i.e. ProjectManager, which provides custom methods to access popular and active projects. The manager can be override in the model with the following code:

objects = ProjectManager()

Lernanta uses the underlying User Authentication provided but Django. Each user has a User Profile and everything that has to do with user profiles is handled in the users app.

Templates and stuff

The base template is located in the templates folder and it is called base.html. Other templates extend this one. If you are not familiar with template inheritance follow this link.

I am a bit confused about Pages here, cause a Page seems to encapsulate everything that it's shown to the user but there is only one template for the content app and a bunch of pages for projects and so on... investigate more!

An example of custom template tags can be seen in the base class in the line:

{% load school_tags %}

This loads the custom tags created in the templatetags folder of the schools app.

Programming Testing

Please have a look at How to test Django applications if you are unfamiliar with the topic.

Lernanta uses nose which is an extension on unittest to make testing easier. The particular package django-nose is used in here.

As far as I can see django-nose and test_utils both are tests runners (although the latter does a bunch of stuff more). TODO: check with Zuzel if both are being used. This particular test_utils skips database creation if the db already exists so integration tests for models run faster. It can also provide mock Request objects to isolate your tests to a degree. Not sure why test_util.TestCase is used though, cause seems to be the same as django.test.TestCase but injecting Jinja, and I don't think Jinja is used at all... check this one too!

Caching

Lernata uses memcached as a caching solution, as can be seen in the configuration file for non local environments. TODO: check this cause I cannot see any memcache calls in the code (although as noted below, there is some Django caching going on).

Locally, for development purposes, it defaults to the dummy cache provided by Django.

TODO: there are some caching arguments passed into drumbeat main ModelBase (import caching.base); find out what is that about... More information on Django caching

Some examples of caching in the Project model. See both cache.get(...) and cache.set(...) actions there.

Celery tasks

There are two places were Celery tasks are used, one is in the users app, and the other in the links app.

In production RabbitMQ is used, if you want to know more about the settings have a look at the set-up in production document.

Keeping up with the development repository

Lernanta development moves fast so to keep up to date you have to pull changes from the main repository (generally called upstream if you have followed github documentation on forking repos) quite often. After a pull, you will need to run any migrations generated by changes to the model classes. To do so you can just type in your console:

./manage.py migrate

More information on generating and running migrations with South in the docs.

From time to time some of the packages that Lernanta depends on will also change, for instance, to upgrade Django to a new release. In that case the contents of the requirements folder will change and you can use the following command to install the new dependencies (note that installing dev.txt will pull in the dependencies in prod.txt):

pip install -r requirements/dev.txt

That command should work assuming that you are using virtualenv, otherwise you might need sudo to install some of the packages needed.

If any of the changes your are pulling are in any of the apps models you will have to run the migrations as:

python manage.py migrate --all --delete-ghost-migrations

adding some data to a local DB

python manage.py loaddata apps/badges/fixtures/test_challenges_with_bagdes.json

username: administrator password: password (that is the logins details of the user that will be created). It is missing many things but it will add a couple of challenges and badges to the database.

Non lernanta apps

List of django apps that lernanta re-uses:

django-taggit is used to make tagging easier. You can see an example in the Projects model tag attribute.

Non lernanta dependencies

South to handle migrations.

Nose as a test runner for programmer's testing.

distribute as a replacement for setuptools.

Celery as a distribute Tasks queue.

Beautiful Soup for screen scrapping.