Django Girls website
This repository contains sources of Django application that powers DjangoGirls.org.
What's in it?
It's a simple CMS that contains 4 models:
- Event - a list of events and their website configuration
- EventPageContent - blocks of content that are visible on the website
- EventPageMenu - items of menu of every website
How to create new event?
Simply go to command line and run this command:
python ./manage.py new_event
And then follow the instructions.
How to manage your website?
Event
http://djangogirls.org/admin/core/event/
Here you can change:
- Meta tags - title and description of the website
- Main color - main color on the website in HEX (default is FF9400)
- Custom CSS - customize CSS on the website
- URL - url that goes after the domain (http://djangogirls.org/__url__)
- Is live? - live website is available on the homepage and can be accessed by anyone
EventPageContent
http://djangogirls.org/admin/core/eventpagecontent/
Each website comes with some default content that you can adjust to your needs. Each object is a "block" on the website that you can modify in following ways:
- Name - it's also a permalink that you can link to like this: #name
- Content - HTML is allowed
- Background - there are two available types of blocks: without background and with background. By uploading image you're choosing the type with background.
- Is public - check this if you want this block to be visible
EventPageMenu
http://djangogirls.org/admin/core/eventpagemenu/add/
To manage menu available on the website, you can add objects to EventPageMenu. Available options:
- Title
- URL
Contributing to Django Girls website
The website is hosted on PythonAnywhere and is available here: http://djangogirls.org/
Please note that we use Python 3 only, so make sure that you use correct version when running commands below.
Setting up a development environment
First, clone the repository:
git clone git@github.com:DjangoGirls/djangogirls.git
Step into newly created djangogirls
directory:
cd djangogirls
Create a new virtual environment if needed. Then, install all the required dependencies:
pip install -r requirements.txt
Start the PostgreSQL database server and enter the psql
shell (you need to have PostgreSQL installed):
psql
In the psql
shell, create a database and a role with the necessary permissions:
CREATE DATABASE djangogirls;
CREATE ROLE postgres;
GRANT ALL privileges ON DATABASE djangogirls TO postgres;
ALTER ROLE postgres WITH LOGIN;
Exit the psql
shell:
\q
Run the migration to create database schema:
./manage.py migrate
Load sample data to the database
./manage.py loaddata sample_db.json
Create a user so you can login to the admin:
./manage.py createsuperuser
Install dependencies for static files:
npm install
Compile CSS and JS files:
gulp watch
Run your local server:
./manage.py runserver
🎉 You're done.
Run the tests
You can run the tests like this:
python -m pytest
Or if you want coverage reports:
python -m pytest --cov
For a coverage report with information about missing lines, run this:
python -m pytest --cov-report term-missing --cov
Static files
We're using a Stylus as our CSS pre-processor. Get styling with Stylus.
This means you shouldn't change any css files, but .styl
files. They're in /static/source/css/ directory.
Autocompiling of .styl
files to .css
:
npx gulp watch
We're also using gulp for our static files builds (see below). To build static files for production, run this:
npx gulp build
For local development:
npx gulp local
Gulp Tasks
Static files are generated and maintained using gulp.js. To use, you'll need Node.js installed. Then, run npm install
. You can now use npx gulp
(note that it's np**x**
), followed by one of the following commands:
gulp local
- run a one-off local build of css & jsgulp watch
- compile and watch static assets for changesgulp build
- run a one-off production build, which involves minifying code and asset revision markersgulp clean
- remove the results of any of the above commands
Running gulp
on its own runs watch
by default.
Developing Gulp Tasks
Each gulp task is a single function, which are combined using the series
operator so they run as a workflow. Each are commented with what they do and why they're important.
The biggest gotcha is async completion. Each task much signal to gulp when it has finished. The easiest way to do this is using an aysnc
function, but if your functionality uses gulp streams (most native gulp functionality does), then you should not use an async
function. Instead, return the gulp stream from the function and it will be handled correctly.
// WRONG - uses gulp's streams in an async function; subsequent tasks won't wait for completion correctly:
const copyFiles = async () => {
return gulp.src(...).pipe(gulp.dest(...))
}
// RIGHT - either returns a gulp stream _or_ uses an `async` function:
const copyFiles = () => {
return gulp.src(...).pipe(gulp.dest(...))
}
const deleteFiles = async () => {
await del(...)
}
Hosting on PythonAnywhere
Key bits of config and secrets are stored in environment variables in two places:
- in the WSGI file (linked from the Web Tab)
- in the virtualenv postactivate at ~/.virtualenvs/djangogirls.com/bin/postactivate
Google Apps API integration
We're using Google Apps Admin SDK for creating email accounts in djangogirls.org domain automatically.
Several things were needed to get this working:
- Create an app in Developer Console
- Create a service account to enable 2 legged oauth (https://developers.google.com/identity/protocols/OAuth2ServiceAccount)
- Enable delegation of domain-wide authority for the service account.
- Enable Admin SDK for the domain.
- Give the service account permission to access admin.directory.users service (https://admin.google.com/AdminHome?chromeless=1#OGX:ManageOauthClients).