Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
35 changes: 35 additions & 0 deletions PersonalBlog-Flask/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# flask-blog
A simple blog web project, use python-flask.

## run
### install dep and env
>(install at global or virtualenv)
```
pip install -r ./requirements.txt
```
### create db
```
python ./db_migrate.py
```

### run
`server: `
```
python ./run.py
```
> default: Running on http://127.0.0.1:5000/

`browser:`
```
http://127.0.0.1:5000/
```

## feature
- sign in
- login
- logout
- avatar
- micro-blog
- follow/unfollow user
- user profile

16 changes: 16 additions & 0 deletions PersonalBlog-Flask/app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from config import basedir

app = Flask(__name__)
app.config.from_object('config')

db = SQLAlchemy(app)

lm = LoginManager()
lm.init_app(app)
lm.login_view = 'login'

from app import views, models #视图/模型模块
33 changes: 33 additions & 0 deletions PersonalBlog-Flask/app/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from flask_wtf import Form
from wtforms import StringField, BooleanField, TextAreaField
from wtforms.validators import DataRequired, Length
from app.models import User

class LoginForm(Form):
# openid = StringField('openid', validators=[DataRequired()])
nickname = StringField('nickname', validators=[DataRequired()])
password = StringField('password', validators=[DataRequired()])
email = StringField('email')
remember_me = BooleanField('remember_me', default=False)

class EditForm(Form):
nickname = StringField('nicknamae', validators=[DataRequired()])
about_me = TextAreaField('about_me', validators=[Length(min=0, max=140)])

def __init__(self, original_nickname, *args, **kwargs):
Form.__init__(self, *args, **kwargs)
self.original_nickname = original_nickname

def validate(self):
if not Form.validate(self):
return false
if self.nickname.data == self.original_nickname:
return True
user = User.query.filter_by(nickname = self.nickname.data).first()
if user != None:
self.nickname.errors.append('This Name is already used! Please choose another one!')
return False
return True

class PostForm(Form):
post = StringField('post', validators=[DataRequired()])
77 changes: 77 additions & 0 deletions PersonalBlog-Flask/app/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from app import db
from hashlib import md5

followers = db.Table('followers',
db.Column('follower_id', db.Integer, db.ForeignKey('user.id')),
db.Column('followed_id', db.Integer, db.ForeignKey('user.id'))
)

class User(db.Model):
id = db.Column(db.Integer, primary_key = True)
nickname = db.Column(db.String(64), index=True, unique = True)
password = db.Column(db.String(120), index=True)
email = db.Column(db.String(120), index = True)
about_me = db.Column(db.String(140))
last_seen = db.Column(db.DateTime)

posts = db.relationship('Post', backref='author', lazy='dynamic')
followed = db.relationship('User',
secondary = followers,
primaryjoin = (followers.c.follower_id == id),
secondaryjoin = (followers.c.followed_id == id),
backref = db.backref('followers',lazy='dynamic'),
lazy = 'dynamic')

is_authenticated = True
is_active = True
is_anonymous = False

def get_id(self):
try:
return unicode(self.id)
except NameError:
return str(self.id)

def avatar(self, size):
return 'http://www.gravatar.com/avatar/' + md5(self.email.encode("utf-8")).hexdigest() + '?d=mm&s=' + str(size)

# be used to debug
def __repr__(self):
return '<User %r>' % (self.nickname)

@staticmethod
def make_unique_nickname(nickname):
if User.query.filter_by(nickname = nickname).first() == None:
return nickname
version = 2
while True:
new_nickname = nickname + str(version)
if User.query.filter_by(nickname = new_nickname).first() == None:
break
version += 1
return new_nickname

def follow(self, user):
if not self.is_following(user):
self.followed.append(user)
return self
def unfollow(self, user):
if self.is_following(user):
self.followed.remove(user)
return self
def is_following(self, user):
return self.followed.filter(followers.c.followed_id == user.id).count() > 0

def followed_posts(self):
return Post.query.join(followers,
(followers.c.followed_id == Post.user_id)).filter(followers.c.follower_id == self.id).order_by(Post.timestamp.desc())


class Post(db.Model):
id = db.Column(db.Integer, primary_key = True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

def __repr__(self):
return '<Post %r>' % (self.body)
6 changes: 6 additions & 0 deletions PersonalBlog-Flask/app/templates/404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{% extends 'base.html' %}

{% block content %}
<h1>File Not Found!</h1>
<p> <a href="{{ url_for('index') }}">Back to Index .</a></p>
{% endblock %}
6 changes: 6 additions & 0 deletions PersonalBlog-Flask/app/templates/500.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{% extends 'base.html' %}

{% block content %}
<h1>An unexpected error has occurred!</h1>
<p> <a href="{{ url_for('index') }}">Back to Index .</a></p>
{% endblock %}
31 changes: 31 additions & 0 deletions PersonalBlog-Flask/app/templates/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<html>
<head>
{%if title %}
<title>{{title}} - microblog</title>
{%else%}
<title>microblog</title>
{%endif%}
</head>
<body>
<div>MicroBlog:
<a href="{{ url_for('index') }}">Home</a>
{% if g.user.is_authenticated %}
| <a href="{{ url_for('logout') }}">Log out</a>
| <a href="{{ url_for('user', nickname = g.user.nickname ) }}">My Profile</a>
{% else %}
<a href="{{ url_for('sign_in') }}">Sign In</a>
{% endif %}
</div>
<hr>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message}}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block content %} {% endblock %}
</body>
</html>
27 changes: 27 additions & 0 deletions PersonalBlog-Flask/app/templates/edit.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{% extends "base.html" %}

