Add all the code
parent
105934eccb
commit
2e2ea9a72c
|
@ -0,0 +1,3 @@
|
|||
from libertywiki.app import get_app
|
||||
|
||||
__all__ = ['get_app']
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
from libertywiki import get_app
|
||||
|
||||
if __name__ == "__main__":
|
||||
get_app().run(port=8080, debug=True)
|
|
@ -0,0 +1,26 @@
|
|||
from flask import Flask
|
||||
|
||||
from rst2html import rst2html
|
||||
|
||||
from libertywiki.db import db
|
||||
from libertywiki.views import wiki
|
||||
|
||||
|
||||
def get_app():
|
||||
"""Create and configure the application object"""
|
||||
app = Flask(__name__)
|
||||
db.init_app(app)
|
||||
|
||||
with app.app_context():
|
||||
db.create_all()
|
||||
|
||||
@app.template_filter('rst2html')
|
||||
def rst2html_filter(text):
|
||||
html, warning = rst2html(text)
|
||||
print(html)
|
||||
print(warning)
|
||||
return html
|
||||
|
||||
app.register_blueprint(wiki)
|
||||
|
||||
return app
|
|
@ -0,0 +1,17 @@
|
|||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
db = SQLAlchemy()
|
||||
Model = db.Model
|
||||
Boolean = db.Boolean
|
||||
Column = db.Column
|
||||
DateTime = db.DateTime
|
||||
Float = db.Float
|
||||
ForeignKey = db.ForeignKey
|
||||
Integer = db.Integer
|
||||
LargeBinary = db.LargeBinary
|
||||
Table = db.Table
|
||||
String = db.String
|
||||
Text = db.Text
|
||||
relationship = db.relationship
|
||||
inspect = db.inspect
|
||||
session = db.session
|
|
@ -0,0 +1,45 @@
|
|||
from datetime import datetime
|
||||
|
||||
from sqlalchemy.ext.hybrid import hybrid_property
|
||||
|
||||
from libertywiki.db import Model, Column, ForeignKey, DateTime, Integer, String, Text
|
||||
from libertywiki.utils import bcrypt
|
||||
|
||||
|
||||
class Page(Model):
|
||||
"""
|
||||
Page model
|
||||
"""
|
||||
__tablename__ = 'pages'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
user_id = Column(Integer, ForeignKey('users.id'))
|
||||
title = Column(String(255), nullable=False)
|
||||
body = Column(Text)
|
||||
slug = Column(String(255), nullable=False, index=True, unique=True)
|
||||
created = Column(DateTime, default=datetime.now())
|
||||
modified = Column(DateTime, default=datetime.now())
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class User(Model):
|
||||
"""
|
||||
User model
|
||||
"""
|
||||
__tablename__ = 'users'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String(255))
|
||||
email = Column(String(255), nullable=False, index=True, unique=True)
|
||||
_password = Column('password', String(255), nullable=False)
|
||||
activation_code = Column(String(255))
|
||||
|
||||
@hybrid_property
|
||||
def password(self):
|
||||
return self.password
|
||||
|
||||
@password.setter
|
||||
def password(self, value):
|
||||
self._password = bcrypt.generate_password_hash(value)
|
|
@ -0,0 +1,32 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Wiki</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||
<style type="text/css">
|
||||
body {
|
||||
min-height: 75rem;
|
||||
padding-top: 4.5rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
|
||||
<div class="container">
|
||||
<a class="navbar-brand d-flex" href="/">Wiki</a>
|
||||
<form class="d-flex">
|
||||
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
|
||||
<button class="btn btn-outline-success" type="submit">Search</button>
|
||||
</form>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="container">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
<!-- JavaScript Bundle with Popper -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<article class="edit-page">
|
||||
<form action="{{ request.root_path + request.path }}" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="page-title" class="form-label">Title</label>
|
||||
<input type="text" class="form-control" id="page-title" name="page-title" aria-describedby="page-title-help" value="{{ page.title }}">
|
||||
<div id="page-title-help" class="form-text">The title of the page</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="page-body" class="form-label">Body</label>
|
||||
<textarea id="page-body" name="page-body" class="form-control font-monospace" aria-describedby="page-body-help">{% if page.body %}{{ page.body }}{% endif %}</textarea>
|
||||
<div id="page-body-help" class="form-text">The content of the page, in reStructuredText</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
</form>
|
||||
</article>
|
||||
{% endblock %}
|
|
@ -0,0 +1,19 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<article class="{{page.slug}}">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<span class="nav-link active" aria-current="page">Article</span>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/{{page.slug}}/edit">Edit</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h1 class="display-6 border-bottom">{{ page.title }}</h1>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
{{ page.body | rst2html | safe }}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
{% endblock %}
|
|
@ -0,0 +1,6 @@
|
|||
from flask_bcrypt import Bcrypt
|
||||
|
||||
bcrypt = Bcrypt()
|
||||
|
||||
|
||||
__all__ = ['bcrypt']
|
|
@ -0,0 +1,39 @@
|
|||
from datetime import datetime
|
||||
|
||||
from flask import Blueprint, request, render_template, redirect
|
||||
|
||||
from libertywiki.db import session
|
||||
from libertywiki.models import Page
|
||||
|
||||
wiki = Blueprint('wiki', __name__, url_prefix='')
|
||||
|
||||
|
||||
@wiki.route('/', defaults={'path': 'Main_Page'}, methods=['GET'])
|
||||
@wiki.route('/<path:path>', methods=['GET'])
|
||||
def index(path=None):
|
||||
page = Page.query.filter_by(slug=path).first()
|
||||
if not page:
|
||||
return redirect('/{}/edit'.format(path))
|
||||
return render_template('page.html', page=page)
|
||||
|
||||
|
||||
@wiki.route('/<path:path>/edit', methods=['GET'])
|
||||
def edit(path):
|
||||
page = Page.query.filter_by(slug=path).first()
|
||||
if not page:
|
||||
page = Page(title=path.replace('_', ' '))
|
||||
return render_template('edit.html', page=page)
|
||||
|
||||
|
||||
@wiki.route("/<path:path>/edit", methods=['POST'])
|
||||
def save(path):
|
||||
page = Page.query.filter_by(slug=path).first()
|
||||
if not page:
|
||||
page = Page()
|
||||
page.title = request.form.get('page-title')
|
||||
page.body = request.form.get('page-body')
|
||||
page.slug = page.title.replace(' ', '_')
|
||||
page.modified = datetime.now()
|
||||
session.add(page)
|
||||
session.commit()
|
||||
return redirect('/{}'.format(page.slug))
|
Loading…
Reference in New Issue