Utilisation d'articles au format Atom plutôt que RSS
This commit is contained in:
parent
a8b3e5ec97
commit
386f9d1c3e
59
afpy.py
59
afpy.py
|
@ -1,4 +1,3 @@
|
|||
import datetime
|
||||
import email
|
||||
import locale
|
||||
import time
|
||||
|
@ -8,6 +7,7 @@ from xml.etree import ElementTree
|
|||
import docutils.core
|
||||
import docutils.writers.html5_polyglot
|
||||
import feedparser
|
||||
from dateutil.parser import parse
|
||||
from flask import Flask, abort, redirect, render_template, request, url_for
|
||||
from flask_cache import Cache
|
||||
from jinja2 import TemplateNotFound
|
||||
|
@ -102,8 +102,8 @@ def edit_post(name, timestamp=None):
|
|||
post = {}
|
||||
else:
|
||||
for state in ('published', 'waiting'):
|
||||
if (root / name / state / timestamp / 'post.xml').is_file():
|
||||
path = (root / name / state / timestamp / 'post.xml')
|
||||
path = (root / name / state / timestamp / 'post.xml')
|
||||
if path.is_file():
|
||||
break
|
||||
else:
|
||||
abort(404)
|
||||
|
@ -134,10 +134,10 @@ def save_post(name, timestamp=None):
|
|||
abort(404)
|
||||
post = root / name / status / timestamp / 'post.xml'
|
||||
tree = ElementTree.Element('item')
|
||||
for key in ('title', 'description', 'content', 'email'):
|
||||
for key, value in request.form.items():
|
||||
element = ElementTree.SubElement(tree, key)
|
||||
element.text = request.form[key]
|
||||
element = ElementTree.SubElement(tree, 'pubDate')
|
||||
element.text = value
|
||||
element = ElementTree.SubElement(tree, 'published')
|
||||
element.text = email.utils.formatdate(
|
||||
int(timestamp) if timestamp else time.time())
|
||||
ElementTree.ElementTree(tree).write(post)
|
||||
|
@ -148,7 +148,7 @@ def save_post(name, timestamp=None):
|
|||
elif 'unpublish' in request.form and status == 'published':
|
||||
(root / name / 'published' / timestamp).rename(
|
||||
root / name / 'waiting' / timestamp)
|
||||
return redirect(url_for('admin'))
|
||||
return redirect(url_for('admin', name=name))
|
||||
return redirect(url_for('rest', name='confirmation'))
|
||||
|
||||
|
||||
|
@ -166,19 +166,21 @@ def posts(name):
|
|||
'posts.html', body_id=name, posts=posts, title=POSTS[name], name=name)
|
||||
|
||||
|
||||
@app.route('/admin/posts')
|
||||
def admin():
|
||||
@app.route('/admin/posts/<name>')
|
||||
def admin(name):
|
||||
if name not in POSTS:
|
||||
abort(404)
|
||||
posts = {}
|
||||
for name, label in POSTS.items():
|
||||
posts[(name, label)] = name_posts = {}
|
||||
for state in ('waiting', 'published'):
|
||||
name_posts[state] = state_posts = {}
|
||||
timestamps = sorted((root / name / state).iterdir(), reverse=True)
|
||||
for timestamp in timestamps:
|
||||
tree = ElementTree.parse(timestamp / 'post.xml')
|
||||
state_posts[timestamp.name] = {
|
||||
item.tag: item.text for item in tree.iter()}
|
||||
return render_template('admin.html', body_id='admin', posts=posts)
|
||||
for state in ('waiting', 'published'):
|
||||
posts[state] = state_posts = {}
|
||||
timestamps = sorted((root / name / state).iterdir(), reverse=True)
|
||||
for timestamp in timestamps:
|
||||
tree = ElementTree.parse(timestamp / 'post.xml')
|
||||
state_posts[timestamp.name] = {
|
||||
item.tag: item.text for item in tree.iter()}
|
||||
return render_template(
|
||||
'admin.html', body_id='admin', posts=posts, title=POSTS[name],
|
||||
name=name)
|
||||
|
||||
|
||||
@app.route('/posts/<name>/<timestamp>')
|
||||
|
@ -191,7 +193,7 @@ def post(name, timestamp):
|
|||
except Exception:
|
||||
abort(404)
|
||||
post = {item.tag: item.text for item in tree.iter()}
|
||||
return render_template('post.html', body_id='post', post=post)
|
||||
return render_template('post.html', body_id='post', post=post, name=name)
|
||||
|
||||
|
||||
@app.route('/feed/<name>/rss.xml')
|
||||
|
@ -200,7 +202,7 @@ def feed(name):
|
|||
if name not in POSTS:
|
||||
abort(404)
|
||||
path = root / name / 'published'
|
||||
timestamps = sorted(path.iterdir(), reverse=True)[:12]
|
||||
timestamps = sorted(path.iterdir(), reverse=True)[:50]
|
||||
entries = []
|
||||
for timestamp in timestamps:
|
||||
tree = ElementTree.parse(timestamp / 'post.xml')
|
||||
|
@ -237,21 +239,16 @@ def jobs():
|
|||
return redirect('https://plone.afpy.org/rss-jobs/RSS', code=307)
|
||||
|
||||
|
||||
@app.template_filter('parse_rfc822_datetime')
|
||||
def parse_rfc822_datetime(rfc822_datetime):
|
||||
return email.utils.parsedate_tz(rfc822_datetime)
|
||||
|
||||
|
||||
@app.template_filter('datetime')
|
||||
def format_datetime(time_struct, format_):
|
||||
return datetime.datetime(*time_struct[:6]).strftime(format_)
|
||||
|
||||
|
||||
@app.template_filter('rfc822_datetime')
|
||||
def format_rfc822_datetime(timestamp):
|
||||
return email.utils.formatdate(timestamp)
|
||||
|
||||
|
||||
@app.template_filter('parse_iso_datetime')
|
||||
def parse_iso_datetime(iso_datetime, format_):
|
||||
return parse(iso_datetime).strftime(format_)
|
||||
|
||||
|
||||
if app.env == 'development': # pragma: no cover
|
||||
from sassutils.wsgi import SassMiddleware
|
||||
app.wsgi_app = SassMiddleware(
|
||||
|
|
1
setup.py
1
setup.py
|
@ -21,6 +21,7 @@ setup(
|
|||
'libsass',
|
||||
'docutils',
|
||||
'feedparser',
|
||||
'python-dateutil',
|
||||
],
|
||||
scripts=['afpy.py'],
|
||||
setup_requires=['pytest-runner'],
|
||||
|
|
|
@ -54,7 +54,10 @@
|
|||
<a href="{{ url_for('rest', name='rss') }}">Flux RSS</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ url_for('admin') }}">Administration</a>
|
||||
<a href="{{ url_for('admin', name='actualites') }}">Admin actualités</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ url_for('admin', name='emplois') }}">Admin offres d'emploi</a>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>
|
||||
|
|
|
@ -5,35 +5,33 @@
|
|||
{% endblock header %}
|
||||
|
||||
{% block main %}
|
||||
{% for (name, label), states in posts.items() %}
|
||||
<article>
|
||||
<h2>{{ label }}</h2>
|
||||
{% for state, timestamps in states.items() %}
|
||||
{% set state_label = 'En attente' if state == 'waiting' else 'Publiés' %}
|
||||
<h3>{{ state_label }}</h3>
|
||||
{% if timestamps %}
|
||||
<table>
|
||||
<thead>
|
||||
<article>
|
||||
<h2>{{ label }}</h2>
|
||||
{% for state, timestamps in posts.items() %}
|
||||
{% set state_label = 'En attente' if state == 'waiting' else 'Publiés' %}
|
||||
<h3>{{ state_label }}</h3>
|
||||
{% if timestamps %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Titre</th>
|
||||
<th>Date</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for timestamp, post in timestamps.items() %}
|
||||
<tr>
|
||||
<th>Titre</th>
|
||||
<th>Date</th>
|
||||
<th>Actions</th>
|
||||
<td>{{ post.title }}</td>
|
||||
<td>{{ post.published | parse_iso_datetime('%x') }}</td>
|
||||
<td><a href="{{ url_for('edit_post', name=name, timestamp=timestamp) }}">Éditer</a></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for timestamp, post in timestamps.items() %}
|
||||
<tr>
|
||||
<td>{{ post.title }}</td>
|
||||
<td>{{ post.pubDate | parse_rfc822_datetime | datetime('%x') }}</td>
|
||||
<td><a href="{{ url_for('edit_post', name=name, timestamp=timestamp) }}">Éditer</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p>Aucun article dans la catégorie « {{ label }} / {{ state_label }} »</p>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</article>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p>Aucun article.</p>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</article>
|
||||
{% endblock main %}
|
||||
|
|
|
@ -28,11 +28,25 @@
|
|||
<input name="title" value="{{ post.title }}" />
|
||||
</label>
|
||||
<label>Description
|
||||
<textarea name="description">{{ post.description }}</textarea>
|
||||
<textarea name="summary">{{ post.summary }}</textarea>
|
||||
</label>
|
||||
<label>Contenu de l'article
|
||||
<textarea name="content" id="content">{{ post.content }}</textarea>
|
||||
</label>
|
||||
{% if name == 'emplois' %}
|
||||
<label>Entreprise
|
||||
<input name="company" value="{{ post.company }}" />
|
||||
</label>
|
||||
<label>Adresse
|
||||
<input name="address" value="{{ post.address }}" />
|
||||
</label>
|
||||
<label>Personne à contacter
|
||||
<input name="contact" value="{{ post.contact }}" />
|
||||
</label>
|
||||
<label>Téléphone
|
||||
<input name="phone" value="{{ post.phone }}" />
|
||||
</label>
|
||||
{% endif %}
|
||||
<label>Adresse e-mail
|
||||
<input name="email" type="email" value="{{ post.email }}" />
|
||||
</label>
|
||||
|
@ -45,9 +59,11 @@
|
|||
{% endif %}
|
||||
{% endif %}
|
||||
</form>
|
||||
<p>
|
||||
L'adresse e-mail n'est pas rendue publique, elle est uniquement utilisée
|
||||
par les modérateurs pour vous contacter si nécessaire.
|
||||
</p>
|
||||
{% if name == 'actualites' %}
|
||||
<p>
|
||||
L'adresse e-mail n'est pas rendue publique, elle est uniquement
|
||||
utilisée par les modérateurs pour vous contacter si nécessaire.
|
||||
</p>
|
||||
{% endif %}
|
||||
</article>
|
||||
{% endblock main %}
|
||||
|
|
|
@ -24,10 +24,10 @@
|
|||
{% for timestamp, post in posts.items() %}
|
||||
<article>
|
||||
<h3>{{ post.title }}</h3>
|
||||
<time pubdate datetime="{{ post.pubDate | parse_rfc822_datetime | datetime('%Y-%m-%d') }}">
|
||||
{{ post.pubDate | parse_rfc822_datetime | datetime('%x') }}
|
||||
<time pubdate datetime="{{ post.published }}">
|
||||
{{ post.published | parse_iso_datetime('%x') }}
|
||||
</time>
|
||||
{{ post.description | safe }}
|
||||
{{ post.summary | safe }}
|
||||
<p><a href="{{ url_for('post', name=name, timestamp=timestamp) }}">Lire la suite…</a></p>
|
||||
</article>
|
||||
{% endfor %}
|
||||
|
|
|
@ -6,14 +6,37 @@
|
|||
|
||||
{% block main %}
|
||||
<article>
|
||||
<time pubdate datetime="{{ post.pubDate | parse_rfc822_datetime | datetime('%Y-%m-%d') }}">
|
||||
Posté le {{ post.pubDate | parse_rfc822_datetime | datetime('%x') }}
|
||||
<time pubdate datetime="{{ post.published }}">
|
||||
Posté le {{ post.published | parse_iso_datetime('%x') }}
|
||||
</time>
|
||||
<p>
|
||||
<em>
|
||||
{{ post.description | safe }}
|
||||
{{ post.summary | safe }}
|
||||
</em>
|
||||
</p>
|
||||
{{ post.content | safe }}
|
||||
</article>
|
||||
{% if name == 'emplois' %}
|
||||
<aside>
|
||||
<h2>{{ post.company }}</h2>
|
||||
<dl>
|
||||
{% if post.address %}
|
||||
<dt>Adresse</dt>
|
||||
<dd>{{ post.address }}</dd>
|
||||
{% endif %}
|
||||
{% if post.contact %}
|
||||
<dt>Personne à contacter</dt>
|
||||
<dd>{{ post.contact }}</dd>
|
||||
{% endif %}
|
||||
{% if post.phone %}
|
||||
<dt>Téléphone</dt>
|
||||
<dd><a href="tel:{{ post.phone }}">{{ post.phone }}</a></dd>
|
||||
{% endif %}
|
||||
{% if post.email %}
|
||||
<dt>Adresse e-mail</dt>
|
||||
<dd><a href="mailto:{{ post.email }}">{{ post.email }}</a></dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
</aside>
|
||||
{% endif %}
|
||||
{% endblock main %}
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
{% for timestamp, post in posts.items() %}
|
||||
<article>
|
||||
<h2>{{ post.title }}</h2>
|
||||
<time pubdate datetime="{{ post.pubDate | parse_rfc822_datetime | datetime('%Y-%m-%d') }}">
|
||||
{{ post.pubDate | parse_rfc822_datetime | datetime('%x') }}
|
||||
<time pubdate datetime="{{ post.published }}">
|
||||
{{ post.published | parse_iso_datetime('%x') }}
|
||||
</time>
|
||||
{{ post.description | safe }}
|
||||
{{ post.summary | safe }}
|
||||
<p><a href="{{ url_for('post', name=name, timestamp=timestamp) }}">Lire la suite…</a></p>
|
||||
</article>
|
||||
{% endfor %}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<![CDATA[ {% if entry.feed %}[{{ entry.feed | safe }}]{% endif %} {{ entry.content.title | safe }} ]]>
|
||||
</title>
|
||||
<description>
|
||||
<![CDATA[ {{ entry.content.description | safe }} ]]>
|
||||
<![CDATA[ {{ (entry.content.description or entry.content.summary) | safe }} ]]>
|
||||
</description>
|
||||
<link>
|
||||
<![CDATA[ {{ entry.content.link | safe }} ]]>
|
||||
|
|
Loading…
Reference in New Issue
Block a user