Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
6b507c6
Added multiple user profiles.
arocks Jan 28, 2015
53a72ab
Alter field
arocks Jan 28, 2015
5b4a2a6
admin for profile inlined into user admin
arocks Jan 28, 2015
d173e00
Setup signals to add the profile whenever user is created
arocks Jan 28, 2015
d5fa704
Renamed 'accounts' app to 'profiles'
arocks Jan 28, 2015
204ef67
Improved format string syntax to truncate
arocks Jan 28, 2015
a027977
Added posts app with Post and Comment models
arocks Jan 28, 2015
90ae122
Added sightings app with admin classes
arocks Jan 30, 2015
117d5e0
Added Service Object for superhero name check
arocks Jan 30, 2015
dd0d37d
Added birthday field and age property field
arocks Jan 30, 2015
71ac511
Added Like model for Posts
arocks Jan 30, 2015
aebd0c8
Added str definitions for models in sighting app
arocks Jan 30, 2015
960ecda
Reordered imports based on Krace's review comment
arocks Jan 31, 2015
92d055d
Fixed bug while calling MockWebClient
arocks Jan 31, 2015
2f964e3
Made profile field nullable.
arocks Feb 3, 2015
0edf8be
Added chapter notes
arocks Feb 3, 2015
72c63d9
Moved chapter notes to README for github visibility
arocks Feb 23, 2015
f5b4ca9
Remove unused imports
kracekumar Mar 11, 2015
8994882
Remove unused import in urls
kracekumar Mar 11, 2015
f9ffcdf
Merge pull request #1 from kracekumar/chapter03
DjangoPatternsBook Mar 13, 2015
a3c4746
Update README.md
DjangoPatternsBook Mar 14, 2015
b130e14
Removing bootstrap sub-app due to upstream changes
arocks Nov 8, 2015
300b5a7
Django 1.8 warnings fixed
arocks Nov 8, 2015
3161fed
Merge branch 'chapter03' into final
arocks Nov 8, 2015
4ee2996
Cosmetic changes to home for superheroes
arocks Nov 8, 2015
c4f91e7
Home page shows personal feed after login
arocks Nov 8, 2015
931159e
Added missing post snipped
arocks Nov 8, 2015
8ffe54c
Added initial data creation script
arocks Nov 8, 2015
3292e22
Refactored my_feed to a separate view
arocks Nov 9, 2015
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
139 changes: 6 additions & 133 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,139 +1,12 @@
# SuperBook
# Final

SuperBook is a social network for superheroes built with [Python][0] using the [Django Web Framework][1].
Run the following commands to create initial data and run the test server:

## Chapters

These are the chapters containing Django code samples from the book 'Django Design Patterns and Best Practices' by Arun Ravindran:

