· 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
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}
30
31app = Flask(__name__)
32db = SQLAlchemy(app)
33
34app.config.update(settings)
35
36blog = Blueprint('blog', __name__)
37
38
39
40# These are template files which are basically html with jinja tags.
41# Jinja is a template language that can parse text and execute python code
42# the results are returned as html text with the proper values.
43
44# The index template string for the main page
45index_template = '''
46{% if posts|length > 0 %}
47
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>{{ 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
84</form>
85'''
86
87error_template = '''
88<div id="error">
89 <h1> Sorry, there was an error</h1>
90 <p>Error:# {{ status_code }}</p>
91</div>
92'''
93
94# Create the form
95class CreatePostForm(FlaskForm):
96 """
97 The form used to create a blog post
98 """
99 title = StringField('Title', validators=[Required()])
100 text = TextField('Text', validators=[Required()])
101 submit = SubmitField('Submit')
102
103
104# Create the Models
105class Post(db.Model):
106 __tablename__ = 'posts'
107
108 id = db.Column(db.Integer(), primary_key=True)
109 title = db.Column(db.String(100))
110 text = db.Column(db.Text())
111
112 likes = db.relationship('PostLike')
113
114 @classmethod
115 def all(cls):
116 """
117 Returns all researcher items from the database
118 """
119 return db.session.query(cls).all()
120
121
122class PostLike(db.Model):
123 __tablename__ = 'post_likes'
124
125 id = db.Column(db.Integer(), primary_key=True)
126 post_id = db.Column(db.Integer(), db.ForeignKey('posts.id'))
127 user_id = db.Column(db.Integer(), db.ForeignKey('users.id'))
128
129 users = db.relationship('User')
130
131
132class User(db.Model):
133 __tablename__ = 'users'
134 id = db.Column(db.Integer(), primary_key=True)
135 name = db.Column(db.String(100))
136
137 def __repr__(self):
138 return self.name
139
140 @classmethod
141 def get_random(cls):
142 user = db.session.query(cls).order_by(func.random()).first()
143 return user.id
144
145
146# Register errorhandlers
147@app.errorhandler(404)
148def page_not_found(e):
149 return render_template_string(error_template, status_code=404), 404
150
151
152@app.errorhandler(500)
153def server_error(e):
154 return render_template_string(error_template, status_code=500), 500
155
156
157# Create the routes
158@blog.route('/', methods=['GET'])
159def index():
160 posts = Post.all()
161 return render_template_string(index_template, posts=posts)
162
163
164@blog.route('/create', methods=['GET', 'POST'])
165def create_post():
166 form = CreatePostForm(request.form)
167 if form.validate_on_submit():
168 post = Post(title=form.title.data,
169 text=form.text.data)
170 db.session.add(post)
171 db.session.commit()
172 return redirect(url_for('blog.index'))
173 return render_template_string(create_post_template, form=form)
174
175
176@blog.route('/like/<int:post_id>')
177def like_post(post_id):
178 post = db.session.query(Post).get(post_id)
179 user = db.session.query(User).get(1)
180 post_like = db.session.query(PostLike) \
181 .filter(PostLike.user_id == user.id) \
182 .first()
183 if post_like:
184 # A post was found with that user so redirect back.
185 # We would typically flash a message giving an error.
186 return redirect(url_for('index'))
187 else:
188
189 post_like = PostLike(post_id=post.id,
190 user_id=User.get_random())
191 db.session.add(post_like)
192 db.session.commit()
193 return redirect(url_for('blog.index'))
194
195app.register_blueprint(blog)
196
197# Utils
198def create_and_seed_db():
199 db.create_all()
200
201 for x in range(10):
202 user = User(name='user' + str(x))
203 db.session.add(user)
204 db.session.commit()
205
206 return
207
208
209if __name__ == '__main__':
210 # This will create the database if it doesn't already exist.
211 if os.path.exists(app.config['SQLALCHEMY_DATABASE_URI'].split('///')[1]):
212 app.run()
213 else:
214 create_and_seed_db()
215 app.run()