Mr Duhaz 10 mesi fa
commit
ce24cb5a6e

+ 0 - 0
README.md


+ 0 - 0
__init__.py


+ 59 - 0
admin.py

@@ -0,0 +1,59 @@
+from django.contrib import admin
+from core.models import *
+
+def bt_p_publier(modeladmin, request, queryset):
+	queryset.update(p_publier=True)
+bt_p_publier.short_description = "Passer en Public"
+def bt_p_not_publier(modeladmin, request, queryset):
+	queryset.update(p_publier=True)
+bt_p_not_publier.short_description = "Passer en Priver"
+def bt_p_menu_poid_plus(modeladmin, request, queryset):
+	for obj in queryset:
+		obj.p_menu_poid=obj.p_menu_poid+5
+		obj.save()
+bt_p_menu_poid_plus.short_description = "Augmenter le poid de 5"
+def bt_p_menu_poid_moin(modeladmin, request, queryset):
+	for obj in queryset:
+		obj.p_menu_poid=obj.p_menu_poid-5
+		obj.save()
+bt_p_menu_poid_moin.short_description = "Diminuer le poid de 5"
+
+def bt_sd_poid_plus(modeladmin, request, queryset):
+	for obj in queryset:
+		obj.sd_poid=obj.sd_poid+5
+		obj.save()
+bt_sd_poid_plus.short_description = "Augmenter le poid de 5"
+def bt_sd_poid_moin(modeladmin, request, queryset):
+	for obj in queryset:
+		obj.sd_poid=obj.sd_poid-5
+		obj.save()
+bt_sd_poid_moin.short_description = "Diminuer le poid de 5"
+
+class Page_Admin(admin.ModelAdmin):
+	form = Page_Admin_Form
+	list_display = ('p_titre', 'p_titre_slugify', 'p_adresse', 'p_contenu', 'p_right', 'p_type', 'p_menu_poid', 'p_publier','p_see_title_and_des_in_templates')
+	list_filter = ('p_type', 'p_menu_parent', 'p_publier', 'p_see_title_and_des_in_templates')
+	actions = [bt_p_menu_poid_plus, bt_p_menu_poid_moin, bt_p_publier, bt_p_not_publier]
+admin.site.register(Page, Page_Admin)
+
+class Speed_Dial_Admin(admin.ModelAdmin):
+	pass
+	list_display = ('sd_titre', 'sd_adresse', 'sd_icone', 'sd_color', 'sd_poid')
+	actions = [bt_sd_poid_plus, bt_sd_poid_moin]
+admin.site.register(Speed_Dial, Speed_Dial_Admin)
+
+class Data_Admin(admin.ModelAdmin):
+	pass
+	exclude = ('d_titre_slugify',)
+	list_display = ('d_titre', 'd_titre_slugify', 'd_type', 'd_variable',)
+admin.site.register(Data, Data_Admin)
+
+class Contact_Admin(admin.ModelAdmin):
+	pass
+	list_display = ('c_type', 'c_name', 'c_email', 'c_description', 'c_statut',)
+	search_fields = ['c_name', 'c_email', 'c_description']
+	list_filter = ('c_type', 'c_statut',)
+
+admin.site.register(Contact, Contact_Admin)
+
+

+ 5 - 0
apps.py

@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class CoreConfig(AppConfig):
+    name = 'core'

+ 49 - 0
migrations/0001_initial.py

@@ -0,0 +1,49 @@
+# Generated by Django 3.2.4 on 2021-06-07 12:36
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Contact',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('c_name', models.CharField(max_length=128, verbose_name='Votre nom')),
+                ('c_email', models.EmailField(max_length=254, verbose_name='Votre emails')),
+                ('c_type', models.CharField(choices=[('contact', 'Pour un contact'), ('beug', 'Pour un beug'), ('plainte', 'Pour une plainte')], default='contact', max_length=16, verbose_name='Type de demande')),
+                ('c_description', models.TextField(verbose_name='Votre demande')),
+                ('c_statut', models.CharField(choices=[('non_lu', 'Non Lu'), ('lu', 'Lu'), ('archive', 'Archivé')], default='non_lu', max_length=16, verbose_name='Statut de la demande')),
+            ],
+        ),
+        migrations.CreateModel(
+            name='Page',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('p_titre', models.CharField(max_length=128, unique=True, verbose_name='Titre')),
+                ('p_titre_slugify', models.CharField(blank=True, editable=False, max_length=128, verbose_name='Titre Slugify')),
+                ('p_icone', models.CharField(blank=True, max_length=32, verbose_name="Code de l'icone")),
+                ('p_type', models.CharField(choices=[('page', 'Une page'), ('sys', 'Une page interne'), ('lien', 'Un lien')], default='page', max_length=4, verbose_name='Type de page')),
+                ('p_adresse', models.CharField(max_length=64, verbose_name='Adresse')),
+                ('p_menu_position', models.CharField(choices=[('no', 'No'), ('haut', 'En haut'), ('cote', 'Sur le coté'), ('pied', 'En pied de page')], default='no', max_length=4, verbose_name='A utiliser dans un menu ?')),
+                ('p_menu_poid', models.PositiveSmallIntegerField(default=50, verbose_name='Poid si utilisé dans les menus')),
+                ('p_mots_clefs', models.CharField(blank=True, max_length=512, verbose_name='Mots clefs')),
+                ('p_description', models.TextField(blank=True, verbose_name='Description')),
+                ('p_contenu', models.TextField(blank=True, verbose_name='Contenu')),
+                ('p_right', models.TextField(blank=True, verbose_name='Contenu à droite')),
+                ('p_publier', models.BooleanField(default=False, verbose_name='Publié')),
+                ('p_see_title_and_des_in_templates', models.BooleanField(default=True, verbose_name='Description et titre visible dans les templates')),
+            ],
+            options={
+                'verbose_name': 'Gestion des pages',
+                'verbose_name_plural': 'Gestion des pages',
+                'ordering': ['p_adresse'],
+            },
+        ),
+    ]