* [Chapter 3](https://github.com/DjangoPatternsBook/superbook/tree/chapter03)
* [Chapter 4](https://github.com/DjangoPatternsBook/superbook/tree/chapter04)
* [Chapter 5](https://github.com/DjangoPatternsBook/superbook/tree/chapter05)
* [Chapter 6](https://github.com/DjangoPatternsBook/superbook/tree/chapter06)
* [Chapter 7](https://github.com/DjangoPatternsBook/superbook/tree/chapter07)
* [Chapter 9](https://github.com/DjangoPatternsBook/superbook/tree/chapter09)

# Installation

The installation instructions have been split into the following sections:

* Creation of a new Virtual Environment (read your OS-specific section)
* Installation of the superbook project (common for all OS)

## Creation of a new Virtual Environment

Virtual environment module is now bundled with Python 3.4. As it is fairly new, most users might not be familiar with using it. Hence, OS-specific installation instructions are given below.

If you OS or distribution is missing here, please skip to 'Others' section.

### Windows 7 or 8

Follow this [detailed guide](http://arunrocks.com/guide-to-install-python-or-pip-on-windows/). In summary:

1. If you don't have Python 3.4 then download the Python MSI installer from http://www.python.org/download/
2. Run the installer. Be sure to check the option to add Python to your PATH while installing.
3. Open PowerShell as admin by right clicking on the PowerShell icon and selecting ‘Run as Admin’
4. To solve permission issues, run the following command:

Set-ExecutionPolicy Unrestricted

5. Enter the following commands in PowerShell to download the bootstrap scripts for easy_install and pip:

mkdir c:\envs
cd c:\envs

(new-object System.Net.WebClient).DownloadFile('https://bootstrap.pypa.io/ez_setup.py', 'c:\envs\distribute_setup.py')

(new-object System.Net.WebClient).DownloadFile('https://raw.github.com/pypa/pip/master/contrib/get-pip.py', 'c:\envs\get-pip.py')

python c:\envs\distribute_setup.py
python c:\envs\get-pip.py

Now typing easy_install or pip should work

6. Check that you have the correct version of Python i.e. Python 3.4 and above:

$ python --version
Python 3.4.0

7. To create a Virtual Environment, use the following commands:

python -m venv sbenv
.\sbenv\Scripts\Activate.bat

### ArchLinux

Check that you have the correct version of Python i.e. Python 3.4 and above:

$ python --version
Python 3.4.0

Create a new virtual environment called `sbenv` and activate it:

$ python -m venv sbenv
$ source sbenv/bin/activate

### Ubuntu (14.10 and below)

Install Python 3.4:

$ sudo apt-get update
$ sudo apt-get install python3.4

Check that you have the correct version of Python i.e. Python 3.4 and above. Note that you need to mention `python3` command or Python 2 will be executed:

$ python3 --version
Python 3.4.2

Create a new virtual environment called `sbenv` (without pip) and activate it:

$ python3 -m venv --without-pip sbenv
$ source sbenv/bin/activate

Now you need to install pip. This command need `wget` to be installed first.

$ wget bootstrap.pypa.io/get-pip.py -O - | python

## Installation of the project

Upgrade your version of pip:

$ pip install -U pip

Make sure that `git` is installed before running the next command. Clone the example project from github and install the dependencies.

$ git clone https://github.com/DjangoPatternsBook/superbook.git
$ cd superbook
$ pip install -r requirements.txt

If pip installation fails, especially if you are on Windows, then try forcing the installation of wheels:

$ pip install --use-wheel -r requirements.txt

## Running each chapter

Each chapter is a seperate git branch with the naming convention `chapternn`; for e.g. `chapter04`. Once you checkout the chapter don't forget to read the README.md file (which changes) and run the migrate command if applicable:

$ git checkout chapter04
$ git clean -f -d
$ cd src
$ ./create_initial_data.py
$ python manage.py runserver

Now you can read the relevant source code. Each chapter is a standalone running site. So to run the site on the test server, run the following commands:

$ python manage.py migrate
$ python manage.py createsuperuser
$ python manage.py runserver

## Finished Site

If you would like to have a look at the finished SuperBook website, just run migrate and start the test server:

$ git checkout final
$ python manage.py migrate
$ python manage.py createsuperuser
$ python manage.py runserver
## Note

**DEMO SITE UNDER CONSTRUCTION**
Currently, this is a mix of various chapters. There is a social network somewhere here. Thankfully, your hidden superpower is programming. So, what are you waiting for? :)

[0]: https://www.python.org/
[1]: https://www.djangoproject.com/
3 changes: 0 additions & 3 deletions src/accounts/admin.py

This file was deleted.

3 changes: 0 additions & 3 deletions src/accounts/models.py

This file was deleted.

67 changes: 67 additions & 0 deletions src/create_initial_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/usr/bin/env python
import os

SUPERUSER_NAME = "hexa"
SUPERUSER_PASSWORD = "hexa"
SUPERUSER_EMAIL = "hexa@superbook.com"

if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "superbook.settings")
import django
django.setup()
print("Django configured...")
from django.core import management
print("Checking apps...")
management.call_command('check')
print("Migrating...")
management.call_command('migrate', interactive=False, verbosity=2)

# Create superuser
print("Creating superuser...")
from django.contrib.auth import get_user_model
User = get_user_model()
su = User.objects.create_superuser(username=SUPERUSER_NAME,
email=SUPERUSER_EMAIL,
password=SUPERUSER_PASSWORD)
su.profile.bio = "An ex-KGB scientist who accidentally discovered human levitation"
su.profile.save()
su.first_name = "Hexa"
su.save()
print("""
SUPERUSER CREATED!
------------------------

NAME: {}
PASSWORD: {}

Login to the website with the above credentials.
""".format(SUPERUSER_NAME, SUPERUSER_PASSWORD))

#
# Create another user
blitz = User.objects.create_user(username="blitz",
email="blitz@superbook.com",
password="blitz")
blitz.first_name = "Blitz"
blitz.profile.bio = "A fine extra-terrestrial athlete"
blitz.profile.save()
blitz.save()

#
# Create fans
fans = [User.objects.create_user(username="fan{}".format(i),
email="fan{}@email.com".format(i),
password="fan")
for i in range(10)]

#
# Create some test posts
from posts.models import Post
Post.objects.create(posted_by=su, message="My first message")
Post.objects.create(posted_by=su, message="My second message")
Post.objects.create(posted_by=su, message="My third message")
Post.objects.create(posted_by=blitz, message="Yo to Everyone!!!")
Post.objects.create(posted_by=blitz,
privacy='individual',
recipient=blitz,
message="Yo to just Me...")
File renamed without changes.
6 changes: 6 additions & 0 deletions src/posts/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.contrib import admin
from . import models

admin.site.register(models.Post)
admin.site.register(models.Comment)
admin.site.register(models.Like)
18 changes: 18 additions & 0 deletions src/posts/managers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from django.db.models.query import QuerySet
from django.db.models import Q


class PostQuerySet(QuerySet):
def public_posts(self):
return self.filter(privacy="public")

def private_posts(self, user):
""" Includes only posts sent by user or marked user as reciepient"""
return self.filter(Q(privacy="individual"),
Q(posted_by=user) | Q(recipient=user))

def viewable_posts(self, user):
combined = self.public_posts() | self.private_posts(user)
return combined.order_by("-created")

PostManager = PostQuerySet.as_manager
58 changes: 58 additions & 0 deletions src/posts/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
from django.conf import settings


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='Comment',
fields=[
('id', models.AutoField(verbose_name='ID', auto_created=True, primary_key=True, serialize=False)),
('created', models.DateTimeField(auto_now_add=True)),
('modified', models.DateTimeField(auto_now=True)),
('message', models.TextField(max_length=500)),
],
options={
'ordering': ['-created'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='Post',
fields=[
('id', models.AutoField(verbose_name='ID', auto_created=True, primary_key=True, serialize=False)),
('created', models.DateTimeField(auto_now_add=True)),
('modified', models.DateTimeField(auto_now=True)),
('message', models.TextField(max_length=500)),
('privacy', models.CharField(max_length=12, choices=[('public', 'Public'), ('individual', 'Individual')], default='public')),
('posted_by', models.ForeignKey(null=True, related_name='posts', blank=True, to=settings.AUTH_USER_MODEL)),
('recipient', models.ForeignKey(null=True, related_name='recieved_posts', blank=True, to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ['-created'],
'abstract': False,
},
bases=(models.Model,),
),
migrations.AddField(
model_name='comment',
name='parent_post',
field=models.ForeignKey(to='posts.Post'),
preserve_default=True,
),
migrations.AddField(
model_name='comment',
name='posted_by',
field=models.ForeignKey(null=True, related_name='comments', blank=True, to=settings.AUTH_USER_MODEL),
preserve_default=True,
),
]
27 changes: 27 additions & 0 deletions src/posts/migrations/0002_like.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
from django.conf import settings


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('posts', '0001_initial'),
]

operations = [
migrations.CreateModel(
name='Like',
fields=[
('id', models.AutoField(auto_created=True, serialize=False, verbose_name='ID', primary_key=True)),
('liked_by', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
('post', models.ForeignKey(to='posts.Post')),
],
options={
},
bases=(models.Model,),
),
]
File renamed without changes.
49 changes: 49 additions & 0 deletions src/posts/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from django.db import models
from django.conf import settings
from .managers import PostManager


class TimeStampedModel(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)

class Meta:
abstract = True


class Postable(TimeStampedModel):
posted_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True,
null=True, related_name="%(class)ss")
message = models.TextField(max_length=500)

def __str__(self):
return "{}: {:.30}".format(self.posted_by, self.message)

class Meta:
abstract = True
ordering = ["-created"]


class Post(Postable):
POST_PRIVACY = (
('public', 'Public'),
('individual', 'Individual')
)
privacy = models.CharField(max_length=12, choices=POST_PRIVACY,
default='public')
# A recipient is needed if the privacy is set to "Individual"
recipient = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True,
null=True, related_name="recieved_posts")
objects = PostManager()


class Comment(Postable):
parent_post = models.ForeignKey(Post)


class Like(models.Model):
liked_by = models.ForeignKey(settings.AUTH_USER_MODEL)
post = models.ForeignKey(Post)

def __str__(self):
return "{} liked <{}>".format(self.liked_by, self.post)
3 changes: 3 additions & 0 deletions src/posts/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
Loading