Skip to content

Commit 142a788

Browse files
committed
Initial commit - Moving all the project files to a separate repository
0 parents  commit 142a788

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+13025
-0
lines changed

.gitignore

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# bower components
7+
static/bower_components/
8+
9+
# C extensions
10+
*.so
11+
12+
# Distribution / packaging
13+
.Python
14+
build/
15+
develop-eggs/
16+
dist/
17+
downloads/
18+
eggs/
19+
.eggs/
20+
lib/
21+
lib64/
22+
parts/
23+
sdist/
24+
var/
25+
wheels/
26+
share/python-wheels/
27+
*.egg-info/
28+
.installed.cfg
29+
*.egg
30+
MANIFEST
31+
32+
# PyInstaller
33+
# Usually these files are written by a python script from a template
34+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
35+
*.manifest
36+
*.spec
37+
38+
# Installer logs
39+
pip-log.txt
40+
pip-delete-this-directory.txt
41+
42+
# Unit test / coverage reports
43+
htmlcov/
44+
.tox/
45+
.nox/
46+
.coverage
47+
.coverage.*
48+
.cache
49+
nosetests.xml
50+
coverage.xml
51+
*.cover
52+
*.py,cover
53+
.hypothesis/
54+
.pytest_cache/
55+
cover/
56+
57+
# Translations
58+
*.mo
59+
*.pot
60+
61+
# Django stuff:
62+
*.log
63+
local_settings.py
64+
db.sqlite3
65+
db.sqlite3-journal
66+
67+
# Flask stuff:
68+
instance/
69+
.webassets-cache
70+
71+
# Scrapy stuff:
72+
.scrapy
73+
74+
# Sphinx documentation
75+
docs/_build/
76+
77+
# PyBuilder
78+
.pybuilder/
79+
target/
80+
81+
# Jupyter Notebook
82+
.ipynb_checkpoints
83+
84+
# IPython
85+
profile_default/
86+
ipython_config.py
87+
88+
# pyenv
89+
# For a library or package, you might want to ignore these files since the code is
90+
# intended to run in multiple environments; otherwise, check them in:
91+
# .python-version
92+
93+
# pipenv
94+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
95+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
96+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
97+
# install all needed dependencies.
98+
#Pipfile.lock
99+
100+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
101+
__pypackages__/
102+
103+
# Celery stuff
104+
celerybeat-schedule
105+
celerybeat.pid
106+
107+
# SageMath parsed files
108+
*.sage.py
109+
110+
# Environments
111+
.env
112+
.venv
113+
env/
114+
venv/
115+
ENV/
116+
env.bak/
117+
venv.bak/
118+
119+
# Spyder project settings
120+
.spyderproject
121+
.spyproject
122+
123+
# Rope project settings
124+
.ropeproject
125+
126+
# mkdocs documentation
127+
/site
128+
129+
# mypy
130+
.mypy_cache/
131+
.dmypy.json
132+
dmypy.json
133+
134+
# Pyre type checker
135+
.pyre/
136+
137+
# pytype static type analyzer
138+
.pytype/
139+
140+
# Cython debug symbols
141+
cython_debug/