+ 23 - 0
migrations/0002_auto_20220422_0914.py

@@ -0,0 +1,23 @@
+# Generated by Django 3.2.7 on 2022-04-22 09:14
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='page',
+            name='p_icone',
+            field=models.CharField(blank=True, max_length=64, verbose_name="Code de l'icone"),
+        ),
+        migrations.AlterField(
+            model_name='page',
+            name='p_type',
+            field=models.CharField(choices=[('page', 'Une page'), ('sys', 'Une page interne'), ('lien', 'Un lien'), ('lien_ext', 'Un lien Externe')], default='page', max_length=8, verbose_name='Type de page'),
+        ),
+    ]

+ 28 - 0
migrations/0003_data.py

@@ -0,0 +1,28 @@
+# Generated by Django 3.2.7 on 2022-11-21 11:17
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0002_auto_20220422_0914'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Data',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('d_titre', models.CharField(max_length=128, unique=True, verbose_name='Titre')),
+                ('d_titre_slugify', models.CharField(blank=True, editable=False, max_length=128, verbose_name='Titre Slugify')),
+                ('d_type', models.CharField(max_length=64, unique=True, verbose_name='Titre')),
+                ('d_variable', models.CharField(max_length=64, unique=True, verbose_name='Titre')),
+            ],
+            options={
+                'verbose_name': 'Stocage de données',
+                'verbose_name_plural': 'Stocage de données',
+                'ordering': ['d_titre'],
+            },
+        ),
+    ]

+ 33 - 0
migrations/0004_auto_20221121_1234.py

@@ -0,0 +1,33 @@
+# Generated by Django 3.2.7 on 2022-11-21 12:34
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0003_data'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='data',
+            name='d_titre',
+            field=models.CharField(max_length=128, unique=True, verbose_name='Nom'),
+        ),
+        migrations.AlterField(
+            model_name='data',
+            name='d_titre_slugify',
+            field=models.CharField(blank=True, editable=False, max_length=128, verbose_name='Nom Slugify'),
+        ),
+        migrations.AlterField(
+            model_name='data',
+            name='d_type',
+            field=models.CharField(max_length=64, verbose_name='Type'),
+        ),
+        migrations.AlterField(
+            model_name='data',
+            name='d_variable',
+            field=models.CharField(max_length=64, verbose_name='Valeur'),
+        ),
+    ]

+ 18 - 0
migrations/0005_page_p_menu_stack.py

@@ -0,0 +1,18 @@
+# Generated by Django 3.2.16 on 2022-12-09 08:31
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0004_auto_20221121_1234'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='page',
+            name='p_menu_stack',
+            field=models.BooleanField(default=False, verbose_name='Regroupé dans le menu'),
+        ),
+    ]

+ 25 - 0
migrations/0006_speed_dial.py

@@ -0,0 +1,25 @@
+# Generated by Django 3.2.16 on 2023-12-01 14:51
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0005_page_p_menu_stack'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Speed_Dial',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('sd_titre', models.CharField(max_length=128, unique=True, verbose_name='Titre')),
+                ('sd_adresse', models.CharField(max_length=64, verbose_name='Adresse')),
+            ],
+            options={
+                'verbose_name': 'Speed Dial',
+                'verbose_name_plural': 'Speed Dial',
+            },
+        ),
+    ]

+ 23 - 0
migrations/0007_auto_20231201_1455.py

