Utilisation d'articles au format Atom plutôt que RSS

This commit is contained in:
Guillaume Ayoub 2018-05-02 23:52:41 +02:00
parent a8b3e5ec97
commit 386f9d1c3e
9 changed files with 114 additions and 76 deletions

59
afpy.py
View File

@ -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(

View File

@ -21,6 +21,7 @@ setup(
'libsass',
'docutils',
'feedparser',
'python-dateutil',
],
scripts=['afpy.py'],
setup_requires=['pytest-runner'],

View File

@ -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>

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 }} ]]>