Basics to view threads
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/venv
|
||||||
|
__pycache__
|
||||||
|
*.db
|
||||||
14
Makefile
Normal file
14
Makefile
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
PYTHON = python3
|
||||||
|
FLASK = flask
|
||||||
|
SQLITE = sqlite3
|
||||||
|
|
||||||
|
default: test
|
||||||
|
|
||||||
|
test::
|
||||||
|
test/all.sh
|
||||||
|
|
||||||
|
venv:
|
||||||
|
$(PYTHON) -m venv $@
|
||||||
|
|
||||||
|
forum.db:
|
||||||
|
$(SQLITE) $@ < schema.txt
|
||||||
53
db/sqlite.py
Normal file
53
db/sqlite.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import sqlite3
|
||||||
|
|
||||||
|
class DB:
|
||||||
|
def __init__(self, conn):
|
||||||
|
self.conn = conn
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_subforums(self):
|
||||||
|
return self._db().execute('select forum_id, name, description from subforums').fetchall()
|
||||||
|
|
||||||
|
def get_subforum(self, subforum):
|
||||||
|
return self._db().execute('select name, description from subforums where forum_id = ?', (subforum,)).fetchone()
|
||||||
|
|
||||||
|
def get_threads(self, subforum):
|
||||||
|
return self._db().execute('select thread_id, title from threads where forum_id = ?', (subforum,)).fetchall()
|
||||||
|
|
||||||
|
def get_thread(self, thread):
|
||||||
|
db = self._db()
|
||||||
|
title, text, author = db.execute('''
|
||||||
|
select title, text, name
|
||||||
|
from threads, users
|
||||||
|
where thread_id = ? and author_id = user_id
|
||||||
|
''',
|
||||||
|
(thread,)
|
||||||
|
).fetchone()
|
||||||
|
comments = db.execute('''
|
||||||
|
select comment_id, parent_id, name, text
|
||||||
|
from comments, users
|
||||||
|
where thread_id = ? and author_id = user_id
|
||||||
|
''',
|
||||||
|
(thread,)
|
||||||
|
).fetchall()
|
||||||
|
return title, text, author, comments
|
||||||
|
|
||||||
|
def get_comments(self, thread):
|
||||||
|
return self._db().execute('''
|
||||||
|
select text
|
||||||
|
from comments
|
||||||
|
where thread_id = ?
|
||||||
|
''',
|
||||||
|
(thread,)
|
||||||
|
).fetchall()
|
||||||
|
|
||||||
|
def get_comment_tree(self, comment):
|
||||||
|
db = self._db()
|
||||||
|
parent = db.execute('select text from comments where comment_id = ?', (comment,)).fetchall()
|
||||||
|
children = db.execute('select text from comments where parent_id = ?', (comment,)).fetchall()
|
||||||
|
print(parent, children)
|
||||||
|
return str(parent) + str(children)
|
||||||
|
return parent
|
||||||
|
|
||||||
|
def _db(self):
|
||||||
|
return sqlite3.connect(self.conn)
|
||||||
48
main.py
Normal file
48
main.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
from flask import Flask, render_template
|
||||||
|
from db.sqlite import DB
|
||||||
|
import os
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
db = DB(os.getenv('DB'))
|
||||||
|
NAME = 'Agrepy'
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def index():
|
||||||
|
return render_template('index.html', title = NAME, subforums = db.get_subforums())
|
||||||
|
|
||||||
|
@app.route('/forum/<forum_id>/')
|
||||||
|
def subforum(forum_id):
|
||||||
|
title, description = db.get_subforum(forum_id)
|
||||||
|
threads = db.get_threads(forum_id)
|
||||||
|
return render_template('subforum.html', title = title, description = description, threads = threads)
|
||||||
|
|
||||||
|
@app.route('/thread/<thread_id>/')
|
||||||
|
def thread(thread_id):
|
||||||
|
title, text, author, comments = db.get_thread(thread_id)
|
||||||
|
comments = create_comment_tree(comments)
|
||||||
|
return render_template('thread.html', title = title, text = text, author = author, comments = comments)
|
||||||
|
|
||||||
|
@app.route('/comment/<comment_id>/')
|
||||||
|
def comment(comment_id):
|
||||||
|
#return str(db.get_comment_tree(comment_id)[0])
|
||||||
|
return str(db.get_comment_tree(comment_id))
|
||||||
|
|
||||||
|
|
||||||
|
class Comment:
|
||||||
|
def __init__(self, author, text):
|
||||||
|
self.author = author
|
||||||
|
self.text = text
|
||||||
|
self.children = []
|
||||||
|
|
||||||
|
def create_comment_tree(comments):
|
||||||
|
root = []
|
||||||
|
comment_map = {}
|
||||||
|
for comment_id, parent_id, author, text in comments:
|
||||||
|
comment = Comment(author, text)
|
||||||
|
parent = comment_map.get(parent_id)
|
||||||
|
if parent is not None:
|
||||||
|
parent.children.append(comment)
|
||||||
|
else:
|
||||||
|
root.append(comment)
|
||||||
|
comment_map[comment_id] = comment
|
||||||
|
return root
|
||||||
41
schema.txt
Normal file
41
schema.txt
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
create table users (
|
||||||
|
user_id integer unique not null primary key autoincrement,
|
||||||
|
name varchar(32) unique not null,
|
||||||
|
password varchar(128) not null,
|
||||||
|
email varchar(254),
|
||||||
|
about text,
|
||||||
|
join_date integer,
|
||||||
|
role integer not null default 0
|
||||||
|
);
|
||||||
|
|
||||||
|
create table threads (
|
||||||
|
thread_id integer unique not null primary key autoincrement,
|
||||||
|
author_id integer not null,
|
||||||
|
forum_id integer not null,
|
||||||
|
create_date integer not null,
|
||||||
|
modify_date integer not null,
|
||||||
|
update_date integer not null,
|
||||||
|
title varchar(64) not null,
|
||||||
|
text text not null,
|
||||||
|
score integer not null default 0,
|
||||||
|
dead boolean not null default false
|
||||||
|
);
|
||||||
|
|
||||||
|
create table comments (
|
||||||
|
comment_id integer unique not null primary key autoincrement,
|
||||||
|
thread_id integer not null,
|
||||||
|
author_id integer not null,
|
||||||
|
parent_id integer,
|
||||||
|
create_date integer not null,
|
||||||
|
modify_date integer not null,
|
||||||
|
text text not null,
|
||||||
|
score integer not null default 0,
|
||||||
|
dead boolean not null default false
|
||||||
|
);
|
||||||
|
|
||||||
|
create table subforums (
|
||||||
|
forum_id integer unique not null primary key autoincrement,
|
||||||
|
name varchar(64) not null,
|
||||||
|
description text,
|
||||||
|
allowed_roles_mask integer not null
|
||||||
|
);
|
||||||
13
templates/base.html
Normal file
13
templates/base.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<head>
|
||||||
|
<title>{{ title }}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav>
|
||||||
|
<a href="{{ url_for('index') }}">Home</a>
|
||||||
|
</nav>
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
<main>
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
9
templates/index.html
Normal file
9
templates/index.html
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<ul>
|
||||||
|
{% for id, name, description in subforums %}
|
||||||
|
<li><a href="{{ url_for('subforum', forum_id = id) }}">{{ name }} - {{ description }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
10
templates/subforum.html
Normal file
10
templates/subforum.html
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<p>{{ description }}</p>
|
||||||
|
<ul>
|
||||||
|
{% for id, title in threads %}
|
||||||
|
<li><a href="{{ url_for('thread', thread_id = id) }}">{{ title }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
19
templates/thread.html
Normal file
19
templates/thread.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% macro render_comment(comment) %}
|
||||||
|
<div style="margin-left:20px">
|
||||||
|
<p><i>{{ comment.author }}</i></p>
|
||||||
|
<p>{{ comment.text }}</p>
|
||||||
|
{% for c in comment.children %}
|
||||||
|
{{ render_comment(c) }}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<p>{{ author }} - rjgoire</p>
|
||||||
|
<p>{{ text }}</p>
|
||||||
|
{% for c in comments %}
|
||||||
|
{{ render_comment(c) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
||||||
22
test/all.sh
Executable file
22
test/all.sh
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
SQLITE=sqlite3
|
||||||
|
FLASK=flask
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
|
tmp=$(mktemp -d)
|
||||||
|
trap 'rm -rf $tmp' EXIT
|
||||||
|
base=$(dirname "$0")
|
||||||
|
|
||||||
|
db=$tmp/forum.db
|
||||||
|
|
||||||
|
. $base/../venv/bin/activate
|
||||||
|
|
||||||
|
# initialize db
|
||||||
|
$SQLITE $db < $base/../schema.txt
|
||||||
|
$SQLITE $db < $base/init_db.txt
|
||||||
|
cd $base/..
|
||||||
|
|
||||||
|
DB=$db $FLASK --app main --debug run
|
||||||
15
test/init_db.txt
Normal file
15
test/init_db.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
insert into users (name, password, email) values ("Foo", "supasecret", "foo@bar.baz");
|
||||||
|
insert into users (name, password, email) values ("Bar", "rgjieogir", "bar@foo.baz");
|
||||||
|
insert into users (name, password) values ("bazzers", "reogke");
|
||||||
|
|
||||||
|
insert into subforums (name, description, allowed_roles_mask)
|
||||||
|
values ("Earth", "The totality of all space and time; all that is, has been, and will be.", 1);
|
||||||
|
|
||||||
|
insert into threads (author_id, forum_id, create_date, modify_date, update_date, title, text)
|
||||||
|
values (1, 1, 0, 0, 0, "Hello, world!",
|
||||||
|
'In its most general sense, the term "world" refers to the totality of entities, to the whole of reality or to everything that is.');
|
||||||
|
|
||||||
|
insert into comments (author_id, thread_id, create_date, modify_date, text)
|
||||||
|
values (2, 1, 0, 0, "Hi!");
|
||||||
|
insert into comments (author_id, thread_id, create_date, modify_date, text, parent_id)
|
||||||
|
values (3, 1, 0, 0, "Greetings.", 1);
|
||||||
Reference in New Issue
Block a user