@@ -0,0 +1,23 @@
+# Generated by Django 3.2.16 on 2023-12-01 14:55
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0006_speed_dial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='speed_dial',
+            name='sd_poid',
+            field=models.PositiveSmallIntegerField(default=50, verbose_name='Poid'),
+        ),
+        migrations.AlterField(
+            model_name='speed_dial',
+            name='sd_adresse',
+            field=models.CharField(max_length=256, verbose_name='Adresse'),
+        ),
+    ]

+ 18 - 0
migrations/0008_speed_dial_sd_icone.py

@@ -0,0 +1,18 @@
+# Generated by Django 3.2.16 on 2023-12-08 07:33
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0007_auto_20231201_1455'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='speed_dial',
+            name='sd_icone',
+            field=models.CharField(blank=True, max_length=64, verbose_name="Code de l'icone"),
+        ),
+    ]

+ 18 - 0
migrations/0009_speed_dial_sd_color.py

@@ -0,0 +1,18 @@
+# Generated by Django 3.2.16 on 2023-12-20 09:51
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0008_speed_dial_sd_icone'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='speed_dial',
+            name='sd_color',
+            field=models.CharField(choices=[('primary', 'Bleu'), ('secondary', 'Gris'), ('success', 'Vert'), ('danger', 'Rouge'), ('warning', 'Orange'), ('info', 'Bleu clair'), ('dark', 'Noir'), ('white', 'Blanc')], default='primary', max_length=10, verbose_name='Couleur du cadre'),
+        ),
+    ]

+ 23 - 0
migrations/0010_auto_20231222_1114.py

@@ -0,0 +1,23 @@
+# Generated by Django 3.2.16 on 2023-12-22 11:14
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0009_speed_dial_sd_color'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='page',
+            name='p_menu_stack',
+        ),
+        migrations.AddField(
+            model_name='page',
+            name='p_menu_parent',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='core.page'),
+        ),
+    ]

+ 0 - 0
migrations/__init__.py


+ 136 - 0
models.py

@@ -0,0 +1,136 @@
+from django.db import models
+from django import forms
+
+from django.template.defaultfilters import slugify
+
+from trumbowyg.widgets import TrumbowygWidget
+
+menu_pos = (
+	(u'no', u'No'),
+	(u'haut', u'En haut'),
+	(u'cote', u'Sur le coté'),
+	(u'pied', u'En pied de page'),
+)
+
+page_type = (
+	(u'page', u'Une page'),
+	(u'sys', u'Une page interne'),
+	(u'lien', u'Un lien'),
+	(u'lien_ext', u'Un lien Externe'),
+)
+
+page_color = (
+	(u'primary', u'Bleu'),
+	(u'secondary', u'Gris'),
+	(u'success', u'Vert'),
+	(u'danger', u'Rouge'),
+	(u'warning', u'Orange'),
+	(u'info', u'Bleu clair'),
+	(u'dark', u'Noir'),
+	(u'white', u'Blanc'),
+)
+
+class Data (models.Model) : #stocage de donnée dynamique
+	d_titre = models.CharField("Nom", max_length = 128, unique = True)
+	d_titre_slugify = models.CharField("Nom Slugify", max_length = 128, blank = True, editable = False)
+	d_type = models.CharField("Type", max_length = 64)
+	d_variable = models.CharField("Valeur", max_length = 64)
+
+	class Meta :
+		verbose_name = 'Stocage de données'
+		verbose_name_plural = 'Stocage de données'
+		ordering = ['d_titre']
+
+	def save(self, *args, **kwargs) :
+		self.d_titre_slugify = slugify(self.d_titre)
+		super(Data, self).save(*args, **kwargs)
+
+	def __unicode__(self):
+		return self.d_titre
+	def __str__(self):
+		return '%s' % (self.d_titre)
+
+class Page (models.Model) : #Architecture pour les pages static est dynamique
+	p_titre = models.CharField("Titre", max_length = 128, unique = True)
+	p_titre_slugify = models.CharField("Titre Slugify", max_length = 128, blank = True, editable = False)
+	p_icone = models.CharField("Code de l'icone", max_length = 64, blank = True)
+	p_type = models.CharField("Type de page",choices=page_type, max_length=8, default='page')
+	p_adresse = models.CharField("Adresse", max_length = 64)
+	p_menu_position = models.CharField("A utiliser dans un menu ?",choices=menu_pos, max_length=4, default='no')
+	p_menu_parent = models.ForeignKey('self', blank = True, null=True, on_delete=models.PROTECT)
+	p_menu_poid = models.PositiveSmallIntegerField("Poid si utilisé dans les menus", default=50)
+	p_mots_clefs = models.CharField("Mots clefs", max_length = 512, blank = True)
+	p_description = models.TextField("Description", blank = True)
+	p_contenu = models.TextField("Contenu", blank = True)
+	p_right = models.TextField("Contenu à droite", blank = True)
+	p_publier = models.BooleanField("Publié", default = False)
+	p_see_title_and_des_in_templates = models.BooleanField("Description et titre visible dans les templates", default = True)
+
+	class Meta :
+		verbose_name = 'Gestion des pages'
+		verbose_name_plural = 'Gestion des pages'
+		ordering = ['p_adresse']
+
+	def save(self, *args, **kwargs) :
+		self.p_titre_slugify = slugify(self.p_titre)
+		if self.p_type == "lien":
+			self.p_description = "."
+			self.p_contenu = "."
+
+		super(Page, self).save(*args, **kwargs)
+
+	def __unicode__(self):
+		return self.p_titre
+	def __str__(self):
+		return '%s' % (self.p_titre)
+	
+class Speed_Dial (models.Model) : # model pour génération de page SpeedDial
+	sd_titre = models.CharField("Titre", max_length = 128, unique = True)
+	sd_icone = models.CharField("Code de l'icone", max_length = 64, blank = True)
+	sd_color = models.CharField("Couleur du cadre",choices=page_color, max_length=10, default='primary')
+	sd_adresse = models.CharField("Adresse", max_length = 256)
+	sd_poid = models.PositiveSmallIntegerField("Poid", default=50)
+	
+	def __str__(self):
+		return self.sd_titre
+
+	class Meta:
+		verbose_name = "Speed Dial"
+		verbose_name_plural = "Speed Dial"
+
+class Contact (models.Model): # model de contact et retour de bug
+	c_type_liste = (
+		('contact', 'Pour un contact'),
+		('beug', 'Pour un beug'),
+		('plainte', 'Pour une plainte'),
+	)
+	c_statut_liste = (
+		('non_lu', 'Non Lu'),
+		('lu', 'Lu'),
+		('archive', 'Archivé'),
+	)
+	c_name = models.CharField("Votre nom", max_length = 128)
+	c_email = models.EmailField("Votre emails")
+	c_type = models.CharField("Type de demande", max_length=16, choices=c_type_liste, default = 'contact')
+	c_description = models.TextField("Votre demande")
+	c_statut = models.CharField("Statut de la demande", max_length=16, choices=c_statut_liste, default = 'non_lu')
+
+	def __unicode__(self):
+		return self.c_name
+	def __str__(self):
+		return '%s' % (self.c_name)
+
+class ContactForm(forms.ModelForm):# formulaire de contact lié au model 
+	class Meta:
+		model = Contact
+		fields = ['c_name', 'c_email', 'c_type', 'c_description']
+
+class Page_Admin_Form(forms.ModelForm):
+	class Meta:
+		model = Page
+		exclude = ['p_titre_slugify']
+		widgets = {
+			'p_contenu': TrumbowygWidget(),
+			'p_right': TrumbowygWidget(),
+			}
+