{% block content %}
<h1>Edit Your Profile</h1>
<form action="" method="post" name="edit">
{{ form.hidden_tag() }}
<table>
<tr>
<td>Your nickname:</td>
<td>
{{ form.nickname(size=24) }}
{% for error in form.errors.nickname %}
<br><span style="color:red;">[ {{ error }}]</span>
{% endfor %}
</td>
</tr>
<tr>
<td>About yourself:</td>
<td>{{ form.about_me(cols=32, rows=4) }}</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Save Changes"></td>
</tr>
</table>
</form>
{% endblock %}
42 changes: 42 additions & 0 deletions PersonalBlog-Flask/app/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

{% extends "base.html" %}
{%block content %}
<h1>Hello, {{g.user.nickname}}!</h1>

<form action="" method="post" name="post">
{{ form.hidden_tag() }}
<table>
<tr>
<td>Say something: </td>
<td>{{ form.post(size = 30, maxlength=140) }}</td>
<td>
{% for error in form.errors.post %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Post!"></td>
<td></td>
</tr>
</table>
</form>

<hr>
{% for post in posts.items %}
{% include 'post.html' %}
<hr>
{% endfor%}

{% if posts.has_prev %}
<a href="{{ url_for('index', page=posts.prev_num) }}"> 上一页 </a>
{% else %}
上一页
{% endif %} |
{% if posts.has_next %}
<a href="{{ url_for('index', page=posts.next_num) }}"> 下一页 </a>
{% else %}
下一页
{% endif %}
{% endblock %}
18 changes: 18 additions & 0 deletions PersonalBlog-Flask/app/templates/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{% extends "base.html" %}

{% block content %}

<h1>Login</h1>
<form action="" method="POST" name="login">
{{form.hidden_tag()}}
<p>
Please enter your name and password! <br>
UserName: {{ form.nickname(size=80) }} <br>
Password: {{ form.password(size=120) }} <br>
Email: {{ form.email(size=120) }} <br>
</p>

<p>{{form.remember_me}} Remember Me</p>
<p><input type="submit" value="Login"></p>
</form>
{% endblock %}
6 changes: 6 additions & 0 deletions PersonalBlog-Flask/app/templates/post.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<table>
<tr valign="top">
<td><img src="{{ post.author.avatar(50) }}"></td>
<td><i>{{ post.author.nickname }} says:</i> <br> {{ post.body }}</td>
</tr>
</table>
18 changes: 18 additions & 0 deletions PersonalBlog-Flask/app/templates/sign_in.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{% extends "base.html" %}

{% block content %}

<h1>Sign In</h1>
<form action="" method="POST" name="sign_in">
{{form.hidden_tag()}}
<p>
Please enter your name and password! <br>
UserName: {{ form.nickname(size=80) }} <br>
Password: {{ form.password(size=120) }} <br>
Email: {{ form.email(size=120) }} <br>
</p>

<p>{{form.remember_me}} Remember Me</p>
<p><input type="submit" value="Sign In"></p>
</form>
{% endblock %}
42 changes: 42 additions & 0 deletions PersonalBlog-Flask/app/templates/user.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{% extends "base.html" %}
{% block content %}
<table>
<tr valign="top">
<td><img src="{{ user.avatar(128) }}"> </td>
<td>
<h1>User: {{user.nickname}} </h1>
{% if user.email %} <p>{{ user.email }}</p> {% endif %}
{% if user.about_me %} <p>{{ user.about_me }}</p> {% endif %}
{% if user.last_seen %} <p><i>Last Seen on: {{ user.last_seen }}</i></p> {% endif %}
<p>
{{ user.followers.count() }} followers |
{% if user.id == g.user.id %}
<a href="{{url_for('edit')}}">Edit AboutMe</a>
{% elif not g.user.is_following(user) %}
<a href="{{ url_for('follow', nickname = user.nickname) }}">Follow</a>
{% else %}
<a href="{{ url_for('unfollow', nickname = user.nickname) }}">UnFollow</a>
{% endif %}
</p>
</td>
</tr>
</table>

<hr>
{% for post in posts.items %}
{% include 'post.html' %}
<hr>
{% endfor %}

{% if posts.has_prev %}
<a href="{{ url_for('index', page=posts.prev_num) }}"> 上一页 </a>
{% else %}
上一页
{% endif %} |
{% if posts.has_next %}
<a href="{{ url_for('index', page=posts.next_num) }}"> 下一页 </a>
{% else %}
下一页
{% endif %}

{% endblock %}
Loading