forked from eric.li/EditionPN
first commit
This commit is contained in:
commit
361bae10ac
11
app/__init__.py
Normal file
11
app/__init__.py
Normal file
@ -0,0 +1,11 @@
|
||||
from flask import Flask
|
||||
from config import Config
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_migrate import Migrate
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(Config)
|
||||
db = SQLAlchemy(app)
|
||||
migrate = Migrate(app, db)
|
||||
|
||||
from app import routes, models
|
97
app/forms.py
Normal file
97
app/forms.py
Normal file
@ -0,0 +1,97 @@
|
||||
from flask_wtf import FlaskForm
|
||||
from flask_wtf.file import FileAllowed
|
||||
from wtforms import StringField, SubmitField, FileField, TextAreaField, RadioField
|
||||
from wtforms.validators import DataRequired, NumberRange, Length, Regexp
|
||||
|
||||
import yaml
|
||||
import os
|
||||
|
||||
REPERTOIRE_YAML = "./export/"
|
||||
|
||||
if not os.path.exists(REPERTOIRE_YAML):
|
||||
os.makedirs(REPERTOIRE_YAML)
|
||||
|
||||
class Form(FlaskForm):
|
||||
|
||||
exporter = SubmitField("Exporter")
|
||||
fichier = FileField("Choisir fichier", validators=[FileAllowed(["yml"], "Fichier Yaml seulement!")])
|
||||
importer = SubmitField("Importer")
|
||||
|
||||
class PNForm(Form):
|
||||
file_length = len("PN0")
|
||||
|
||||
code = StringField("Code", validators=[DataRequired(), Length(3,3)])
|
||||
nom = StringField("Nom", validators=[DataRequired()] )
|
||||
diminutif = StringField("Diminutif", validators=[DataRequired()] )
|
||||
description = TextAreaField("Description", validators=[DataRequired()] )
|
||||
type = RadioField("Type", choices=[1,2,3], validators=[DataRequired()])
|
||||
|
||||
class ACForm(Form):
|
||||
file_length = len("AC0000.yml")
|
||||
|
||||
code = StringField("Code", validators=[DataRequired(), Length(6,6)])
|
||||
|
||||
|
||||
class SAEForm(Form):
|
||||
file_length = len("SAE00.yml")
|
||||
|
||||
code = StringField("Code", validators=[DataRequired(), Length(5,5)])
|
||||
titre = StringField("Titre", validators=[DataRequired()] )
|
||||
semestre = StringField("Semestre", validators=[DataRequired()] )
|
||||
heures_encadrees = StringField("Heures encadrées", validators=[DataRequired()] )
|
||||
heures_tp = StringField("Heures TP", validators=[DataRequired()] )
|
||||
projet = StringField("Projet", validators=[DataRequired()] )
|
||||
description = TextAreaField("Description", validators=[DataRequired()] )
|
||||
coef = StringField("Coef.", validators=[DataRequired()] )
|
||||
acs = StringField("ACs", validators=[DataRequired()] )
|
||||
ressources = StringField("Ressources", validators=[DataRequired()] )
|
||||
livrables = TextAreaField("Livrables", validators=[DataRequired()] )
|
||||
motscles = StringField("Mots clés", validators=[DataRequired()] )
|
||||
|
||||
|
||||
class RessourceForm(Form):
|
||||
file_length = len("R000.yml")
|
||||
|
||||
code = StringField("Code", validators=[DataRequired(), Length(4,4)])
|
||||
nom = StringField("Nom", validators=[DataRequired()] )
|
||||
semestre = StringField("Semestre", validators=[DataRequired()] )
|
||||
heures_formation = StringField("Heures formation", validators=[DataRequired()] )
|
||||
heures_tp = StringField("Heures TP", validators=[DataRequired()] )
|
||||
coef = StringField("Coef.", validators=[DataRequired()] )
|
||||
acs = StringField("ACs", validators=[DataRequired()] )
|
||||
saes = StringField("SAEs", validators=[DataRequired()] )
|
||||
prerequis = StringField("Prérequis", validators=[DataRequired()] )
|
||||
contexte = TextAreaField("Contexte", validators=[DataRequired()] )
|
||||
contenu = TextAreaField("Contenu", validators=[DataRequired()] )
|
||||
motscles = StringField("Mots clés", validators=[DataRequired()] )
|
||||
|
||||
class CompetenceForm(Form):
|
||||
file_length = len("RT0.yml")
|
||||
|
||||
code = StringField("Code", validators=[DataRequired(), Length(3,3)])
|
||||
nom = StringField("Nom", validators=[DataRequired()] )
|
||||
diminutif = StringField("Diminutif", validators=[DataRequired()] )
|
||||
description = TextAreaField("Description", validators=[DataRequired()] )
|
||||
composantes = TextAreaField("Composantes", validators=[DataRequired()] )
|
||||
situations = TextAreaField("Situations", validators=[DataRequired()] )
|
||||
niveaux = TextAreaField("Niveaux", validators=[DataRequired()] )
|
||||
|
||||
def form_import(form):
|
||||
""" Si import a été appuyé et qu'il n'y a pas d'erreur d'import => importe le fichier yaml"""
|
||||
if form.importer.data and len(form.fichier.errors) == 0 and len(form.fichier.data.filename) == form.file_length:
|
||||
fichier_Yaml = yaml.safe_load(form.fichier.data.read())
|
||||
for categorie, valeur in fichier_Yaml.items():
|
||||
form[categorie].data = valeur
|
||||
form.validate_on_submit() # Réinitialise les messages d'erreur
|
||||
return form
|
||||
|
||||
def form_export(form):
|
||||
""" Si le formulaire est valide => exporte dans un fichier yaml avec les informations du formulaire """
|
||||
output = {}
|
||||
|
||||
for categorie, valeur in list(form.data.items())[3:-1]:
|
||||
output[categorie] = valeur
|
||||
|
||||
fichier = REPERTOIRE_YAML + form.code.data + ".yml"
|
||||
with open(fichier, "w", encoding="utf8") as fid:
|
||||
fid.write(yaml.dump(output))
|
11
app/models.py
Normal file
11
app/models.py
Normal file
@ -0,0 +1,11 @@
|
||||
from app import db
|
||||
|
||||
class PN(db.Model):
|
||||
code = db.Column(db.String(3), primary_key = True)
|
||||
nom = db.Column(db.String(255))
|
||||
diminutif = db.Column(db.String(30))
|
||||
description = db.Column(db.Text())
|
||||
type = db.Column(db.Integer())
|
||||
|
||||
def __repr__(self):
|
||||
return "<PN {}>".format(self.code)
|
59
app/routes.py
Normal file
59
app/routes.py
Normal file
@ -0,0 +1,59 @@
|
||||
from flask import render_template, flash, redirect, url_for, request
|
||||
from app import app
|
||||
from app.forms import *
|
||||
from app.models import PN
|
||||
|
||||
import yaml
|
||||
|
||||
@app.route("/")
|
||||
@app.route("/index")
|
||||
def index():
|
||||
return render_template("base.html")
|
||||
|
||||
@app.route("/PN", methods=["GET","POST"])
|
||||
def PN():
|
||||
form = PNForm()
|
||||
form_validation = form.validate_on_submit()
|
||||
form = form_import(form)
|
||||
if form_validation and form.exporter.data:
|
||||
flash("Ajout du référentiel PN: {} ".format(form.code.data))
|
||||
form_export(form)
|
||||
return redirect(url_for("PN"))
|
||||
return render_template("PN.html", form = form)
|
||||
|
||||
@app.route("/AC", methods=["GET","POST"])
|
||||
def AC():
|
||||
return render_template("PN.html", form = form)
|
||||
|
||||
@app.route("/SAE", methods=["GET","POST"])
|
||||
def SAE():
|
||||
form = SAEForm()
|
||||
form_validation = form.validate_on_submit()
|
||||
form = form_import(form)
|
||||
if form_validation and form.exporter.data:
|
||||
flash("Ajout du référentiel SAE: {} ".format(form.code.data))
|
||||
form_export(form)
|
||||
return redirect(url_for("SAE"))
|
||||
return render_template("SAE.html", form = form)
|
||||
|
||||
@app.route("/Ressource", methods=["GET","POST"])
|
||||
def Ressource():
|
||||
form = RessourceForm()
|
||||
form_validation = form.validate_on_submit()
|
||||
form = form_import(form)
|
||||
if form_validation and form.exporter.data:
|
||||
flash("Ajout du référentiel Ressource: {} ".format(form.code.data))
|
||||
form_export(form)
|
||||
return redirect(url_for("Ressource"))
|
||||
return render_template("Ressource.html", form = form)
|
||||
|
||||
@app.route("/Competence", methods=["GET","POST"])
|
||||
def Competence():
|
||||
form = CompetenceForm()
|
||||
form_validation = form.validate_on_submit()
|
||||
form = form_import(form)
|
||||
if form_validation and form.exporter.data:
|
||||
flash("Ajout du référentielCompetence: {} ".format(form.code.data))
|
||||
form_export(form)
|
||||
return redirect(url_for("Competence"))
|
||||
return render_template("Competence.html", form = form)
|
16
app/templates/Competence.html
Normal file
16
app/templates/Competence.html
Normal file
@ -0,0 +1,16 @@
|
||||
{% extends "form.html" %}
|
||||
|
||||
{% block title %}RT Form{% endblock %}
|
||||
{% block form_title %}Formulaire de Compétences (RT){% endblock %}
|
||||
|
||||
{% block formulaire %}
|
||||
|
||||
{{ render_field(form.code,"input") }}
|
||||
{{ render_field(form.nom,"input") }}
|
||||
{{ render_field(form.diminutif,"input") }}
|
||||
{{ render_field(form.description,"textarea") }}
|
||||
{{ render_field(form.composantes,"textarea") }}
|
||||
{{ render_field(form.situations,"textarea") }}
|
||||
{{ render_field(form.niveaux,"textarea") }}
|
||||
|
||||
{% endblock %}
|
28
app/templates/PN.html
Normal file
28
app/templates/PN.html
Normal file
@ -0,0 +1,28 @@
|
||||
{% extends "form.html" %}
|
||||
|
||||
{% block title %}PN Form{% endblock %}
|
||||
{% block form_title %}Formulaire de Programmes Nationaux (PN){% endblock %}
|
||||
|
||||
{% block formulaire %}
|
||||
|
||||
{{ render_field(form.code,"input") }}
|
||||
{{ render_field(form.nom,"input") }}
|
||||
{{ render_field(form.diminutif,"input") }}
|
||||
{{ render_field(form.description,"textarea") }}
|
||||
|
||||
<div class="field">
|
||||
<label class="label">{{ form.type.label }}</label>
|
||||
<div class="control">
|
||||
{% for num in form.type %}
|
||||
<label class="radio">
|
||||
{{ num(class="radio") }}
|
||||
{{ num.label }}
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% for error in form.type.errors %}
|
||||
<p class="help is-danger">{{error}}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
21
app/templates/Ressource.html
Normal file
21
app/templates/Ressource.html
Normal file
@ -0,0 +1,21 @@
|
||||
{% extends "form.html" %}
|
||||
|
||||
{% block title %}Ressource Form{% endblock %}
|
||||
{% block form_title %}Formulaire de Ressources (R){% endblock %}
|
||||
|
||||
{% block formulaire %}
|
||||
|
||||
{{ render_field(form.code,"input") }}
|
||||
{{ render_field(form.nom,"input") }}
|
||||
{{ render_field(form.semestre,"input") }}
|
||||
{{ render_field(form.heures_formation,"input") }}
|
||||
{{ render_field(form.heures_tp,"input") }}
|
||||
{{ render_field(form.coef,"input") }}
|
||||
{{ render_field(form.acs,"input") }}
|
||||
{{ render_field(form.saes,"input") }}
|
||||
{{ render_field(form.prerequis,"input") }}
|
||||
{{ render_field(form.contexte,"textarea") }}
|
||||
{{ render_field(form.contenu,"textarea") }}
|
||||
{{ render_field(form.motscles,"input") }}
|
||||
|
||||
{% endblock %}
|
21
app/templates/SAE.html
Normal file
21
app/templates/SAE.html
Normal file
@ -0,0 +1,21 @@
|
||||
{% extends "form.html" %}
|
||||
|
||||
{% block title %}SAE Form{% endblock %}
|
||||
{% block form_title %}Formulaire de Situations d'apprentissages et d'évaluations (SAE){% endblock %}
|
||||
|
||||
{% block formulaire %}
|
||||
|
||||
{{ render_field(form.code,"input") }}
|
||||
{{ render_field(form.titre,"input") }}
|
||||
{{ render_field(form.semestre,"input") }}
|
||||
{{ render_field(form.heures_encadrees,"input") }}
|
||||
{{ render_field(form.heures_tp,"input") }}
|
||||
{{ render_field(form.projet,"input") }}
|
||||
{{ render_field(form.description,"textarea") }}
|
||||
{{ render_field(form.coef,"input") }}
|
||||
{{ render_field(form.acs,"input") }}
|
||||
{{ render_field(form.ressources,"input") }}
|
||||
{{ render_field(form.livrables,"textarea") }}
|
||||
{{ render_field(form.motscles,"input") }}
|
||||
|
||||
{% endblock %}
|
54
app/templates/base.html
Normal file
54
app/templates/base.html
Normal file
@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="has-navbar-fixed-top">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.2/css/bulma.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
||||
{% block head %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<!-- Barre de navigation -->
|
||||
<nav class="navbar is-primary is-spaced is-fixed-top py-0">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item is-size-5" href="https://scodoc.org/">ScoDoc</a>
|
||||
<!-- Menu deroulant affiché uniquement sur mobile -->
|
||||
<div class="navbar-burger">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navbar-menu">
|
||||
<div class="navbar-start">
|
||||
<!-- Liste des catégories -->
|
||||
<a class="navbar-item" href="{{ url_for('PN') }}">PN</a>
|
||||
<a class="navbar-item" href="{{ url_for('AC') }}">AC</a>
|
||||
<a class="navbar-item" href="{{ url_for('SAE') }}">SAÉ</a>
|
||||
<a class="navbar-item" href="{{ url_for('Ressource') }}">Ressource</a>
|
||||
<a class="navbar-item" href="{{ url_for('Competence') }}">Competence</a>
|
||||
</div>
|
||||
<div class="navbar-end">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- Contenu de la page -->
|
||||
<div class="container">
|
||||
<div class="box">
|
||||
{% with messages = get_flashed_messages() %}
|
||||
{% if messages %}
|
||||
<script>
|
||||
alert("{% for message in messages %}{{message}}{% endfor %}");
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
48
app/templates/form.html
Normal file
48
app/templates/form.html
Normal file
@ -0,0 +1,48 @@
|
||||
{% macro render_field(field,class) %}
|
||||
<div class="field">
|
||||
<label class="label">{{ field.label }}</label>
|
||||
<div class="control">
|
||||
{{ field(class=class)}}
|
||||
</div>
|
||||
{% for error in field.errors %}
|
||||
<p class="help is-danger">{{error}}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<form action="" enctype=multipart/form-data method="post" novalidate>
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="content">
|
||||
<h1 class="title">{% block form_title %}{% endblock %}</h1>
|
||||
|
||||
{% block formulaire %}{% endblock %}
|
||||
|
||||
<div class="field is-grouped">
|
||||
<div class="control">
|
||||
{{ form.exporter(class="button")}}
|
||||
</div>
|
||||
<div class="control">
|
||||
<div class="file has-name">
|
||||
<label class="file-label">
|
||||
{{ form.fichier(class="file-input") }}
|
||||
<span class="file-cta">
|
||||
<span class="file-icon">
|
||||
<i class="fas fa-file-import"></i>
|
||||
</span>
|
||||
<span class="file-label">
|
||||
{{ form.fichier.label}}
|
||||
</span>
|
||||
</span>
|
||||
{{ form.importer(class="button file-name", accept=".yml")}}
|
||||
</label>
|
||||
</div>
|
||||
{% for error in form.fichier.errors %}
|
||||
<p class="help is-danger">{{error}}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
7
config.py
Normal file
7
config.py
Normal file
@ -0,0 +1,7 @@
|
||||
import os
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
class Config(object):
|
||||
SECRET_KEY = os.environ.get("SECRET_KEY") or 'unStringRandomDuneLongueurRandom'
|
||||
SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL") or "sqlite:///" + os.path.join(basedir, "app.db")
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
7
main.py
Normal file
7
main.py
Normal file
@ -0,0 +1,7 @@
|
||||
from app import app, db
|
||||
from app.models import PN
|
||||
|
||||
@app.shell_context_processor
|
||||
def make_shell_context():
|
||||
return {"db": db, "PN": PN}
|
||||
|
1
migrations/README
Normal file
1
migrations/README
Normal file
@ -0,0 +1 @@
|
||||
Generic single-database configuration.
|
50
migrations/alembic.ini
Normal file
50
migrations/alembic.ini
Normal file
@ -0,0 +1,50 @@
|
||||
# A generic, single database configuration.
|
||||
|
||||
[alembic]
|
||||
# template used to generate migration files
|
||||
# file_template = %%(rev)s_%%(slug)s
|
||||
|
||||
# set to 'true' to run the environment during
|
||||
# the 'revision' command, regardless of autogenerate
|
||||
# revision_environment = false
|
||||
|
||||
|
||||
# Logging configuration
|
||||
[loggers]
|
||||
keys = root,sqlalchemy,alembic,flask_migrate
|
||||
|
||||
[handlers]
|
||||
keys = console
|
||||
|
||||
[formatters]
|
||||
keys = generic
|
||||
|
||||
[logger_root]
|
||||
level = WARN
|
||||
handlers = console
|
||||
qualname =
|
||||
|
||||
[logger_sqlalchemy]
|
||||
level = WARN
|
||||
handlers =
|
||||
qualname = sqlalchemy.engine
|
||||
|
||||
[logger_alembic]
|
||||
level = INFO
|
||||
handlers =
|
||||
qualname = alembic
|
||||
|
||||
[logger_flask_migrate]
|
||||
level = INFO
|
||||
handlers =
|
||||
qualname = flask_migrate
|
||||
|
||||
[handler_console]
|
||||
class = StreamHandler
|
||||
args = (sys.stderr,)
|
||||
level = NOTSET
|
||||
formatter = generic
|
||||
|
||||
[formatter_generic]
|
||||
format = %(levelname)-5.5s [%(name)s] %(message)s
|
||||
datefmt = %H:%M:%S
|
90
migrations/env.py
Normal file
90
migrations/env.py
Normal file
@ -0,0 +1,90 @@
|
||||
from __future__ import with_statement
|
||||
|
||||
import logging
|
||||
from logging.config import fileConfig
|
||||
|
||||
from flask import current_app
|
||||
|
||||
from alembic import context
|
||||
|
||||
# this is the Alembic Config object, which provides
|
||||
# access to the values within the .ini file in use.
|
||||
config = context.config
|
||||
|
||||
# Interpret the config file for Python logging.
|
||||
# This line sets up loggers basically.
|
||||
fileConfig(config.config_file_name)
|
||||
logger = logging.getLogger('alembic.env')
|
||||
|
||||
# add your model's MetaData object here
|
||||
# for 'autogenerate' support
|
||||
# from myapp import mymodel
|
||||
# target_metadata = mymodel.Base.metadata
|
||||
config.set_main_option(
|
||||
'sqlalchemy.url',
|
||||
str(current_app.extensions['migrate'].db.engine.url).replace('%', '%%'))
|
||||
target_metadata = current_app.extensions['migrate'].db.metadata
|
||||
|
||||
# other values from the config, defined by the needs of env.py,
|
||||
# can be acquired:
|
||||
# my_important_option = config.get_main_option("my_important_option")
|
||||
# ... etc.
|
||||
|
||||
|
||||
def run_migrations_offline():
|
||||
"""Run migrations in 'offline' mode.
|
||||
|
||||
This configures the context with just a URL
|
||||
and not an Engine, though an Engine is acceptable
|
||||
here as well. By skipping the Engine creation
|
||||
we don't even need a DBAPI to be available.
|
||||
|
||||
Calls to context.execute() here emit the given string to the
|
||||
script output.
|
||||
|
||||
"""
|
||||
url = config.get_main_option("sqlalchemy.url")
|
||||
context.configure(
|
||||
url=url, target_metadata=target_metadata, literal_binds=True
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
def run_migrations_online():
|
||||
"""Run migrations in 'online' mode.
|
||||
|
||||
In this scenario we need to create an Engine
|
||||
and associate a connection with the context.
|
||||
|
||||
"""
|
||||
|
||||
# this callback is used to prevent an auto-migration from being generated
|
||||
# when there are no changes to the schema
|
||||
# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
|
||||
def process_revision_directives(context, revision, directives):
|
||||
if getattr(config.cmd_opts, 'autogenerate', False):
|
||||
script = directives[0]
|
||||
if script.upgrade_ops.is_empty():
|
||||
directives[:] = []
|
||||
logger.info('No changes in schema detected.')
|
||||
|
||||
connectable = current_app.extensions['migrate'].db.engine
|
||||
|
||||
with connectable.connect() as connection:
|
||||
context.configure(
|
||||
connection=connection,
|
||||
target_metadata=target_metadata,
|
||||
process_revision_directives=process_revision_directives,
|
||||
**current_app.extensions['migrate'].configure_args
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
if context.is_offline_mode():
|
||||
run_migrations_offline()
|
||||
else:
|
||||
run_migrations_online()
|
24
migrations/script.py.mako
Normal file
24
migrations/script.py.mako
Normal file
@ -0,0 +1,24 @@
|
||||
"""${message}
|
||||
|
||||
Revision ID: ${up_revision}
|
||||
Revises: ${down_revision | comma,n}
|
||||
Create Date: ${create_date}
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
${imports if imports else ""}
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = ${repr(up_revision)}
|
||||
down_revision = ${repr(down_revision)}
|
||||
branch_labels = ${repr(branch_labels)}
|
||||
depends_on = ${repr(depends_on)}
|
||||
|
||||
|
||||
def upgrade():
|
||||
${upgrades if upgrades else "pass"}
|
||||
|
||||
|
||||
def downgrade():
|
||||
${downgrades if downgrades else "pass"}
|
34
migrations/versions/be67c6934c05_pn_table.py
Normal file
34
migrations/versions/be67c6934c05_pn_table.py
Normal file
@ -0,0 +1,34 @@
|
||||
"""PN table
|
||||
|
||||
Revision ID: be67c6934c05
|
||||
Revises:
|
||||
Create Date: 2021-05-03 17:01:39.845539
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'be67c6934c05'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('PN',
|
||||
sa.Column('code', sa.String(length=3), nullable=False),
|
||||
sa.Column('nom', sa.String(length=255), nullable=True),
|
||||
sa.Column('diminutif', sa.String(length=30), nullable=True),
|
||||
sa.Column('description', sa.Text(), nullable=True),
|
||||
sa.PrimaryKeyConstraint('code')
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('PN')
|
||||
# ### end Alembic commands ###
|
28
migrations/versions/c1377d41bf27_pn_table.py
Normal file
28
migrations/versions/c1377d41bf27_pn_table.py
Normal file
@ -0,0 +1,28 @@
|
||||
"""PN table
|
||||
|
||||
Revision ID: c1377d41bf27
|
||||
Revises: be67c6934c05
|
||||
Create Date: 2021-05-03 17:20:44.055359
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'c1377d41bf27'
|
||||
down_revision = 'be67c6934c05'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('PN', sa.Column('type', sa.Integer(), nullable=True))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('PN', 'type')
|
||||
# ### end Alembic commands ###
|
Loading…
Reference in New Issue
Block a user