· 9 years ago · Nov 05, 2016, 10:20 AM
1# THIS PROJECT IS AN EXAMPLE APP. SOME CODE MAY NOT BE ACTUALLY USEFUL
2# FOR DEMONSTRATION PURPOSES ONLY
3# YOUR MILEAGE MAY VARY
4# Requirements are Flask, Flask-WTF, Flask-SQLAlchemy
5
6import os
7
8from flask import (Flask,
9 Blueprint,
10 redirect,
11 render_template_string,
12 request,
13 url_for)
14
15from flask_sqlalchemy import SQLAlchemy
16from flask_wtf import FlaskForm
17from sqlalchemy import func
18from wtforms import StringField, SubmitField, TextField
19from wtforms.validators import Required
20
21BASE_PATH = os.path.abspath(os.path.dirname(__file__))
22
23settings = {
24 'SECRET_KEY': 'super not secure development key',
25 'DEBUG': True,
26 'SQLALCHEMY_TRACK_MODIFICATIONS': False,
27 'SQLALCHEMY_DATABASE_URI': 'sqlite:///' + os.path.join(BASE_PATH,
28 'posts.db'),
29 'SQLALCHEMY_ECHO': True
30}
31
32app = Flask(__name__)
33db = SQLAlchemy(app)
34
35app.config.update(settings)
36
37blog = Blueprint('blog', __name__)
38
39
40
41# These are template files which are basically html with jinja tags.
42# Jinja is a template language that can parse text and execute python code
43# the results are returned as html text with the proper values.
44
45# The index template string for the main page
46index_template = '''
47{% if posts %}
48 <table class="posts-table">
49 <thead>
50 <tr>
51 <th>ID</th>
52 <th>title</th>
53 <th>likes</th>
54 <th>like?</th>
55 </tr>
56 </thead>
57 <tbody>
58 {% for post in posts %}
59 <tr>
60 <td>{{ post.id }}</td>
61 <td>{{ post.title }}</td>
62 <td{% if post.likes | length > 3 %} style="color:green;"{% endif %}>{{ post.likes | length }}</td>
63 <td><a href="{{ url_for('blog.like_post', post_id=post.id) }}">like it!</a>
64 </tr>
65 {% endfor %}
66 </tbody>
67 </table>
68{% else %}
69<p> You don't have any posts </p>
70{% endif %}
71<a href = "{{ url_for('blog.create_post') }}">Create Post</a>
72'''
73
74# The template string for creating a blog post
75create_post_template = '''
76<form action="{{ url_for('blog.create_post') }}" method="POST" name="post_form">
77 {{ form.csrf_token }}
78 {{ form.title.label }}
79 {{ form.title }}
80 {{ form.text.label }}
81 {{ form.text }}
82 {{ form.submit() }}
83</form>
84'''
85
86error_template = '''
87<div id="error">
88 <h1> Sorry, there was an error</h1>
89 <p>Error:# {{ status_code }}</p>
90</div>
91'''
92
93# Create the form
94class CreatePostForm(FlaskForm):
95 """
96 The form used to create a blog post
97 """
98 title = StringField('Title', validators=[Required()])
99 text = TextField('Text', validators=[Required()])
100 submit = SubmitField('Submit')
101
102
103# Create the Models
104class Post(db.Model):
105 __tablename__ = 'posts'
106
107 id = db.Column(db.Integer(), primary_key=True)
108 title = db.Column(db.String(100))
109 text = db.Column(db.Text())
110
111 likes = db.relationship('PostLike')
112
113 @classmethod
114 def all(cls):
115 """
116 Returns all researcher items from the database
117 """
118 return db.session.query(cls).all()
119
120
121class PostLike(db.Model):
122 __tablename__ = 'post_likes'
123
124 id = db.Column(db.Integer(), primary_key=True)
125 post_id = db.Column(db.Integer(), db.ForeignKey('posts.id'))
126 user_id = db.Column(db.Integer(), db.ForeignKey('users.id'))
127
128 users = db.relationship('User')
129
130
131class User(db.Model):
132 __tablename__ = 'users'
133 id = db.Column(db.Integer(), primary_key=True)
134 name = db.Column(db.String(100))
135
136 def __repr__(self):
137 return self.name
138
139 @classmethod
140 def get_random(cls):
141 user = db.session.query(cls).order_by(func.random()).first()
142 return user.id
143
144
145# Register errorhandlers
146@app.errorhandler(404)
147def page_not_found(e):
148 return render_template_string(error_template, status_code=404), 404
149
150
151@app.errorhandler(500)
152def server_error(e):
153 return render_template_string(error_template, status_code=500), 500
154
155
156# Create the routes
157@blog.route('/', methods=['GET'])
158def index():
159 posts = Post.all()
160 return render_template_string(index_template, posts=posts)
161
162
163@blog.route('/create', methods=['GET', 'POST'])
164def create_post():
165 form = CreatePostForm(request.form)
166 if form.validate_on_submit():
167 post = Post(title=form.title.data,
168 text=form.text.data)
169 db.session.add(post)
170 db.session.commit()
171 return redirect(url_for('blog.index'))
172 return render_template_string(create_post_template, form=form)
173
174
175@blog.route('/like/<int:post_id>')
176def like_post(post_id):
177 post = db.session.query(Post).get(post_id)
178 user = db.session.query(User).get(1)
179 post_like = db.session.query(PostLike) \
180 .filter(PostLike.user_id == user.id) \
181 .first()
182 if post_like:
183 # A post was found with that user so redirect back.
184 # We would typically flash a message giving an error.
185 return redirect(url_for('index'))
186 else:
187
188 post_like = PostLike(post_id=post.id,
189 user_id=User.get_random())
190 db.session.add(post_like)
191 db.session.commit()
192 return redirect(url_for('blog.index'))
193
194app.register_blueprint(blog)
195
196# Utils
197def create_and_seed_db():
198 db.create_all()
199
200 for x in range(10):
201 user = User(name='user' + str(x))
202 db.session.add(user)
203 db.session.commit()
204
205 return
206
207
208if __name__ == '__main__':
209 # This will create the database if it doesn't already exist.
210 if os.path.exists(app.config['SQLALCHEMY_DATABASE_URI'].split('///')[1]):
211 app.run()
212 else:
213 create_and_seed_db()
214 app.run()