+ 25 - 0
templates/404.html

@@ -0,0 +1,25 @@
+{% extends 'base.html' %}
+{% load crispy_forms_tags %}
+{% load static %}
+
+{% block modals %}
+{% endblock %}
+
+{% block main %}
+<div class="card text-center mx-auto m-3 border-light " style="width: 32rem;">
+	<img src="/static/img/img-404.jpg" class="card-img-top">
+	<div class="card-body">        
+		<p>Désoler, nous l’avons bien cherché, mais nous ne l’avons pas trouvé. Cette page n’est surement plus d’actualité.</p>
+	</div>
+</div>
+{% endblock %}
+
+{% block right_panel %}
+{% endblock %}
+
+{% block script %}
+{% endblock %}
+
+
+
+

+ 163 - 0
templates/base.html

@@ -0,0 +1,163 @@
+{% load static %}
+<!DOCTYPE html>
+<html lang="fr" class="h-100">
+<head>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+	<meta name="keywords" content="{%if page.p_mots_clefs%}{{page.p_mots_clefs}}{% endif %}">
+	<meta name="description" content="{% if page.p_description %}{{page.p_description}}{% endif %}">
+	{% block add_meta_description %}{% endblock %}
+	<title>{{page.c_sitename}}{% if page.p_meta_title %} | {{page.p_meta_title}}{% elif page.p_titre %} | {{page.p_titre}}{% endif %}</title>
+	<link rel="shortcut icon" href="/static/favicon.ico">
+	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
+	<link href="//fonts.googleapis.com/css2?family=Kufam&display=swap" rel="stylesheet">
+	<script src="https://kit.fontawesome.com/7cf2a101ac.js"></script>
+	{% if not request.user.is_authenticated %}
+		<script data-ad-client="ca-pub-0171697375250839" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+	{% endif %}
+	<style type="text/css">
+		img {
+			display: block;
+			max-width: 100%;
+			height: auto;
+		}
+		body {
+			background-color:black;
+			background-image: url('{% static page.c_bgimagelogo %}'), url('{% static page.c_bgimage %}') ;
+			background-position: 96% 95%, center ;
+			background-size: 20%,cover;
+			background-repeat: no-repeat;
+			background-attachment: fixed;
+			font-size: 15px;
+		}
+	</style>
+</head>
+<body class="d-flex flex-column h-100">
+<header style="color: #fff; font-family: Omnes;">
+	<nav class="navbar navbar-expand-lg navbar-dark" style="background-color: {{page.c_bgcolor}};"> 
+		<div class="container-fluid">
+		<div class="collapse navbar-collapse" id="navbarSupportedContent">
+		<a class="navbar-brand" href="{% url 'core_index' %}"><i class="{{page.c_sitelogo}}"></i> {{page.c_sitename}} </a>
+		{% if page.p_menu_haut %}
+		<ul class="navbar-nav mr-auto">
+		{% regroup page.p_menu_haut by p_menu_parent as menu_with_parent %}
+
+		{% for p_menu_parent in menu_with_parent%}
+			{% if p_menu_parent.grouper != none %}
+			<div class="navbar-nav dropdown">
+			<a class="nav-link dropdown-toggle mr-5" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fas fa-bars" ></i> {{ p_menu_parent.grouper }}</a>
+				<div class="dropdown-menu" style="margin-top: 28px; margin-left: 5px;" aria-labelledby="navbarDropdownMenuLink">
+				{% for item in p_menu_parent.list|dictsortreversed:"p_menu_poid" %}
+					<a class="dropdown-item" {%if item.p_type == "lien_ext" %}target="_blank"{% endif %}  href="{{item.p_adresse}}">{% if item.p_icone %}<i class="{{item.p_icone}}" ></i> {% endif %}{{item.p_titre}}</a></li>
+				{% endfor %}
+				</div>
+			</div>
+			{% else %}
+				{% for item in p_menu_parent.list %}
+					<li class="nav-item"><a class="nav-link" {%if item.p_type == "lien_ext" %}target="_blank"{% endif %}  href="{{item.p_adresse}}">{% if item.p_icone %}<i class="{{item.p_icone}}" ></i> {% endif %}{{item.p_titre}}</a></li>
+				{% endfor %}
+			{% endif %}
+		{% endfor %}
+		</ul>
+		{% endif %}
+		{% if page.c_menulogin == 'True' %}
+			<div class="navbar-nav dropdown">
+				<a class="nav-link dropdown-toggle mr-5" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fas fa-id-badge" ></i> Mon profil</a>
+				<div class="dropdown-menu" style="margin-top: 28px; margin-left: 5px;" aria-labelledby="navbarDropdownMenuLink">
+					{% if not request.user.is_authenticated %}
+						<a class="dropdown-item" href="{% url 'core_login' %}" ><i class="fas fa-sign-in-alt"></i> Connexion</a>
+					{% elif request.user.is_authenticated %}
+						<a class="dropdown-item" href="{% url 'admin:index' %}" ><i class="fas fa-cog" ></i> Admin</a>
+						<a class="dropdown-item" href="{% url 'core_logout' %}" ><i class="fas fa-sign-out-alt"></i> Déconexion</a>
+					{% endif %}
+				</div>
+			</div>
+		{% endif %}
+		</div>
+		<div class="pos-f-t d-lg-none justify-content-end">
+		<div class="collapse" id="navbarToggleExternalContent">
+			<div class="p-3" style="background-color: {{page.c_bgcolor}};">
+				{% if page.p_menu_haut %}
+					<ul class="navbar-nav">
+					{% for item in page.p_menu_haut %}
+						<li class="nav-item"><a class="nav-link" {%if item.p_type == "lien_ext" %}target="_blank"{% endif %} href="{{item.p_adresse}}">{% if item.p_icone %}<i class="{{item.p_icone}}" ></i> {% endif %}{{item.p_titre}}</a></li>
+					{% endfor %}
+					{% if page.c_menulogin == 'True' %}
+						<hr>
+						{% if not request.user.is_authenticated %}
+							<li class="nav-item"><a class="nav-link" href="{% url 'core_login' %}" ><i class="fas fa-sign-in-alt"></i> Connexion</a></li>
+						{% elif request.user.is_authenticated %}
+							<li class="nav-item"><a class="nav-link" href="{% url 'admin:index' %}" ><i class="fas fa-cog" ></i> Admin</a></li>
+							<li class="nav-item"><a class="nav-link" href="{% url 'core_logout' %}" ><i class="fas fa-sign-out-alt"></i> Déconexion</a></li>
+						{% endif %}
+					{% endif %}
+					</ul>
+				{% endif %}
+			</div>
+		</div>
+		<nav class="navbar navbar-dark" style="background-color: {{page.c_bgcolor}};">
+			<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggleExternalContent" aria-controls="navbarToggleExternalContent" aria-expanded="false" aria-label="Toggle navigation">
+			<span class="navbar-toggler-icon"></span>
+			 </button>
+		</nav>
+	</div>
+	</div>
+	</nav>
+</header>
+<main role="main" class="flex-shrink-0">
+<div class="container-fluid mw-100">
+	<div class="row p-2">
+		{% block left_panel %}
+		{% endblock %}
+		<div class="col-lg-9 p-0">
+			{% if messages %}
+				<div class="card-body messages p-0 mr-3 ml-3">
+				{% for message in messages %}
+					<div class="m-2 alert alert-dismissable alert-{{ message.tags }}" data-alert="alert">
+					<button type="button" class="close" data-dismiss="alert" >&times;</button>
+					{{ message }}
+					</div>
+				{% endfor %}
+				</div>
+			{% endif %}
+			<div class="card" style="background-color: rgba(250,250,250,0.88);" >
+				{% if page.p_see_title_and_des_in_templates == True %}
+				<div class="card-header">
+						<h2>{% block title %}{% if page.p_icone != "" %}<i class="{{page.p_icone}}"></i> {% endif %}{{page.p_titre|safe}}{% endblock %}</h2>
+				</div>
+				{% endif %}
+				{% if page.p_include %}
+					{% include page.p_include %}
+				{% else %}
+					{% block main %}{% endblock %}
+				{% endif %}
+			</div>
+		</div>
+		{% if not request.user.is_authenticated or page.p_right %}
+		<div class="col-lg-3">
+			<div class="card" style="background-color: rgba(250,250,250,0.88);" >
+				{% block right_panel %}
+				{% endblock %}
+			</div>
+		</div>
+		{% endif %}
+	</div>
+</div>
+</main>
+<footer class="footer mt-auto py-1 text-white" style="background-color: {{page.c_bgcolor}};">
+	<div class="container">
+		{% if page.p_menu_pied %}
+		{% for item in page.p_menu_pied %}
+			<a class="link-light" href="{{item.p_adresse}}">{{item.p_titre}}</a>{% if not forloop.last %}, {% endif %}
+		{% endfor %}
+		{% endif %}
+	</div>
+</footer>
+{% block modals %}{% endblock %}
+<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
+<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
+{% block script %}
+{% endblock %}
+</body>
+</html>

