final test before release v1.0

This commit is contained in:
2023-01-21 16:43:29 +01:00
parent 59e2a50a3f
commit e8916c454f
15 changed files with 313 additions and 137 deletions

Binary file not shown.

View File

@@ -0,0 +1,26 @@
"""init
Revision ID: a632e375e7dc
Revises:
Create Date: 2023-01-21 11:25:48.517435
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'a632e375e7dc'
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('entries', 'author')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('entries', sa.Column('author', sa.VARCHAR(length=50), nullable=True))
# ### end Alembic commands ###

View File

@@ -1,55 +0,0 @@
"""init
Revision ID: d335bb2cb9da
Revises:
Create Date: 2023-01-21 08:05:36.719719
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'd335bb2cb9da'
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('tags',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('tag', sa.Unicode(length=25), nullable=True),
sa.Column('tag_name', sa.Unicode(length=25), nullable=False),
sa.PrimaryKeyConstraint('id', name=op.f('pk_tags'))
)
op.create_table('users',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.Unicode(length=255), nullable=False),
sa.Column('password', sa.Unicode(length=255), nullable=False),
sa.Column('last_logged', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('id', name=op.f('pk_users')),
sa.UniqueConstraint('name', name=op.f('uq_users_name'))
)
op.create_table('entries',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('title', sa.Unicode(length=255), nullable=False),
sa.Column('body', sa.UnicodeText(), nullable=True),
sa.Column('created', sa.DateTime(), nullable=True),
sa.Column('creator', sa.Unicode(length=50), nullable=True),
sa.Column('edited', sa.DateTime(), nullable=True),
sa.Column('editor', sa.Unicode(length=50), nullable=True),
sa.Column('tag', sa.Unicode(length=25), nullable=True),
sa.Column('author', sa.Unicode(length=50), nullable=True),
sa.Column('status', sa.Unicode(length=50), nullable=True),
sa.PrimaryKeyConstraint('id', name=op.f('pk_entries')),
sa.UniqueConstraint('title', name=op.f('uq_entries_title'))
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('entries')
op.drop_table('users')
op.drop_table('tags')
# ### end Alembic commands ###

View File

@@ -1,4 +1,4 @@
from wtforms import Form, StringField, TextAreaField, validators from wtforms import Form, StringField, TextAreaField, SelectField, validators
from wtforms import IntegerField, PasswordField from wtforms import IntegerField, PasswordField
from wtforms.validators import InputRequired, Length from wtforms.validators import InputRequired, Length
from wtforms.widgets import HiddenInput from wtforms.widgets import HiddenInput
@@ -10,10 +10,8 @@ class BlogCreateForm(Form):
filters=[strip_filter]) filters=[strip_filter])
body = TextAreaField('Corps du texte', validators=[InputRequired(), Length(min=1)], body = TextAreaField('Corps du texte', validators=[InputRequired(), Length(min=1)],
filters=[strip_filter]) filters=[strip_filter])
topic = StringField('Topic', validators=[InputRequired(), Length(min=1, max=255)], tag = SelectField('Tag')
filters=[strip_filter]) status = SelectField('Statut', choices=[('brouillon','Brouillon'),('privé','Privé'),('publié','Publié')])
tag = StringField('Tag', validators=[InputRequired(), Length(min=1, max=20)],
filters=[strip_filter])
class BlogUpdateForm(BlogCreateForm): class BlogUpdateForm(BlogCreateForm):
id = IntegerField(widget=HiddenInput()) id = IntegerField(widget=HiddenInput())
@@ -22,6 +20,13 @@ class BlogSearchForm(Form):
criteria = StringField('Critère', validators=[InputRequired(), Length(min=3, max=45)], criteria = StringField('Critère', validators=[InputRequired(), Length(min=3, max=45)],
filters=[strip_filter]) filters=[strip_filter])
class TagForm(Form):
id = IntegerField(widget=HiddenInput())
tag = StringField('Tag', validators=[InputRequired(), Length(min=1, max=25)],
filters=[strip_filter])
class UserCreateForm(Form): class UserCreateForm(Form):
username = StringField('Nom', validators=[InputRequired(), Length(min=1, max=255)], username = StringField('Nom', validators=[InputRequired(), Length(min=1, max=255)],
filters=[strip_filter]) filters=[strip_filter])

