From 6f9b9e4127e551621b27e4e88c5dc23c6a0f84ac Mon Sep 17 00:00:00 2001 From: Juliette Luiselli Date: Mon, 25 Mar 2019 22:30:25 +0100 Subject: [PATCH 1/3] html page d'accueil et css --- annuaire/urls.py | 3 +- fiches/static/fiches/css/style.css | 352 +++++++++++++++++++++++++++++ fiches/templates/fiches/base.html | 60 +++++ fiches/templates/fiches/fiche.html | 1 + fiches/urls.py | 6 + fiches/views.py | 3 + picture/pnmadela2.jpg | Bin 0 -> 3561 bytes 7 files changed, 424 insertions(+), 1 deletion(-) create mode 100644 fiches/static/fiches/css/style.css create mode 100644 fiches/templates/fiches/base.html create mode 100644 fiches/templates/fiches/fiche.html create mode 100644 fiches/urls.py create mode 100644 picture/pnmadela2.jpg diff --git a/annuaire/urls.py b/annuaire/urls.py index 1d7e4ba..22e75b3 100644 --- a/annuaire/urls.py +++ b/annuaire/urls.py @@ -14,8 +14,9 @@ Including another URLconf 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin -from django.urls import path +from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), + path('fiche/', include('fiches.urls')) ] diff --git a/fiches/static/fiches/css/style.css b/fiches/static/fiches/css/style.css new file mode 100644 index 0000000..63a70ef --- /dev/null +++ b/fiches/static/fiches/css/style.css @@ -0,0 +1,352 @@ +html { + background: url(../images/background-motif.png) repeat; + color: #FFF; + font-family: Verdana, Verdana, Geneva, sans-serif; +} + +body { + margin: 0 0 0.8em 0; + background: transparent url(../images/background.png) no-repeat center top; + min-height: 538px; +} + +img { + border: 0; +} + +a:link { + background-color: inherit; + color: #7978DA; + text-decoration: none; +} + +a:visited { + background-color: inherit; + color: #9CA6FF; + text-decoration: none; +} + +a:hover { + background-color: inherit; + color: #006CE3; + text-decoration: underline; +} + +p { + margin-top: 0.6em; + margin-bottom: 0.6em; +} + +.ens { + color: #89C4FF; + background-color: inherit; +} + +.tiny { + font-size: 0.8em; +} + +.verytiny { + font-size: 0.7em; +} + +.dark { + color: #666; + background-color: inherit; +} + +.center { + text-align: center; +} + +.right { + float: right; +} + +.spacer { + width: 100%; + clear: both; +} + +.error { + font-weight: bold; + color: #FB0000; + background-color: inherit; +} + +.warning { + font-weight: bold; + color: #FF8A00; + background-color: inherit; +} + +.mainspacer { + width: 100%; + height: 0.8em; +} + +.success { + font-weight: bold; + color: #00E000; + background-color: inherit; +} + +.success a:link { + background-color: inherit; + color: #008800; + text-decoration: none; +} + +.success a:visited { + background-color: inherit; + color: #008800; + text-decoration: none; +} + +.success a:hover { + background-color: inherit; + color: #4FFF4F; + text-decoration: underline; +} + +.block { + background-color: #333; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + text-align: justify; + padding: 0.5em 0.5em; + margin: 0 1em 1em 1em; +} + +#main { + padding-top: 0.5em; + margin-left: 1em; + background-color: transparent; + color: #FFF; + width: 40em; + float: left; +} + +#header { + margin: 0 1em 0 1em; + float: left; + text-align: center; +} + +#header h1 { + margin-top: 0; + font-family: Georgia, sans-serif; +} + +#header h1 a:link, #header h1 a:visited { + color: #FFF; + background-color: inherit; + text-decoration: none; +} + +#header h1 a:hover { + text-decoration: underline; +} + +#language_switch { + margin-top: 0.5em; + float: left; +} + +#language_switch form { + float: left; + padding: 0; + margin-left: 0.5em; +} + +#content { +} + +#content h3 { + margin-top: 0; + margin-bottom: 0.2em; +} + +#content h4 { + margin-top: 0.5em; + margin-bottom: 0.2em; +} + +#footer { + padding: 0.2em 0; + margin: 1em 5em 0 5em; + clear: both; + background-color: #333; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + text-align: center; +} + +#contact { + margin: 0.5em 8em 0 8em; +} + +#search { + margin-bottom: 1em; +} + +.errorlist { + display: inline; + margin-top: 0; + margin-bottom: 0; + padding-left: 0; +} + +.errorlist li { + display: inline; + font-weight: bold; + color: #E00000; + background-color: inherit; +} + +#advanced_search { + border: 1px solid #CCC; + padding: 0.5em; + margin-bottom: 1em; +} + +.advanced_filter { + width: 50%; + margin-top: 1px; + margin-bottom: 1px; + float: left; +} + +.advanced_filter input { + max-width: 60%; +} + +.submit_button { + text-align: center; +} + +.add_delete_button { + text-align: right; + margin: 0.3em; +} + +#pdflink { + text-align: right; + font-size: 0.8em; +} + +#picture { + width: 8em; + float: left; +} + +#picture img { + margin-top: 0.3em; + max-width: 8em; +} + +#infos { + padding-left: 1em; + float: left; + width: 31em; +} + +#ficheedit { + margin-top: 0; + padding-top: 0; +} + +.editfield { + padding-top: 0.2em; + padding-bottom: 0.2em; +} + +.editfield input { +} + +.editfield textarea { + margin-left: auto; + margin-right: auto; + margin-top:0.2em; + display: block; + width: 98%; + height: 3em; +} + +.message { + margin-top: 0.3em; + margin-bottom: 0.3em; + text-align: center; +} + +.long_message { + margin-top: 0.6em; + margin-bottom: 0.6em; + text-align: justify; +} + +fieldset.address .editfield textarea, fieldset.quote .editfield textarea { + height: 3em; +} + +fieldset.address, fieldset.quote { + padding-bottom: 0.2em; +} + +#main-login-container { + width: 500px; + margin: 3.5em auto; +} + +#main-login-container h3.error { + text-align: center; + width: 100%; + margin-bottom: 20px; + font-size: 1.3em; + font-family: 'Droid Serif', serif; +} + +#main-login { + width: 500px; + border: 15px solid #333; + -webkit-border-radius: 20px; + -moz-border-radius: 20px; + border-radius: 20px; +} + +#main-login.login_block { + padding: 2em; + box-shadow: 0 0 100px #AAA inset; +} + +a#login_clipper, a#login_outsider { + float: left; + display: block; + width: 250px; + height: 200px; + text-align: center; + font-family: 'Droid Serif', serif; + font-size: 1.3em; + font-weight: bold; + line-height: 190px; + text-decoration: none; + color: #FFF; +} + +a#login_clipper { + background-color: #123E96; + box-shadow: 0 0 100px #040C78 inset; +} + +a#login_clipper:hover { + background-color: #164BB6; +} + +a#login_outsider { + background-color: #961221; + box-shadow: 0 0 100px #780411 inset; +} + +a#login_outsider:hover { + background-color: #B31729; +} diff --git a/fiches/templates/fiches/base.html b/fiches/templates/fiches/base.html new file mode 100644 index 0000000..dcfe049 --- /dev/null +++ b/fiches/templates/fiches/base.html @@ -0,0 +1,60 @@ +{% load i18n %} +{% load staticfiles %} + + + + + + {% block title_onglet %}{% trans "Annuaire des élèves de l'ENS" %}{% endblock %} + + + +{% block extrahead %}{% endblock %} +{# Pour pouvoir ajouter des trucs dans le head sur une autre page #} + + + +
+
+ + {% block contentspacer %}{% endblock %} + {% block content %}{% endblock %} + +
+ +
+ + {% block contact %} + + {% trans "Contacter l'équipe annuaire" %} + + + powered by Django, KDENS + +
+ {% endblock %} + +
+
+
+ + diff --git a/fiches/templates/fiches/fiche.html b/fiches/templates/fiches/fiche.html new file mode 100644 index 0000000..ee8a4db --- /dev/null +++ b/fiches/templates/fiches/fiche.html @@ -0,0 +1 @@ +{% extends "fiches/base.html" %} \ No newline at end of file diff --git a/fiches/urls.py b/fiches/urls.py new file mode 100644 index 0000000..a155217 --- /dev/null +++ b/fiches/urls.py @@ -0,0 +1,6 @@ +from django.urls import path +from . import views + +urlpatterns = [ + path('',views.fiche, name='fiche') + ] \ No newline at end of file diff --git a/fiches/views.py b/fiches/views.py index 91ea44a..367322e 100644 --- a/fiches/views.py +++ b/fiches/views.py @@ -1,3 +1,6 @@ from django.shortcuts import render # Create your views here. + +def fiche(request): + return render(request,'fiches/fiche.html',{}) \ No newline at end of file diff --git a/picture/pnmadela2.jpg b/picture/pnmadela2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d53a11a8b697e9915f32863b1025675c954a5de3 GIT binary patch literal 3561 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 literal 0 HcmV?d00001 From 9f254fc839401c71c96be70274b67a8b1a8f02e3 Mon Sep 17 00:00:00 2001 From: Juliette Luiselli Date: Mon, 8 Apr 2019 20:07:38 +0200 Subject: [PATCH 2/3] add import --- annuaire/urls.py | 1 + 1 file changed, 1 insertion(+) diff --git a/annuaire/urls.py b/annuaire/urls.py index 22e75b3..125db47 100644 --- a/annuaire/urls.py +++ b/annuaire/urls.py @@ -13,6 +13,7 @@ Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ +from django.conf import settings from django.contrib import admin from django.urls import path, include From a672e439e8079fcf20058a6d548556bff9ec8343 Mon Sep 17 00:00:00 2001 From: Juliette Luiselli Date: Mon, 8 Apr 2019 21:47:50 +0200 Subject: [PATCH 3/3] page fiche (html) --- .gitignore | 6 +- annuaire/settings.py | 6 +- annuaire/urls.py | 4 ++ fiches/migrations/0002_auto_20190408_1929.py | 24 +++++++ fiches/models.py | 12 +++- fiches/static/fiches/css/style.css | 3 +- fiches/templates/fiches/fiche.html | 67 ++++++++++++++++++- fiches/urls.py | 2 +- fiches/views.py | 9 ++- picture/pnmadela2.jpg | Bin 3561 -> 0 bytes 10 files changed, 119 insertions(+), 14 deletions(-) create mode 100644 fiches/migrations/0002_auto_20190408_1929.py delete mode 100644 picture/pnmadela2.jpg diff --git a/.gitignore b/.gitignore index 1e6486a..51af000 100644 --- a/.gitignore +++ b/.gitignore @@ -4,11 +4,7 @@ *~ *# -/media/archives/* -/media/images/* -/media/documents/* -/media/original_images/* -/media/admin +/media/picture /recensements/ /venv/ diff --git a/annuaire/settings.py b/annuaire/settings.py index 614c878..32af7e0 100644 --- a/annuaire/settings.py +++ b/annuaire/settings.py @@ -103,7 +103,7 @@ AUTH_PASSWORD_VALIDATORS = [ # Internationalization # https://docs.djangoproject.com/en/dev/topics/i18n/ -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = 'fr-fr' TIME_ZONE = 'UTC' @@ -118,3 +118,7 @@ USE_TZ = True # https://docs.djangoproject.com/en/dev/howto/static-files/ STATIC_URL = '/static/' + +MEDIA_ROOT = os.path.join(BASE_DIR, 'media') + +MEDIA_URL = '/media/' \ No newline at end of file diff --git a/annuaire/urls.py b/annuaire/urls.py index 125db47..0c8e865 100644 --- a/annuaire/urls.py +++ b/annuaire/urls.py @@ -16,8 +16,12 @@ Including another URLconf from django.conf import settings from django.contrib import admin from django.urls import path, include +from django.conf.urls.static import static urlpatterns = [ path('admin/', admin.site.urls), path('fiche/', include('fiches.urls')) ] + +if settings.DEBUG: + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/fiches/migrations/0002_auto_20190408_1929.py b/fiches/migrations/0002_auto_20190408_1929.py new file mode 100644 index 0000000..6b5f8eb --- /dev/null +++ b/fiches/migrations/0002_auto_20190408_1929.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2 on 2019-04-08 19:29 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('fiches', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='phone', + name='profile', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fiches.Profile', verbose_name='profil'), + ), + migrations.AlterField( + model_name='social', + name='profile', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fiches.Profile', verbose_name='profil'), + ), + ] diff --git a/fiches/models.py b/fiches/models.py index beeac8d..9324314 100644 --- a/fiches/models.py +++ b/fiches/models.py @@ -26,23 +26,31 @@ class Profile(models.Model): keep_me = models.BooleanField( default=False, verbose_name=_("conserver la fiche annuaire ?") ) + def __str__(self): + return self.full_name class Department(models.Model): name = models.CharField(max_length=1023, verbose_name=_("nom du département")) + def __str__(self): + return self.name class Phone(models.Model): - profile = models.OneToOneField( + profile = models.ForeignKey( Profile, on_delete=models.CASCADE, verbose_name=_("profil") ) name = models.CharField(max_length=1023, verbose_name=_("type")) number = models.CharField(max_length=1023, verbose_name=_("numéro")) + def __str__(self): + return "{} : {}".format(self.name, self.number) class Social(models.Model): - profile = models.OneToOneField( + profile = models.ForeignKey( Profile, on_delete=models.CASCADE, verbose_name=_("profil") ) name = models.CharField(max_length=1023, verbose_name=_("type")) content = models.CharField(max_length=1023, verbose_name=_("contenu")) + def __str__(self): + return "{} : {}".format(self.name, self.content) \ No newline at end of file diff --git a/fiches/static/fiches/css/style.css b/fiches/static/fiches/css/style.css index 63a70ef..a5780d0 100644 --- a/fiches/static/fiches/css/style.css +++ b/fiches/static/fiches/css/style.css @@ -1,12 +1,11 @@ html { - background: url(../images/background-motif.png) repeat; + background-color: black; color: #FFF; font-family: Verdana, Verdana, Geneva, sans-serif; } body { margin: 0 0 0.8em 0; - background: transparent url(../images/background.png) no-repeat center top; min-height: 538px; } diff --git a/fiches/templates/fiches/fiche.html b/fiches/templates/fiches/fiche.html index ee8a4db..f51cb68 100644 --- a/fiches/templates/fiches/fiche.html +++ b/fiches/templates/fiches/fiche.html @@ -1 +1,66 @@ -{% extends "fiches/base.html" %} \ No newline at end of file +{% extends "fiches/base.html" %} +{% block content %} +
+
+ +
+
+