+ 4 - 0
templates/link.html

@@ -0,0 +1,4 @@
+{% comment %} No dynamic link {% endcomment %}
+<div class="row mt-2">
+</div>
+<p>&nbsp;</p>

+ 42 - 0
templates/login.html

@@ -0,0 +1,42 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% load crispy_forms_tags %}
+
+
+
+{% block main %}
+{% if request.user.is_authenticated %}
+	<div class="card text-white bg-secondary m-5">
+	<div class="card-header">Oups ! </div>
+	<div class="card-body">
+		<p class="card-text">
+			Pardon, mais vous étez deja connecté. <a href="{% url 'core_index' %}">Retourné à accueil</a>
+		</p>
+		</div>
+	</div>
+{% else %}
+		<div class="card text-white bg-secondary m-5">
+	<div class="card-header">Aide</div>
+	<div class="card-body">
+		<p class="card-text">
+			Merci de vous connecter en utilisant vos informations de conection lié à votre ouverture de session.
+		</p>
+		</div>
+	</div>
+
+
+{% endif %}
+{% endblock %}
+
+{% block right_panel %}
+	<div class="card text-white bg-dark m-0">
+		<div class="card-header">Connection</div>
+		<div class="card-body">
+		<form method="post">{% csrf_token %}
+			{{ form|crispy }}
+			<input type="submit" class="btn btn-success" value="Se connecter">
+		</form>
+		</div>
+	</div>
+{% endblock %}
+