View File

@@ -21,7 +21,6 @@ class BlogRecord(Base):
edited = Column(DateTime, default=datetime.datetime.now) edited = Column(DateTime, default=datetime.datetime.now)
editor = Column(Unicode(50), default='') editor = Column(Unicode(50), default='')
tag = Column(Unicode(25)) tag = Column(Unicode(25))
author = Column(Unicode(50), default='')
status = Column(Unicode(50), default='brouillon') status = Column(Unicode(50), default='brouillon')
@property @property
@@ -38,3 +37,4 @@ class Tags(Base):
__tablename__ = 'tags' __tablename__ = 'tags'
id = Column(Integer, primary_key=True) id = Column(Integer, primary_key=True)
tag = Column(Unicode(25)) tag = Column(Unicode(25))

View File

@@ -7,6 +7,8 @@ def includeme(config):
config.add_route('blog_search', '/blog_search') config.add_route('blog_search', '/blog_search')
config.add_route('login', '/login') config.add_route('login', '/login')
config.add_route('logout', '/logout') config.add_route('logout', '/logout')
config.add_route('tags', '/tags')
config.add_route('tag_edit', '/tag_edit/{id}')
config.add_route('users', '/users') config.add_route('users', '/users')
config.add_route('user_add', '/user_add/{name}') config.add_route('user_add', '/user_add/{name}')
config.add_route('user_pwd', '/user_pwd/{name}') config.add_route('user_pwd', '/user_pwd/{name}')

View File

@@ -2,22 +2,21 @@ import sqlalchemy as sa
import datetime #<- will be used to set default dates on models import datetime #<- will be used to set default dates on models
from sqlalchemy import or_ from sqlalchemy import or_
from ..models.blog_record import BlogRecord from ..models.blog_record import BlogRecord, Tags
class BlogRecordService(object): class BlogRecordService(object):
@classmethod
def all(cls, request):
query = request.dbsession.query(BlogRecord)
return query.order_by(sa.desc(BlogRecord.created))
@classmethod @classmethod
def by_criteria(cls, request, criteria): def by_criteria(cls, request, criteria):
search = "%{}%".format(criteria) search = "%{}%".format(criteria)
query = request.dbsession.query(BlogRecord).filter(or_(BlogRecord.title.like(search), query = request.dbsession.query(BlogRecord)
BlogRecord.body.like(search))).all() if request.authenticated_userid == None:
# if user is anonym, display only published posts
query = query.filter(BlogRecord.status == 'publié')
query = query.filter(or_(BlogRecord.title.like(search),
BlogRecord.body.like(search))).all()
return query return query
@classmethod @classmethod
@@ -29,6 +28,30 @@ class BlogRecordService(object):
def get_last_created(cls, request): def get_last_created(cls, request):
# gest the 10 last created posts # gest the 10 last created posts
query = request.dbsession.query(BlogRecord) query = request.dbsession.query(BlogRecord)
if request.authenticated_userid == None:
# if user is anonym, display only published posts
query = query.filter(BlogRecord.status == 'publié')
query = query.order_by(sa.desc(BlogRecord.created)).limit(10).all() query = query.order_by(sa.desc(BlogRecord.created)).limit(10).all()
return query return query
@classmethod
def delete(cls, request, id):
request.dbsession.query(BlogRecord).filter(BlogRecord.id == id).delete(synchronize_session=False)
return
@classmethod
def get_tags(cls, request):
query = request.dbsession.query(Tags)
query = query.order_by(Tags.tag).all()
return query
@classmethod
def get_tags_byId(cls, request, id):
# gest the last 5 items modified
query = request.dbsession.query(Tags).filter(Tags.id == id).first()
return query
@classmethod
def tag_delete(cls, request, id):
request.dbsession.query(Tags).filter(Tags.id == id).delete(synchronize_session=False)
return