{{ profile.full_name }} + ({{ profile.promotion }}) + {% if profile.nickname %} + alias:{{ profile.nickname }})

+ {% endif %} +

+ {% if profile.department.exists %} + Département{{ profile.department.count|pluralize}} : + {% endif %} + {% for dep in profile.department.all %} + {{ dep }} + {% if not forloop.last %} + , + {% endif %} + {% endfor %} + {% if profile.birth_date %} +

+

+ {% if profile.phone_set.exists %} + Téléphone{{ profile.phone_set.count|pluralize}} : + {% endif %} + {% for ph in profile.phone_set.all %} + {{ ph }} + {% if not forloop.last %} + ,
+ {% endif %} + {% endfor %} +

+

+ {% if profile.social_set.exists %} + {{ profile.social_set.count|pluralize:"Réseau social,Réseaux sociaux"}} : + {% endif %} + {% for ph in profile.social_set.all %} + {{ ph }} + {% if not forloop.last %} + ,
+ {% endif %} + {% endfor %} +

+

+ Date de naissance : {{ profile.birth_date }} +

+ {% endif %} + + {% if profile.thurne %} +

+ Thurne : {{ profile.thurne }} +

+ {% endif %} +
+
+
+ {% if profile.text_field %} +

+ Champ libre : {{ profile.text_field }} +

+ {% endif %} +
+{% endblock %} \ No newline at end of file diff --git a/fiches/urls.py b/fiches/urls.py index a155217..c9dd17a 100644 --- a/fiches/urls.py +++ b/fiches/urls.py @@ -2,5 +2,5 @@ from django.urls import path from . import views urlpatterns = [ - path('',views.fiche, name='fiche') + path('',views.fiche, name='fiche') ] \ No newline at end of file diff --git a/fiches/views.py b/fiches/views.py index 367322e..214d33f 100644 --- a/fiches/views.py +++ b/fiches/views.py @@ -1,6 +1,11 @@ from django.shortcuts import render +from django.shortcuts import get_object_or_404 +from .models import Profile # Create your views here. -def fiche(request): - return render(request,'fiches/fiche.html',{}) \ No newline at end of file +def fiche(request,id): + profile=get_object_or_404(Profile,id=id) + return render(request,'fiches/fiche.html',{"profile":profile}) + + diff --git a/picture/pnmadela2.jpg b/picture/pnmadela2.jpg deleted file mode 100644 index d53a11a8b697e9915f32863b1025675c954a5de3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3561 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