+ 70 - 0
templates/page.html

@@ -0,0 +1,70 @@
+{% extends 'base.html' %}
+{% load crispy_forms_tags %}
+{% load static %}
+
+{% block main %}
+
+<div class="card-body">
+{% if not page.output or page.err %}
+	{{page.p_contenu|safe}}
+{% else %}
+	{% if page.err %}{{page.err|safe}}{% endif %}
+	{% if page.output and page.err %}<hr>{% endif %}
+	{% if page.output %}{{page.output|safe|urlize}}{% endif %}
+{% endif %}
+{% if page.speeddial %}
+	<h3>Speed Dial</h3>
+	<div class="container mb-4">
+		<div class="row">
+		{% for item in page.speeddial %}
+			<div class="col-sm col-lg-3 mb-1">
+				<div class="card bg-{{item.sd_color}}" style="padding: 1px;">
+					<div class="card-body d-flex flex-row" style=" background : white; opacity: 0.85;">
+						<div class="p-2"><a class="text-decoration-none" href="{{item.sd_adresse}}" target="_blank"><i class="{% if item.sd_icone != '' %}{{item.sd_icone }}{% else %}fas fa-external-link-square-alt{% endif %}"></i></a></div>
+						<div class="p-2 w-80" onmouseover="this.style.cursor='pointer';" onclick="bt_open_url('{{item.sd_adresse|escapejs}}')">{{item.sd_titre}}</div>
+					</div>
+				</div>
+			</div>
+		{% endfor %}
+		</div>
+	</div>
+{% endif%}
+{% if page.form and not page.output %}
+	<div class="col-sm-9 p-0 m-3">
+	<div class="card text-white bg-dark">
+		{% if page.p_f_titre %}<div class="card-header">{{page.p_f_titre}}</div>{% endif %}
+		<div class="card-body">
+			<form action="{{page.p_adresse}}" method="post">{% csrf_token %}
+				{{ page.form|crispy }}
+				<input type="submit" class="btn btn-success mt-1" value="Valider">
+			</form>
+		</div>
+	</div>
+	</div>
+{% endif %}
+</div>
+{% endblock %}
+
+{% block right_panel %}
+{% if page.p_right != "" %}
+<div class="card-body">
+	{% if page.form and page.output %}
+		{% if page.p_f_titre %}<div class="card-header">{{page.p_f_titre}}</div>{% endif %}
+			<form class="mb-2" action="{{page.p_adresse}}" method="post">{% csrf_token %}
+				{{ page.form|crispy }}
+				<input type="submit" class="btn btn-success mt-1" value="Valider">
+			</form>
+	{% endif %}
+	{{page.p_right|safe}}
+</div>
+{% endif %}
+{% endblock %}
+
+{% block script %}
+<script type="text/javascript">
+function bt_open_url(url){
+	{% comment %} window.open(url,'_blank'); {% endcomment %}
+	window.location.href=url;
+};
+</script>
+{% endblock %}

