First commit - databasbaserat system snarare än filer
Kvar att göra: Hantera foton Putsa på interface
This commit is contained in:
commit
d2fc9d6349
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.DS_Store
|
||||
__pycache__/
|
||||
*.jpg
|
||||
*.db
|
||||
config.py
|
12
app/__init__.py
Normal file
12
app/__init__.py
Normal file
@ -0,0 +1,12 @@
|
||||
from flask import Flask
|
||||
from flask_bootstrap import Bootstrap
|
||||
from flaskext.markdown import Markdown
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_object('config')
|
||||
Bootstrap(app)
|
||||
Markdown(app)
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
from . import views, models
|
14
app/forms.py
Normal file
14
app/forms.py
Normal file
@ -0,0 +1,14 @@
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, BooleanField, TextAreaField, SelectField, SelectMultipleField, SubmitField
|
||||
from wtforms import widgets
|
||||
from wtforms.validators import DataRequired
|
||||
|
||||
class PageForm(FlaskForm):
|
||||
|
||||
name = StringField('namn', validators=[DataRequired()])
|
||||
title = StringField('Title', validators=[DataRequired()])
|
||||
description = TextAreaField('Beskrivning')
|
||||
endpoint = BooleanField('Produkt')
|
||||
thumbnail = SelectField('Bild')
|
||||
photos = SelectMultipleField('Galleri', option_widget=widgets.CheckboxInput(), widget=widgets.ListWidget(prefix_label=False))
|
||||
submit = SubmitField('Ok')
|
99
app/models.py
Normal file
99
app/models.py
Normal file
@ -0,0 +1,99 @@
|
||||
from . import db
|
||||
from flask import url_for
|
||||
import random
|
||||
from sqlalchemy import event
|
||||
|
||||
|
||||
photos = db.Table('photos',
|
||||
db.Column('page_id', db.Integer, db.ForeignKey('page.id')),
|
||||
db.Column('photo_id', db.Integer, db.ForeignKey('photo.id'))
|
||||
)
|
||||
|
||||
thumbnails = db.Table('thumbnails',
|
||||
db.Column('page_id', db.Integer, db.ForeignKey('page.id')),
|
||||
db.Column('photo_id', db.Integer, db.ForeignKey('photo.id'))
|
||||
)
|
||||
|
||||
|
||||
class Page(db.Model):
|
||||
__tablename__ = 'page'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
||||
parent_id = db.Column(db.Integer, db.ForeignKey('page.id'))
|
||||
children = db.relationship("Page", backref=db.backref('parent', remote_side=[id]))
|
||||
|
||||
name = db.Column(db.String(64), index=True, default="")
|
||||
permalink = db.Column(db.String(256), index=True, default="")
|
||||
|
||||
title = db.Column(db.String(120), index=True, default="")
|
||||
description = db.Column(db.Text(), index=True, default="")
|
||||
|
||||
thumbnail = db.relationship('Photo', secondary=thumbnails, uselist=False)
|
||||
|
||||
photos = db.relationship('Photo', secondary=photos)
|
||||
|
||||
endpoint = db.Column(db.Boolean)
|
||||
|
||||
|
||||
def update_permalink(self, name=None, parent_id=None):
|
||||
parent_id = parent_id or self.parent_id
|
||||
name = name or self.name
|
||||
if self.id == 1:
|
||||
self.permalink = ""
|
||||
return
|
||||
url = ""
|
||||
if parent_id:
|
||||
url = self.parent.permalink
|
||||
url = "/".join(filter(None,[url, name]))
|
||||
self.permalink = url
|
||||
print("Set permalink of " + repr(name) + " to " + url)
|
||||
|
||||
@property
|
||||
def all_photos(self):
|
||||
if self.photos:
|
||||
return self.photos
|
||||
else:
|
||||
l = [photo for c in self.children for photo in c.all_photos]
|
||||
random.shuffle(l)
|
||||
if len(l) > 25:
|
||||
del l[25:]
|
||||
return l
|
||||
@property
|
||||
def breadcrumbs(self):
|
||||
if self.parent:
|
||||
l = list(self.parent.breadcrumbs)
|
||||
else:
|
||||
l = list()
|
||||
l.append(self)
|
||||
return l
|
||||
@event.listens_for(Page.parent_id, 'set')
|
||||
def parent_set(target, value, old_value, initiator):
|
||||
if value:
|
||||
target.update_permalink(parent_id=value)
|
||||
@event.listens_for(Page.name, 'set')
|
||||
def name_set(target, value, old_value, initiator):
|
||||
if value:
|
||||
target.update_permalink(name=value)
|
||||
|
||||
class Photo(db.Model):
|
||||
__tablename__ = 'photo'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
link_id = db.Column(db.Integer, db.ForeignKey('page.id'))
|
||||
link = db.relationship("Page", foreign_keys=[link_id], uselist=False)
|
||||
alt = db.Column(db.String(120), index=True)
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
return url_for('photo', id=self.id)
|
||||
@property
|
||||
def thumbnail(self):
|
||||
return url_for('thumbnail', id=self.id)
|
||||
@property
|
||||
def slide(self):
|
||||
return url_for('slide', id=self.id)
|
||||
|
||||
@property
|
||||
def page(self):
|
||||
return url_for('page', permalink = self.link.permalink)
|
24
app/photo.py
Normal file
24
app/photo.py
Normal file
@ -0,0 +1,24 @@
|
||||
from PIL import Image, ImageOps
|
||||
import os
|
||||
|
||||
def genimg(imgin, imgout, size):
|
||||
img = Image.open(imgin)
|
||||
img.thumbnail(size)
|
||||
hpad = int((size[0]-img.size[0])/2)
|
||||
vpad = int((size[1]-img.size[1])/2)
|
||||
thumb = Image.new(mode='RGBA', size=size, color=(255,255,255,0))
|
||||
thumb.paste(img, (hpad, vpad))
|
||||
thumb.save(imgout)
|
||||
|
||||
#thumb (171,180)
|
||||
#slides (550,400)
|
||||
|
||||
def genboth(num):
|
||||
fn = '{}.jpg'.format(num)
|
||||
imgin = os.path.join('app', 'photos', fn)
|
||||
thumb = os.path.join('app', 'photos', 'thumbs', fn)
|
||||
slide = os.path.join('app', 'photos', 'slides', fn)
|
||||
|
||||
genimg(imgin, thumb, (171,180))
|
||||
genimg(imgin, slide, (550,400))
|
||||
|
BIN
app/static/favicon.ico
Normal file
BIN
app/static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
153
app/templates/admin.html
Normal file
153
app/templates/admin.html
Normal file
@ -0,0 +1,153 @@
|
||||
{% extends "base.html" %}
|
||||
{% block navbar %}
|
||||
{% endblock %}
|
||||
{% block styles %}
|
||||
{{ super() }}
|
||||
<style>
|
||||
.just-padding {
|
||||
padding: 15px;
|
||||
}
|
||||
.list-group.list-group-root {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.list-group.list-group-root .list-group {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.list-group.list-group-root .list-group-item {
|
||||
border-radius: 0;
|
||||
border-width: 1px 0 0 0;
|
||||
}
|
||||
.list-group.list-group-root > .list-group-item:first-child {
|
||||
border-top-width: 0;
|
||||
}
|
||||
.list-group.list-group-root > .list-group > .list-group-item {
|
||||
padding-left: 30px;
|
||||
}
|
||||
.list-group.list-group-root > .list-group > .list-group > .list-group-item {
|
||||
padding-left: 45px;
|
||||
}
|
||||
.list-group.list-group-root > .list-group > .list-group > .list-group > .list-group-item {
|
||||
padding-left: 60px;
|
||||
}
|
||||
.list-group.list-group-root > .list-group > .list-group > .list-group > .list-group > .list-group-item {
|
||||
padding-left: 75px;
|
||||
}
|
||||
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% macro delete_button(type, title, id) -%}
|
||||
<button type="button" class="btn btn-danger" data-toggle="modal" data-target="#deletemodal" data-type="{{type}}" data-id="{{id}}" data-title="{{title}}"><span class="glyphicon glyphicon-remove"></button>
|
||||
{%- endmacro %}
|
||||
|
||||
{% block content %}
|
||||
<div class="modal fade" id="deletemodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"><!-- Delete modal -->
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4>Är du säker?</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Vill du verkligen ta bort sidan?</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Nej</button>
|
||||
<a href="#" class="btn btn-primary">Ja</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- Delete modal -->
|
||||
|
||||
|
||||
|
||||
<div class="container">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title"> Sidor </h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="just-padding">
|
||||
<div class="list-group list-group-root well">
|
||||
{% for page in pages recursive %}
|
||||
<div class="list-group-item">
|
||||
/{{ page.permalink }} - {{ page.title }}
|
||||
<a href="{{url_for('admin_page', id=page.id)}}" class="btn btn-default"><span class="glyphicon glyphicon-pencil"></a>
|
||||
{% if page.endpoint %}
|
||||
{% else %}
|
||||
<a href="{{url_for('admin_newpage', parent=page.id)}}" class="btn btn-success"><span class="glyphicon glyphicon-plus"></a>
|
||||
{% endif %}
|
||||
{% if page.id != 1 %}
|
||||
{% if not page.children %}
|
||||
{{ delete_button('page', page.title, page.id) }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if page.children %}
|
||||
<div class="list-group">
|
||||
{{ loop(page.children) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title"> Foton </h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-body">
|
||||
<form class="form-inline">
|
||||
<div class="form-group">
|
||||
<input type="file">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default">Ladda upp foto</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% for photo in photos %}
|
||||
<div class="col-md-2">
|
||||
<div class="thumbnail">
|
||||
<img src="{{ photo.thumbnail }}" class="img-responsive">
|
||||
<div class="panel-footer">
|
||||
<a class="btn btn-default"><span class="glyphicon glyphicon-pencil"></a>
|
||||
{{ delete_button('photo', photo.alt, photo.id) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block scripts %}
|
||||
{{super()}}
|
||||
<script>
|
||||
$('#deletemodal').on('show.bs.modal', function (event) {
|
||||
var button = $(event.relatedTarget)
|
||||
var type = button.data('type')
|
||||
var id = button.data('id')
|
||||
var title = button.data('title')
|
||||
|
||||
var modal = $(this)
|
||||
if(type == 'page') {
|
||||
var message = 'Vill du verkligen ta bort sidan - ' + title + '?'
|
||||
var href = '/admin/delpage/' + id
|
||||
} else {
|
||||
var message = 'Vill du verkligen ta bort bilden - ' + title + '?'
|
||||
var href = '##'
|
||||
}
|
||||
modal.find('.modal-body p').text(message)
|
||||
modal.find('.modal-footer a').attr('href', href)
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
76
app/templates/admin_page.html
Normal file
76
app/templates/admin_page.html
Normal file
@ -0,0 +1,76 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "bootstrap/wtf.html" as wtf %}
|
||||
{% block navbar %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<form class="form-horizontal" method="post" role="form">
|
||||
|
||||
{{ wtf.form_field(form.name, form_type="horizontal") }}
|
||||
|
||||
{{ wtf.form_field(form.title, form_type="horizontal") }}
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label col-lg-2" for="description">Beskrivning</label>
|
||||
<div class="col-lg-10">
|
||||
{{ form.description(rows=20, class_="form-control") }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ wtf.form_field(form.endpoint, form_type="horizontal") }}
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label col-lg-2" for="thumbnail">Bild</label>
|
||||
<div class="col-lg-8">
|
||||
{{ form.thumbnail(class_="form-control") }}
|
||||
</div>
|
||||
<div class="col-lg-2">
|
||||
<img src="{{url_for('thumbnail', id=form.thumbnail.data)}}" class="thumbnail img-responsive">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="gallery-group" class="form-group"{% if not form.endpoint.data %} style="display: none;"{%endif%}>
|
||||
<label class="control-label col-lg-2" for="photos">Galleri</label>
|
||||
<div class="col-lg-10">
|
||||
{{ form.photos }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ wtf.form_field(form.submit, form_type="horizontal") }}
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div id="preview" class="panel-body">
|
||||
{{ page.description | markdown }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
{{super()}}
|
||||
<script>
|
||||
$('#endpoint').change(function() {
|
||||
var gallery_group = $('#gallery-group');
|
||||
if(this.checked){
|
||||
gallery_group.show();
|
||||
} else {
|
||||
gallery_group.hide();
|
||||
}
|
||||
});
|
||||
$('#description').change(function() {
|
||||
$.post("/admin/markdown", {md: $('#description').val()}).done(function(data) {
|
||||
$('#preview').html(data);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
45
app/templates/base.html
Normal file
45
app/templates/base.html
Normal file
@ -0,0 +1,45 @@
|
||||
{% extends "bootstrap/base.html" %}
|
||||
{% block title %} -- Design by Lovén -- {% endblock %}
|
||||
{% block styles %}
|
||||
{{super()}}
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
.selected img {
|
||||
opacity: 0.5;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
{% block navbar %}
|
||||
<nav class="navbar navbar-default">
|
||||
<div class="container">
|
||||
<div class="navbar-header col-xs-11">
|
||||
<ol class="breadcrumb">
|
||||
{% for b in page.breadcrumbs %}
|
||||
{% if loop.last %}
|
||||
<li class="active">
|
||||
{% else %}
|
||||
<li>
|
||||
{% endif %}
|
||||
{% if loop.first %}
|
||||
<a href="/"><img src="{{ url_for('static', filename='favicon.ico')}}"></a>
|
||||
{% endif %}
|
||||
{% if loop.last %}
|
||||
{{ b.title }}
|
||||
{% else %}
|
||||
<a href="/{{ b.permalink }}"> {{ b.title }} </a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
<div class="navbar-header col-xs-1">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="mailto:kontakt@designbyloven.se"><span class="glyphicon glyphicon-envelope"></span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{% endblock %}
|
||||
|
120
app/templates/page.html
Normal file
120
app/templates/page.html
Normal file
@ -0,0 +1,120 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
|
||||
<div class="container">
|
||||
|
||||
<div class="row"> <!-- Content row -->
|
||||
<div class="col-md-6 hidden-xs hidden-sm"> <!-- Slideshow -->
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
|
||||
<div id="myCarousel" class="carousel slide" data-ride="carousel">
|
||||
<div class="carousel-inner" role="listbox">
|
||||
{% for p in page.all_photos %}
|
||||
<div class="item {% if loop.index==1 %}active{% endif %}" data-slide-number="{{ loop.index-1 }}">
|
||||
{% if page.endpoint %}
|
||||
<a href="{{ p.url }}" title="{{ p.alt }}">
|
||||
{% else %}
|
||||
<a href="{{ p.page }}" title="{{ p.alt }}">
|
||||
{% endif %}
|
||||
<img src=" {{ p.slide }}" class="img-responsive" alt="{{ p.alt }}">
|
||||
</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if page.endpoint %}
|
||||
<div class="panel-footer" id="slider-thumbs">
|
||||
<ul class="list-inline">
|
||||
{% for p in page.all_photos %}
|
||||
<li>
|
||||
<a id="carousel-selector-{{ loop.index-1 }}" class="thumbnail {% if loop.index==1 %}selected{% endif %}" style="width: 100px; height=100px;">
|
||||
<img src="{{ p.thumbnail }}" width=100 height=100 alt="{{ p.alt }}">
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div> <!-- Slideshow -->
|
||||
|
||||
<div class="col-md-6 col-sm-12"> <!-- Content -->
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="panel-title"> <h2>{{ page.title }}</h2> </div>
|
||||
{{ page.description | markdown }}
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
{% if page.endpoint %}
|
||||
<a href="mailto:order@designbyloven.se" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span> Beställ</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- Content -->
|
||||
</div> <!-- Content row -->
|
||||
|
||||
{% if page.endpoint %}
|
||||
<div class="row"> <!-- Slideshow for small screens -->
|
||||
<div class="col-md-6 visible-xs visible-sm">
|
||||
<div class="well">
|
||||
<ul class="list-inline">
|
||||
{% for p in page.photos %}
|
||||
<li>
|
||||
<a class="thumbnail" style="width:100px; height=100px;" href="{{ p.url }}">
|
||||
<img src="{{ p.thumbnail }}" width=100 height=100 alt="{{ p.alt }}">
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- Slideshow for small screens -->
|
||||
{% else %}
|
||||
<div class="row"> <!-- Subsection list !-->
|
||||
{% for c in page.children %}
|
||||
<div class="col-xs-6 col-md-3">
|
||||
<div class="thumbnail">
|
||||
<div class="caption" style="padding: 0;">
|
||||
<div class="text-center"><a href="{{ c.permalink }}"><h3>{{ c.title }}</h3></a></div>
|
||||
</div>
|
||||
<a href="{{ c.permalink }}"><img src="{{ c.thumbnail.thumbnail }}" class="img-responsive"></a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div> <!-- Subsection list -->
|
||||
{% endif %}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
{{super()}}
|
||||
<script>
|
||||
$('#myCarousel').carousel({
|
||||
interval: 5000
|
||||
});
|
||||
|
||||
$('[id^=carousel-selector-]').click(function() {
|
||||
var id_selector = $(this).attr("id");
|
||||
var id = id_selector.substr(id_selector.length -1);
|
||||
id = parseInt(id);
|
||||
$('#myCarousel').carousel(id);
|
||||
$('[id^=carousel-selector-]').removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
});
|
||||
|
||||
$('#myCarousel').on('slid.bs.carousel', function (e) {
|
||||
var id = $('.item.active').data('slide-number');
|
||||
id = parseInt(id);
|
||||
$('[id^=carousel-selector-]').removeClass('selected');
|
||||
$('[id=carousel-selector-'+id+']').addClass('selected');
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
88
app/views.py
Normal file
88
app/views.py
Normal file
@ -0,0 +1,88 @@
|
||||
from flask import render_template, send_from_directory, redirect, url_for, request, render_template_string
|
||||
from . import app, db
|
||||
from .models import Page, Photo
|
||||
from .forms import PageForm
|
||||
|
||||
|
||||
@app.route('/')
|
||||
@app.route('/<path:permalink>')
|
||||
def page(permalink=""):
|
||||
permalink = permalink.strip("/")
|
||||
print("asked for:" + permalink)
|
||||
|
||||
page = Page.query.filter_by(permalink=permalink).first_or_404()
|
||||
|
||||
return render_template("page.html", page = page)
|
||||
|
||||
@app.route('/photo/<id>')
|
||||
def photo(id):
|
||||
return send_from_directory('photos', '{}.jpg'.format(id))
|
||||
@app.route('/thumbnail/<id>')
|
||||
def thumbnail(id):
|
||||
return send_from_directory('photos/thumbs', '{}.jpg'.format(id))
|
||||
@app.route('/slide/<id>')
|
||||
def slide(id):
|
||||
return send_from_directory('photos/slides', '{}.jpg'.format(id))
|
||||
|
||||
@app.route('/favicon.ico')
|
||||
def favicon():
|
||||
return send_from_directory('static', 'favicon.ico')
|
||||
|
||||
|
||||
@app.route('/admin')
|
||||
def admin():
|
||||
pages = [Page.query.first()]
|
||||
photos = Photo.query.all()
|
||||
return render_template("admin.html", pages=pages, photos=photos)
|
||||
|
||||
@app.route('/admin/page/<id>', methods=['GET', 'POST'])
|
||||
def admin_page(id):
|
||||
page = Page.query.filter_by(id=id).first_or_404()
|
||||
form = PageForm()
|
||||
photos = Photo.query.all()
|
||||
form.photos.choices = [('{}'.format(p.id), '<img src="/thumbnail/{}">'.format(p.id)) for p in photos]
|
||||
form.thumbnail.choices = [('{}'.format(p.id), p.alt) for p in photos]
|
||||
|
||||
if form.validate_on_submit():
|
||||
page.name = form.name.data
|
||||
page.title = form.title.data
|
||||
page.description = form.description.data
|
||||
page.endpoint = form.endpoint.data
|
||||
page.thumbnail = Photo.query.filter_by(id=form.thumbnail.data).first()
|
||||
page.photos = [Photo.query.filter_by(id=int(p)).first() for p in form.photos.data]
|
||||
|
||||
db.session.add(page)
|
||||
db.session.commit()
|
||||
return redirect(url_for('admin'))
|
||||
|
||||
else:
|
||||
form.name.data = page.name
|
||||
form.title.data = page.title
|
||||
form.description.data = page.description
|
||||
form.endpoint.data = page.endpoint
|
||||
print(page.thumbnail)
|
||||
form.thumbnail.data = str(page.thumbnail.id) if page.thumbnail else '1'
|
||||
form.photos.data = [str(p.id) for p in page.photos]
|
||||
return render_template('admin_page.html', page=page, form=form)
|
||||
|
||||
@app.route('/admin/newpage/<parent>')
|
||||
def admin_newpage(parent):
|
||||
parent = Page.query.filter_by(id=parent).first_or_404()
|
||||
new = Page(name="child_{}".format(len(parent.children)+1), title="Ny sida", endpoint=True, parent=parent, parent_id=parent.id)
|
||||
|
||||
db.session.add(new)
|
||||
|
||||
db.session.commit()
|
||||
return redirect(url_for('admin'))
|
||||
|
||||
@app.route('/admin/delpage/<id>')
|
||||
def admin_delpage(id):
|
||||
page = Page.query.filter_by(id=id).first_or_404()
|
||||
root = Page.query.filter_by(id=1).first()
|
||||
db.session.delete(page)
|
||||
db.session.commit()
|
||||
return redirect(url_for('admin'))
|
||||
|
||||
@app.route('/admin/markdown', methods=['POST'])
|
||||
def markdown():
|
||||
return render_template_string('{{ md | markdown }}', md=request.form['md'])
|
35
db_create.py
Executable file
35
db_create.py
Executable file
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python
|
||||
from config import SQLALCHEMY_DATABASE_URI
|
||||
from app import db, models
|
||||
|
||||
db.create_all()
|
||||
|
||||
ph1 = models.Photo(alt="Kuvertbody superman")
|
||||
ph2 = models.Photo(alt="Kuvertbody linjer")
|
||||
ph3 = models.Photo(alt="Kuvertbody Hedvig")
|
||||
|
||||
index = models.Page(name="", title="Design by Lovén", description="Välkommen till *Design* by **Lovén**")
|
||||
|
||||
kuvertbody = models.Page(name="kuvertbody", title="Kuvertbody", description="An praktisk body som man kan dra av neråt", thumbnail=ph1)
|
||||
linjer = models.Page(name="linjer", title="Kuvertbody - Linjer", description="Raka sömmar på framsidan", photos=[ph2, ph3], thumbnail=ph2, endpoint = True)
|
||||
superman = models.Page(name="superman", title="Kuvertbody - Superman", description="Alla barn är superhjältar", photos=[ph1], thumbnail=ph1, endpoint = True)
|
||||
|
||||
index.children = [kuvertbody]
|
||||
kuvertbody.children.append(linjer)
|
||||
kuvertbody.children.append(superman)
|
||||
|
||||
ph1.link = superman
|
||||
ph2.link = linjer
|
||||
ph3.link = linjer
|
||||
|
||||
|
||||
db.session.add(ph1)
|
||||
db.session.add(ph2)
|
||||
db.session.add(ph3)
|
||||
db.session.add(index)
|
||||
db.session.add(kuvertbody)
|
||||
db.session.add(linjer)
|
||||
db.session.add(superman)
|
||||
db.session.commit()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user