View File

@@ -12,20 +12,23 @@
<hr/> <hr/>
<p>{{ body_html | safe }}</p> <p>{{ body_html | safe }}</p>
<hr/> <hr/>
{% if request.authenticated_userid %} <p>
<p> Auteur : <strong>{{ entry.author }}</strong><br>
Topic : <strong>{{ entry.topic }}</strong> Publié le : <strong>{{ entry.created.strftime("%d-%m-%Y - %H:%M") }}</strong><br>
&nbsp;|&nbsp; {% if request.authenticated_userid %}
Tag : <strong>{{ entry.tag }}</strong> Modifié le : <strong>{{ entry.edited.strftime("%d-%m-%Y - %H:%M") }}</strong><br>
&nbsp;|&nbsp; Tag : <strong>{{ entry.tag }}</strong><br>
Créé le : <strong>{{ entry.created.strftime("%d-%m-%Y - %H:%M") }}</strong> Statut : <strong>{{ entry.status }}</strong>
&nbsp;|&nbsp; {% endif %}
Modifié le : <strong>{{ entry.edited.strftime("%d-%m-%Y - %H:%M") }}</strong> </p>
</p>
{% else %} <script>
<p> const anchors = document.querySelectorAll('a');
Créé : <strong title="{{ entry.created }}">{{ entry.created_in_words }}</strong> anchors.forEach((a) => {
</p> a.setAttribute('target', '__blank');
{% endif %} a.setAttribute('rel', 'noopener noreferrer');
});
</script>
{% endblock %} {% endblock %}

View File

@@ -19,30 +19,31 @@
{{ form.body(class_='form-control', cols="35", rows="20") }} {{ form.body(class_='form-control', cols="35", rows="20") }}
</div> </div>
{% for error in form.topic.errors %}
<div class="error">{{ error }}</div>
{% endfor %}
<div class="form-group">
<label class="required-field" for="topic">{{ form.topic.label }}</label>
{{ form.topic(class_='form-control') }}
</div>
{% for error in form.tag.errors %}
<div class="text-danger">{{ error }}</div>
{% endfor %}
<div class="form-group"> <div class="form-group">
<label class="required-field" for="tag">{{ form.tag.label }}</label> <label class="required-field" for="tag">{{ form.tag.label }}</label>
{{ form.tag(class_='form-control') }} {{ form.tag(class_='form-control') }}
</div> </div>
<div class="form-group">
<label class="required-field" for="status">{{ form.status.label }}</label>
{{ form.status(class_='form-control') }}
</div>
<p>
{% if blog_id != '0' %}
Créé le : <strong>{{ entry.created.strftime("%d-%m-%Y - %H:%M") }}</strong><br>
Modifié le : <strong>{{ entry.edited.strftime("%d-%m-%Y - %H:%M") }}</strong>
{% endif %}
</p>
<br /> <br />
<div class="form-group"> <div class="form-group">
<a class="btn btn-default" href="{{ request.route_url('home') }}"><span class="glyphicon glyphicon-chevron-left"></span> Retour</a> <a class="btn btn-default" href="{{ request.route_url('home') }}"><span class="glyphicon glyphicon-chevron-left"></span> Retour</a>
<button class="btn btn-primary" type="submit" name="form.submitted"> <button class="btn btn-primary" type="submit" name="form.submitted">
<span class="glyphicon glyphicon-ok"></span> Enregistrer</button> <span class="glyphicon glyphicon-ok"></span> Enregistrer</button>
{% if action == 'edit' %} {% if blog_id != '0' %}
<button class="btn btn-warning" type="submit" name="form.deleted"> <button class="btn btn-danger" type="button" data-toggle="modal" data-target="#confirmDelete">
<span class="glyphicon glyphicon-remove"></span> Supprimer</button> <span class="glyphicon glyphicon-remove"></span> Supprimer</button>
{% endif %} {% endif %}
</div> </div>
@@ -50,4 +51,30 @@
</form> </form>
<!-- Modal : Confirmation SUPRESSION -->
<div id="confirmDelete" class="modal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Supprimer une page</h4>
</div>
<div class="modal-body">
<!-- The form is placed inside the body of modal -->
<p>Etes-vous certain(e) de vouloir supprimer <b><br>
{{ entry.title }}</b> ?</p>
</div>
<div class="modal-footer">
<div class="form-group">
<div class="text-center">
<form id="confirmForm" method="post">
<button type="submit" class="btn btn-danger" name="form.deleted">Supprimer</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %} {% endblock %}