+ 3 - 0
tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 236 - 0
views.py

@@ -0,0 +1,236 @@
+from django.shortcuts import render
+from django.template import loader
+from django.urls import reverse
+from django.http import HttpResponse, HttpResponseRedirect
+from django.contrib import messages
+
+
+from django.contrib.auth import authenticate, login, logout
+from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
+from django.contrib.auth.models import User
+
+from core.models import *
+
+def get_get_value(request):
+	get_value = {}
+	if request.method == 'GET':
+		get = request.GET
+		for element in get:
+			get_value[element] = get[element]
+			print(get_value)
+	return get_value
+
+def gen_menu(position):
+	try:
+		menu = Page.objects.all().exclude(p_publier = 0).filter(p_menu_position = position).order_by('p_menu_parent')
+	except:
+		menu = Page.objects.none()
+	return menu
+
+def gen_speeddial():
+	try:
+		speeddial = Speed_Dial.objects.order_by('-sd_poid')
+	except:
+		speeddial = Speed_Dial.objects.none()
+	return speeddial
+
+def get_data_value(name):
+	try:
+		data = Data.objects.get(d_titre_slugify = name)
+	except:
+		data = Data()
+		if name == "site-name":
+			data.d_titre = name
+			data.d_type = "txt"
+			data.d_variable = "Duhaz Core"
+			data.save()
+		elif name == "site-logo":
+			data.d_titre = name
+			data.d_type = "txt"
+			data.d_variable = "far fa-clone"
+			data.save()
+		elif name == "background-color":
+			data.d_titre = name
+			data.d_type = "txt"
+			data.d_variable = "#999"
+			data.save()
+		elif name == "background":
+			data.d_titre = name
+			data.d_type = "txt"
+			data.d_variable = "background.jpeg"
+			data.save()
+		elif name == "background-logo":
+			data.d_titre = name
+			data.d_type = "txt"
+			data.d_variable = "logo-txt-Mrduhaz.png"
+			data.save()
+		elif name == "login-menu":
+			data.d_titre = name
+			data.d_type = "txt"
+			data.d_variable = "True"
+			data.save()
+		else :
+			data.d_variable = "Blop"
+	return data.d_variable
+
+
+def update_data_value(name, value):
+	try:
+		data = Data.objects.get(d_titre_slugify = name)
+		data.d_variable = value
+		data.save()
+	except:
+		data = Data.objects.none()
+		data.d_variable = "Blop"
+	return data.d_variable
+
+def gen_page_base():
+	page = Page.objects.none()
+	page.p_menu_haut = gen_menu('haut')
+	page.p_menu_pied = gen_menu('pied')
+	page.p_see_title_and_des_in_templates = True
+
+	page.c_sitename = get_data_value('site-name')
+	page.c_sitelogo = get_data_value('site-logo')
+	page.c_bgcolor = get_data_value('background-color')
+	page.c_bgimage = get_data_value('background')
+	page.c_bgimagelogo = get_data_value('background-logo')
+	page.c_menulogin = get_data_value('login-menu')
+
+	return page
+
+def gen_page_sys(p_titre_slugify):
+	#print(p_titre_slugify)
+	try :
+		page = Page.objects.get(p_titre_slugify = p_titre_slugify)
+	except:
+		page = gen_page_base()
+		page.p_contenu = "<h1>Erreur la page demandé n'existe pas </h1>"
+		page.p_titre = "404 ! Erreur sur la page demmandé"
+		page.p_icone = "fas fa-bug"
+
+	page.p_menu_haut = gen_menu('haut')
+	page.p_menu_pied = gen_menu('pied')
+	page.p_meta_title = page.p_titre
+
+	page.c_sitename = get_data_value('site-name')
+	page.c_sitelogo = get_data_value('site-logo')
+	page.c_bgcolor = get_data_value('background-color')
+	page.c_bgimage = get_data_value('background')
+	page.c_bgimagelogo = get_data_value('background-logo')
+	page.c_menulogin = get_data_value('login-menu')
+	
+	return page
+
+
+def index(request):
+	page = gen_page_sys('bienvenus')
+	page.speeddial = gen_speeddial()
+
+	template = loader.get_template('page.html')
+	context = {
+		'page' : page,
+	} 
+	return HttpResponse(template.render(context, request))
+
+def page(request, p_url):
+	#print(p_url)
+	p_url = "/"+p_url
+	template = loader.get_template('page.html')
+	try:
+		page = Page.objects.get(p_adresse = p_url)
+		page.p_menu_haut = gen_menu('haut')
+		page.p_menu_pied = gen_menu('pied')
+		page.p_meta_title = page.p_titre
+		page.c_sitename = get_data_value('site-name')
+		page.c_sitelogo = get_data_value('site-logo')
+		page.c_bgcolor = get_data_value('background-color')
+		page.c_bgimage = get_data_value('background')
+		page.c_bgimagelogo = get_data_value('background-logo')
+		page.c_menulogin = get_data_value('login-menu')
+	except:
+		page = gen_page_base()
+		page.p_contenu = "<h1>Erreur la page demandé n'existe pas </h1>"
+
+	context = {
+		'page' : page,
+	}
+	return HttpResponse(template.render(context, request))
+
+def contact(request,):
+	page = gen_page_base()
+	template = loader.get_template('page.html')
+	page.p_titre = "Nous Contacter"
+	page.p_description = "Formulaire de prise de contact"
+	page.p_contenu = "<p>Merci de remplir le formulaire pour nous contacter.</p>"
+	page.p_adresse = "/contact"
+
+	if request.method == "POST":
+		form = ContactForm(request.POST)
+		if form.is_valid():
+			n_contact = form.save()
+			page.p_contenu = "<p>Merci. Nous vous répondrons au vite.</p>"
+	else :
+		form = ContactForm()
+	
+	context = {
+		'page' : page,
+		'form' : form,
+	}
+	return HttpResponse(template.render(context, request))
+
+def p_login(request):
+	next = request.GET.get('next','')
+	page = gen_page_base()
+	template = loader.get_template('login.html')
+	if request.method == "POST":
+		form = AuthenticationForm(request, data=request.POST)
+		if form.is_valid():
+			username = request.POST['username']
+			password = request.POST['password']
+			user = authenticate(request, username=username, password=password)
+			if user is not None:
+				login(request, user)
+				messages.add_message(request, messages.INFO, 'Bonjour, vous êtes maintenant connecté')
+				if next :
+					return HttpResponseRedirect(next)
+				else :
+					return HttpResponseRedirect(reverse('core_index'))
+			else :
+				pass
+	else :
+		form = AuthenticationForm(request)
+	context = {
+		'page' : page,
+		'form' : form,
+	}
+	return HttpResponse(template.render(context, request))
+
+def p_logout(request):
+	logout(request)
+	messages.add_message(request, messages.INFO, 'A bientôt')
+	return HttpResponseRedirect(reverse('core_index'))
+
+def p_registration(request):
+	page = gen_page_sys("inscription-sur-le-site")
+	template = loader.get_template('page.html')
+	page.p_f_titre = "Inscription"
+	if request.method == "POST":
+		form = UserCreationForm(request.POST)
+		if form.is_valid():
+			username = form.cleaned_data['username']
+			password = form.cleaned_data['password1']
+			user=User.objects.create_user(username=username, password=password)
+			user.save()
+			user = authenticate(username=username, password=password)
+			login(request, user)
+			messages.add_message(request, messages.INFO, 'Merci pour votre inscription')
+			return HttpResponseRedirect(reverse('flux_control_panel'))
+	else :
+		form = UserCreationForm()
+	context = {
+			'page' : page,
+			'form' : form,
+		}
+	return HttpResponse(template.render(context, request))
+