README.md

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Daily Blog
2+
3+
Daily Blog is a simple multi-user blog web application where users can sign in and post blog posts as well as like and comment on other posts made by other users.
4+
5+
This is my project for the [Udacity's Full Stack Web Developer Nanodegree](https://www.udacity.com/course/full-stack-web-developer-nanodegree--nd004) course [Intro to Backend](https://www.udacity.com/course/intro-to-backend--ud171).
6+
7+
Project Name: Multi User Blog.
8+
9+
You can view all of my Nanodegree projects from this repo [mohllal/udacity-fsnd](https://github.com/mohllal/udacity-fsnd).
10+
11+
### Prerequisites:
12+
The application was built on [Google App Engine platform](https://cloud.google.com/appengine/docs/standard/python/download) using [Python 2.7](https://www.python.org/downloads/).
13+
It uses [Google Cloud Datastore](https://cloud.google.com/appengine/docs/standard/python/datastore/) as the underlying database technology.
14+
15+
### Features:
16+
- Login/Signup.
17+
- CRUD Post operations.
18+
- CRUD Comment operations.
19+
- Like\Dislike to other posts.
20+
- Elegant UI.
21+
22+
### Usage:
23+
1. Clone this repository to your desktop, go to the ```p3-daily-blog``` directory and run:
24+
```python
25+
dev_appserver.py .
26+
```
27+
**Note:** Ensure the you have both Python 2.7 and GAE SDK installed.
28+
29+
2. Go to [localhost:8080](http://localhost:8080) to see the application running and [localhost:8000](http://localhost:8000) for the admin console.
30+
31+
### Built With:
32+
- [Bootstrap 3](http://getbootstrap.com/): Bootstrap is the most popular HTML, CSS, and JS framework for developing responsive, mobile first projects on the web.
33+
- [JQuery](https://jquery.com/): jQuery is a fast, small, and feature-rich JavaScript library.
34+
- [Milligram](http://milligram.io/): Milligram is a CSS framework that provides a minimal setup of styles for a fast and clean starting point.
35+
- [Jinja2](http://jinja.pocoo.org/docs/2.9/): Jinja2 is a modern and designer-friendly templating language for Python, modelled after Django’s templates.
36+
- [webapp2](https://webapp2.readthedocs.io/en/latest/): webapp2 is a lightweight Python web framework compatible with Google App Engine’s webapp.
37+
38+
### License:
39+
This software is licensed under the [Modified BSD License](https://opensource.org/licenses/BSD-3-Clause).

app.yaml

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
runtime: python27
2+
api_version: 1
3+
threadsafe: yes
4+
5+
handlers:
6+
- url: /favicon\.ico
7+
static_files: favicon.ico
8+
upload: favicon\.ico
9+
10+
- url: /static
11+
static_dir: static
12+
13+
- url: .*
14+
script: main.app
15+
16+
libraries:
17+
- name: webapp2
18+
version: "2.5.2"
19+
- name: jinja2
20+
version: latest

handlers/__init__.py

Whitespace-only changes.

handlers/deletecomment.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from google.appengine.ext import db
2+
from handlers.handler import Handler
3+
from utilities import Utils
4+
5+
6+
class DeleteCommentHandler(Handler):
7+
"""
8+
This class represents request handler for comment delete action.
9+
It checks if the requested comment id is valid and
10+
if the logged in user the permission to do this.
11+
"""
12+
def get(self, post_id, comment_id):
13+
# Check if the user is currently logged in
14+
if not self.user:
15+
return self.redirect('/login')
16+
17+
postKey = db.Key.from_path('Post', int(post_id), parent=Utils.blog_key())
18+
post = db.get(postKey)
19+
20+
commentKey = db.Key.from_path('Comment', int(comment_id), parent=postKey)
21+
comment = db.get(commentKey)
22+
23+
# Check if the comment id is valid and
24+
# if the logged in user has the permission to edit it
25+
if not comment or \
26+
not comment.user.key().id() == self.user.key().id():
27+
self.error(404)
28+
return
29+
30+
post.comments -= 1
31+
32+
comment.delete()
33+
post.put()
34+
35+
self.redirect('/blog/' + str(post_id))

handlers/deletepost.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from google.appengine.ext import db
2+
from handlers.handler import Handler
3+
from utilities import Utils
4+
5+
6+
class DeletePostHandler(Handler):
7+
"""
8+
This class represents request handler for post delete action.
9+
It checks if the requested post id is valid and
10+
if the logged in user has this permission.
11+
"""
12+
def get(self, post_id):
13+
key = db.Key.from_path('Post', int(post_id), parent=Utils.blog_key())
14+
post = db.get(key)
15+
16+
# Check if the user is currently logged in
17+
if not self.user:
18+
return self.redirect('/login')
19+
20+
# Check if the post id is valid or
21+
# the logged in user has this permission
22+
if not post or \
23+
not post.user.key().id() == self.user.key().id():
24+
self.error(404)
25+
return
26+
27+
post.delete()
28+
self.redirect('/')

handlers/editcomment.py

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from google.appengine.ext import db
2+
from handlers.handler import Handler
3+
from utilities import Utils
4+
5+
6+
class EditCommentHandler(Handler):
7+
"""
8+
This class represents request handler for comment edit action.
9+
It checks if the requested comment id is valid and
10+
if the logged in user has this permission.
11+
It handles one post request to edit comment (content).
12+
"""
13+
def get(self, post_id, comment_id):
14+
# Check if the user is currently logged in
15+
if not self.user:
16+
return self.redirect("/login")
17+
18+
postKey = db.Key.from_path('Post', int(post_id), parent=Utils.blog_key())
19+
20+
commentKey = db.Key.from_path('Comment', int(comment_id), parent=postKey)
21+
comment = db.get(commentKey)
22+
23+
# Check if the comment id is valid and if
24+
# the logged in user has the permission to edit it
25+
if not comment or \
26+
not comment.user.key().id() == self.user.key().id():
27+
self.error(404)
28+
return
29+
30+
self.render("comment-form.html",
31+
content=comment.content, post_id=post_id)
32+
33+
def post(self, post_id, comment_id):
34+
# Check if the user is currently logged in
35+
if not self.user:
36+
return self.redirect('/login')
37+
38+
postKey = db.Key.from_path('Post', int(post_id), parent=Utils.blog_key())
39+
40+
commentKey = db.Key.from_path('Comment', int(comment_id), parent=postKey)
41+
comment = db.get(commentKey)
42+
43+
# Check if the comment id is valid and if
44+
# the logged in user has the permission to edit it
45+
if not comment or \
46+
not comment.user.key().id() == self.user.key().id():
47+
self.error(404)
48+
return
49+
50+
# Get form input value (content)
51+
content = self.request.get('content')
52+
53+
if content:
54+
comment.content = content
55+
comment.put()
56+
return self.redirect('/blog/' + str(post_id))
57+
else:
58+
error = "Content must be provided!"
59+
self.render("comment-form.html",
60+
content=content, error=error, post_id=post_id)

handlers/editpost.py

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from google.appengine.ext import db
2+
from handlers.handler import Handler
3+
from utilities import Utils
4+
5+
6+
class EditPostHandler(Handler):
7+
"""
8+
This class represents request handler for post edit action.
9+
It checks if the requested post id is valid and if
10+
the logged in user has this permission.
11+
It handles one post request to edit post (subject and content).
12+
"""
13+
def get(self, post_id):
14+
key = db.Key.from_path('Post', int(post_id), parent=Utils.blog_key())
15+
post = db.get(key)
16+
17+
# Check if the user is currently logged in
18+
if not self.user:
19+
return self.redirect('/login')
20+
21+
# Check if the post id is valid and if
22+
# the logged in user has the permission to edit it
23+
if not post or \
24+
not post.user.key().id() == self.user.key().id():
25+
self.error(404)
26+
return
27+
28+
self.render("post-form.html", subject=post.subject,
29+
content=post.content)
30+
31+
def post(self, post_id):
32+
key = db.Key.from_path('Post', int(post_id), parent=Utils.blog_key())
33+
post = db.get(key)
34+
35+
# Check if the user is currently logged in
36+
if not self.user:
37+
return self.redirect('/')
38+
39+
# Check if the post id is valid
40+
# or the logged in user has this permission
41+
if not post or not post.user.key().id() == self.user.key().id():
42+
self.error(404)
43+
return
44+
45+
# Get form input values (subject and content)
46+
subject = self.request.get('subject')
47+
content = self.request.get('content')
48+
49+
if subject and content:
50+
post.subject = subject
51+
post.content = content
52+
post.put()
53+
return self.redirect('/blog/' + str(post_id))
54+
else:
55+
error = "Subject and content must be provided!"
56+
self.render("post-form.html", subject=subject,
57+
content=content, error=error)

0 commit comments

Comments
 (0)