View File

@@ -3,21 +3,24 @@
{% block content %} {% block content %}
{% if request.authenticated_userid %} {% if request.authenticated_userid %}
<p><a href="{{ request.route_url('blog_edit', id='0') }}"> <p><a href="{{ request.route_url('blog_edit', id='0') }}" class="btn btn-success" role="button">
[Nouveau post]</a> <span class="glyphicon glyphicon-plus"></span> Nouveau</a>
</p> </p>
{% endif%} {% endif%}
<table id="posts_list" class="table table-condensed"> <table id="posts_list" class="table table-condensed">
{% for entry in last_ten %} {% for entry in last_ten %}
<tr> <tr>
<td>{{ entry.created.strftime("%d.%m.%Y") }}</td> <td>{{ entry.created.strftime("%d.%m.%Y") }}</td>
<td> <td>
<a href="{{ request.route_url('blog', id=entry.id, slug=entry.slug) }}">{{ entry.title }}</a> <a href="{{ request.route_url('blog', id=entry.id, slug=entry.slug) }}">{{ entry.title }}</a>
</td> </td>
<td>{{ entry.topic }}</td> <td>{{ entry.tag }}</td>
<td>{{ entry.tag }}</td> {% if entry.status != 'publié' %}
</td> <td><span class="label label-danger">{{ entry.status }}</span></td>
{% else %}
<td>&nbsp;</td>
{% endif%}
</tr> </tr>
{% else %} {% else %}
<p class="text-danger">Aucun post trouvé</p> <p class="text-danger">Aucun post trouvé</p>

View File

@@ -32,27 +32,28 @@
<a class="navbar-brand" href="{{ request.route_url('home') }}">CAO Blogr</a> <a class="navbar-brand" href="{{ request.route_url('home') }}">CAO Blogr</a>
</div> </div>
<div class="collapse navbar-collapse" id="myNavbar"> <div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li><a href="{{ request.route_url('blog_search') }}"><span class="glyphicon glyphicon-search"></span></a></li> <li><a href="{{ request.route_url('blog_search') }}"><span class="glyphicon glyphicon-search"></span></a></li>
{% if request.authenticated_userid %} {% if request.authenticated_userid %}
<li class="dropdown"> <li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">{{request.authenticated_userid}} <a class="dropdown-toggle" data-toggle="dropdown" href="#">{{request.authenticated_userid}}
<span class="caret"></span> <span class="caret"></span>
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
{% if request.authenticated_userid == 'admin' %} {% if request.authenticated_userid == 'admin' %}
<li><a href="{{request.route_url('users')}}">Utilisateurs</a></li> <li><a href="{{request.route_url('users')}}">Utilisateurs</a></li>
{% endif %} {% endif %}
<li><a href="{{ request.route_url('logout') }}">Se déconnecter</a></li> <li><a href="{{ request.route_url('tags') }}"><span class="glyphicon glyphicon-tag"></span>&nbsp;&nbsp;Tags</a></li>
</ul> <li><a href="{{ request.route_url('logout') }}"><span class="glyphicon glyphicon-off"></span>&nbsp;&nbsp;Se déconnecter</a></li>
</li> </ul>
{% else %} </li>
<!-- si anonyme, lien pour se connecter --> {% else %}
<li><a href="{{ request.route_url('login') }}"> <!-- si anonyme, lien pour se connecter -->
<span class="glyphicon glyphicon-user"></span></a></li> <li><a href="{{ request.route_url('login') }}">
{% endif %} <span class="glyphicon glyphicon-user"></span></a></li>
{% endif %}
</ul> </ul>
</div> </div>
</div> </div>
</nav> </nav>

