final test before release v1.0
This commit is contained in:
BIN
cao_blogr.sqlite
BIN
cao_blogr.sqlite
Binary file not shown.
26
cao_blogr/alembic/versions/20230121_a632e375e7dc.py
Normal file
26
cao_blogr/alembic/versions/20230121_a632e375e7dc.py
Normal 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 ###
|
||||||
@@ -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 ###
|
|
||||||
@@ -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])
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|
||||||
|
|||||||
@@ -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}')
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
{% if request.authenticated_userid %}
|
||||||
Tag : <strong>{{ entry.tag }}</strong>
|
Modifié le : <strong>{{ entry.edited.strftime("%d-%m-%Y - %H:%M") }}</strong><br>
|
||||||
|
|
Tag : <strong>{{ entry.tag }}</strong><br>
|
||||||
Créé le : <strong>{{ entry.created.strftime("%d-%m-%Y - %H:%M") }}</strong>
|
Statut : <strong>{{ entry.status }}</strong>
|
||||||
|
|
{% 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 %}
|
||||||
|
|
||||||
|
|||||||
@@ -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">×</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 %}
|
||||||
|
|||||||
@@ -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> </td>
|
||||||
|
{% endif%}
|
||||||
</tr>
|
</tr>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p class="text-danger">Aucun post trouvé</p>
|
<p class="text-danger">Aucun post trouvé</p>
|
||||||
|
|||||||
@@ -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> Tags</a></li>
|
||||||
</ul>
|
<li><a href="{{ request.route_url('logout') }}"><span class="glyphicon glyphicon-off"></span> 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>
|
||||||
|
|||||||
55
cao_blogr/templates/tag_edit.jinja2
Normal file
55
cao_blogr/templates/tag_edit.jinja2
Normal 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">×</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 %}
|
||||||
17
cao_blogr/templates/tags.jinja2
Normal file
17
cao_blogr/templates/tags.jinja2
Normal 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 %}
|
||||||
@@ -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,
|
||||||
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user