View File

@@ -0,0 +1,55 @@
{% extends "cao_blogr:templates/layout.jinja2" %}
{% block content %}
<form action="{{ url }}" method="post" class="form">
{% for error in form.tag.errors %}
<div class="error">{{ error }}</div>
{% endfor %}
<div class="form-group">
<label class="required-field" for="tag">{{form.tag.label}}</label>
{{form.tag(class_='form-control')}}
</div>
<div class="form-group">
<a class="btn btn-default" href="{{ request.route_url('tags') }}">
<span class="glyphicon glyphicon-chevron-left"></span> Retour</a>
<button class="btn btn-primary" type="submit" name="form.submitted">
<span class="glyphicon glyphicon-ok"></span> Enregistrer</button>
{% if form.id.data %}
<button class="btn btn-danger" type="button" data-toggle="modal" data-target="#confirmDelete">
<span class="glyphicon glyphicon-remove"></span> Supprimer</button>
{% endif %}
</div>
</form>
<!-- Modal : Confirmation SUPRESSION -->
<div id="confirmDelete" class="modal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Supprimer le Tag</h4>
</div>
<div class="modal-body">
<!-- The form is placed inside the body of modal -->
<p>Etes-vous certain(e) de vouloir supprimer le Tag <b>{{ form.tag.data }}</b> ?</p>
</div>
<div class="modal-footer">
<div class="form-group">
<div class="text-center">
<form id="confirmForm" method="post">
<button type="submit" class="btn btn-danger" name="form.deleted">Supprimer</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,17 @@
{% extends "cao_blogr:templates/layout.jinja2" %}
{% block content %}
<p><a href="{{ request.route_url('tag_edit', id='0') }}" class="btn btn-success" role="button">
<span class="glyphicon glyphicon-plus"></span> Nouveau</a>
</p>
<ul></ul>
{% for entry in tags %}
<li>
<a href="{{ request.route_url('tag_edit', id=entry.id) }}">{{ entry.tag }}</a>
</li>
{% endfor %}
</ul>
{% endblock %}

View File

@@ -1,8 +1,8 @@
from pyramid.view import view_config from pyramid.view import view_config
from pyramid.httpexceptions import HTTPNotFound, HTTPFound from pyramid.httpexceptions import HTTPNotFound, HTTPFound
from ..models.blog_record import BlogRecord from ..models.blog_record import BlogRecord, Tags
from ..services.blog_record import BlogRecordService from ..services.blog_record import BlogRecordService
from ..forms import BlogCreateForm, BlogUpdateForm, BlogSearchForm from ..forms import BlogCreateForm, BlogUpdateForm, BlogSearchForm, TagForm
import markdown import markdown
import datetime #<- will be used to set default dates on models import datetime #<- will be used to set default dates on models
@@ -35,13 +35,16 @@ def blog_edit(request):
blog_id = request.matchdict['id'] blog_id = request.matchdict['id']
url = request.route_url('blog_edit',id=blog_id) url = request.route_url('blog_edit',id=blog_id)
# get the list of tags
tags = BlogRecordService.get_tags(request)
if blog_id == '0': if blog_id == '0':
# create a new post # create a new post
entry = BlogRecord() entry = BlogRecord()
# set default values # set default values
entry.tag = 'pyramid'
entry.topic = 'blog'
form = BlogCreateForm(request.POST, entry) form = BlogCreateForm(request.POST, entry)
form.tag.choices = [(row.tag, row.tag) for row in tags]
page_title = 'Nouvelle page'
else: else:
# modify post # modify post
entry = BlogRecordService.by_id(request, blog_id) entry = BlogRecordService.by_id(request, blog_id)
@@ -49,26 +52,39 @@ def blog_edit(request):
request.session.flash(u"Page non trouvée : %s" % blog_id, 'warning') request.session.flash(u"Page non trouvée : %s" % blog_id, 'warning')
return HTTPFound(location=request.route_url('home')) return HTTPFound(location=request.route_url('home'))
form = BlogUpdateForm(request.POST, entry) form = BlogUpdateForm(request.POST, entry)
form.tag.choices = [(row.tag, row.tag) for row in tags]
page_title = 'Modifier : ' + entry.title
if 'form.submitted' in request.params and form.validate(): if 'form.submitted' in request.params and form.validate():
if blog_id == '0': if blog_id == '0':
form.populate_obj(entry) form.populate_obj(entry)
import pdb;pdb.set_trace() # interdire le car '/' dans le titre à cause du slug
entry.title = entry.title.replace('/','.')
entry.creator = request.authenticated_userid
entry.editor = entry.creator
request.dbsession.add(entry) request.dbsession.add(entry)
return HTTPFound(location=request.route_url('home')) return HTTPFound(location=request.route_url('home'))
else: else:
del form.id # SECURITY: prevent overwriting of primary key del form.id # SECURITY: prevent overwriting of primary key
form.populate_obj(entry) form.populate_obj(entry)
# interdire le car '/' dans le titre à cause du slug
entry.title = entry.title.replace('/','.')
entry.edited = datetime.datetime.now() entry.edited = datetime.datetime.now()
entry.editor = request.authenticated_userid
return HTTPFound(location=request.route_url('blog', id=entry.id, slug=entry.slug)) return HTTPFound(location=request.route_url('blog', id=entry.id, slug=entry.slug))
if 'form.deleted' in request.params:
BlogRecordService.delete(request, blog_id)
request.session.flash("La page a été supprimée avec succès.", 'success')
return HTTPFound(location=request.route_url('home'))
return { return {
'page_title': entry.title, 'page_title': page_title,
'url': url, 'url': url,
'form': form, 'form': form,
} 'blog_id': blog_id,
'entry': entry, }
@view_config(route_name='blog_search', @view_config(route_name='blog_search',
@@ -90,3 +106,55 @@ def blog_search(request):
'criteria': criteria, 'criteria': criteria,
} }
@view_config(route_name='tags', renderer='cao_blogr:templates/tags.jinja2', permission='view')
def tags(request):
# get the list of tags of this topic
tags = BlogRecordService.get_tags(request)
return {
'page_title': 'Tags',
'tags': tags,
}
@view_config(route_name='tag_edit', renderer='cao_blogr:templates/tag_edit.jinja2', permission='view')
def tag_edit(request):
# get tag parameters from request
tag_id = request.matchdict['id']
url = request.route_url('tag_edit', id=tag_id)
if tag_id == '0':
# create a new tag
entry = Tags()
form = TagForm(request.POST, entry)
page_title = "Nouveau Tag"
else:
# modify post
entry = BlogRecordService.get_tags_byId(request, tag_id)
if not entry:
request.session.flash(u"Tag non trouvé : %s" % tag_id, 'warning')
return HTTPFound(location=request.route_url('tags'))
form = TagForm(request.POST, entry)
page_title = entry.tag
if 'form.submitted' in request.params and form.validate():
if tag_id == '0':
form.populate_obj(entry)
request.dbsession.add(entry)
return HTTPFound(location=request.route_url('tags'))
else:
del form.id # SECURITY: prevent overwriting of primary key
form.populate_obj(entry)
return HTTPFound(location=request.route_url('tags'))
if 'form.deleted' in request.params:
BlogRecordService.tag_delete(request, entry.id)
request.session.flash("La fiche a été supprimée avec succès.", 'success')
return HTTPFound(location=request.route_url('tags'))
return {
'page_title': page_title,
'url': url,
'form': form,
}

View File

@@ -62,8 +62,9 @@ def login(request):
@view_config(route_name='logout', renderer='string') @view_config(route_name='logout', renderer='string')
def logout(request): def logout(request):
username = request.authenticated_userid
headers = forget(request) headers = forget(request)
request.session.flash('Vous avez bien été déconnecté.', 'success') request.session.flash('Au revoir ' + username + ' !', 'success')
return HTTPFound(location=request.route_url('home'), headers=headers) return HTTPFound(location=request.route_url('home'), headers=headers)