├── README.md ├── disquaire_project ├── __init__.py ├── settings.py ├── static │ └── .gitignore ├── urls.py └── wsgi.py ├── manage.py ├── requirements.txt └── store ├── __init__.py ├── __pycache__ ├── __init__.cpython-36.pyc ├── admin.cpython-36.pyc ├── apps.cpython-36.pyc ├── forms.cpython-36.pyc ├── models.cpython-36.pyc ├── tests.cpython-36.pyc ├── urls.cpython-36.pyc └── views.cpython-36.pyc ├── admin.py ├── apps.py ├── dumps └── store.json ├── forms.py ├── management ├── __init__.py ├── __pycache__ │ └── __init__.cpython-36.pyc ├── commands │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ └── add_albums.cpython-36.pyc │ ├── _private.py │ └── add_albums.py └── data │ └── albums.yml ├── migrations ├── 0001_initial.py ├── __init__.py └── __pycache__ │ ├── 0001_initial.cpython-36.pyc │ └── __init__.cpython-36.pyc ├── models.py ├── static └── store │ ├── css │ ├── bootstrap.min.css │ └── business-casual.css │ ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 │ ├── img │ ├── bg.jpg │ ├── intro-pic.jpg │ ├── slide-1.jpg │ ├── slide-2.jpg │ ├── slide-3.jpg │ └── theboatthatrocked.jpg │ └── js │ ├── bootstrap.min.js │ └── jquery.js ├── templates ├── 404.html ├── 500.html └── store │ ├── base.html │ ├── detail.html │ ├── index.html │ ├── list.html │ ├── listing.html │ ├── merci.html │ ├── search.html │ └── search_form.html ├── tests.py ├── urls.py └── views.py /README.md: -------------------------------------------------------------------------------- 1 | # Déployez une application Django 2 | 3 | Ce site sert de base au cours Déployez une application Django. 4 | 5 | # Contributeurs 6 | 7 | [Céline Martinet Sanchez](https://github.com/celine-m-s) pour OpenClassrooms. 8 | -------------------------------------------------------------------------------- /disquaire_project/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/disquaire_project/__init__.py -------------------------------------------------------------------------------- /disquaire_project/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for disquaire_project project. 3 | 4 | Generated by 'django-admin startproject' using Django 1.11.3. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.11/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/1.11/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | 16 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 17 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 18 | 19 | 20 | # Quick-start development settings - unsuitable for production 21 | # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ 22 | 23 | # SECURITY WARNING: keep the secret key used in production secret! 24 | SECRET_KEY = os.environ.get('SECRET_KEY', '4i&u(!%shd*0-3$ls)fohsjsd48t(gu%1-ch_wyzk7@#n3bd8e') 25 | # '-~aO;| F;rE[??/w^zcumh(9' 26 | 27 | 28 | # SECURITY WARNING: don't run with debug turned on in production! 29 | if os.environ.get('ENV') == 'PRODUCTION': 30 | DEBUG = False 31 | else: 32 | DEBUG = True 33 | 34 | 35 | ALLOWED_HOSTS = ['disquaire.herokuapp.com'] 36 | 37 | 38 | # Application definition 39 | 40 | INSTALLED_APPS = [ 41 | 'store.apps.StoreConfig', 42 | 'django.contrib.admin', 43 | 'django.contrib.auth', 44 | 'django.contrib.contenttypes', 45 | 'django.contrib.sessions', 46 | 'django.contrib.messages', 47 | 'django.contrib.staticfiles', 48 | 'debug_toolbar', 49 | ] 50 | 51 | MIDDLEWARE = [ 52 | 'django.middleware.security.SecurityMiddleware', 53 | 'django.contrib.sessions.middleware.SessionMiddleware', 54 | 'django.middleware.common.CommonMiddleware', 55 | 'django.middleware.csrf.CsrfViewMiddleware', 56 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 57 | 'django.contrib.messages.middleware.MessageMiddleware', 58 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 59 | 'django.middleware.locale.LocaleMiddleware', 60 | 'debug_toolbar.middleware.DebugToolbarMiddleware', 61 | 'whitenoise.middleware.WhiteNoiseMiddleware', 62 | ] 63 | 64 | ROOT_URLCONF = 'disquaire_project.urls' 65 | 66 | TEMPLATES = [ 67 | { 68 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 69 | 'DIRS': [], 70 | 'APP_DIRS': True, 71 | 'OPTIONS': { 72 | 'context_processors': [ 73 | 'django.template.context_processors.debug', 74 | 'django.template.context_processors.request', 75 | 'django.contrib.auth.context_processors.auth', 76 | 'django.contrib.messages.context_processors.messages', 77 | ], 78 | }, 79 | }, 80 | ] 81 | 82 | WSGI_APPLICATION = 'disquaire_project.wsgi.application' 83 | 84 | 85 | # Database 86 | # https://docs.djangoproject.com/en/1.11/ref/settings/#databases 87 | 88 | DATABASES = { 89 | 'default': { 90 | 'ENGINE': 'django.db.backends.postgresql', # on utilise l'adaptateur postgresql 91 | 'NAME': 'disquaire', # le nom de notre base de données créée précédemment 92 | 'USER': 'celinems', # attention : remplacez par votre nom d'utilisateur !! 93 | 'PASSWORD': '', 94 | 'HOST': '', 95 | 'PORT': '5432', 96 | } 97 | } 98 | 99 | 100 | 101 | # Password validation 102 | # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators 103 | 104 | AUTH_PASSWORD_VALIDATORS = [ 105 | { 106 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 107 | }, 108 | { 109 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 110 | }, 111 | { 112 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 113 | }, 114 | { 115 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 116 | }, 117 | ] 118 | 119 | 120 | # Internationalization 121 | # https://docs.djangoproject.com/en/1.11/topics/i18n/ 122 | 123 | LANGUAGE_CODE = 'fr' 124 | 125 | TIME_ZONE = 'Europe/Paris' 126 | 127 | USE_I18N = True 128 | 129 | USE_L10N = True 130 | 131 | USE_TZ = True 132 | 133 | 134 | # Static files (CSS, JavaScript, Images) 135 | # https://docs.djangoproject.com/en/1.11/howto/static-files/ 136 | 137 | STATIC_URL = '/static/' 138 | 139 | # Django debug toolbar 140 | INTERNAL_IPS = ['127.0.0.1'] 141 | 142 | 143 | if os.environ.get('ENV') == 'PRODUCTION': 144 | 145 | STATIC_ROOT = os.path.join(BASE_ROOT, 'staticfiles') 146 | 147 | # Simplified static file serving. 148 | # https://warehouse.python.org/project/whitenoise/ 149 | STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' 150 | -------------------------------------------------------------------------------- /disquaire_project/static/.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | -------------------------------------------------------------------------------- /disquaire_project/urls.py: -------------------------------------------------------------------------------- 1 | """disquaire_project URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/1.11/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.conf.urls import url, include 14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) 15 | """ 16 | from django.conf import settings 17 | from django.conf.urls import include, url 18 | from django.contrib import admin 19 | 20 | from store import views 21 | 22 | urlpatterns = [ 23 | url(r'^$', views.index, name="index"), 24 | url(r'^store/', include('store.urls', namespace='store')), 25 | url(r'^admin/', admin.site.urls) 26 | ] 27 | 28 | if settings.DEBUG: 29 | import debug_toolbar 30 | urlpatterns = [ 31 | url(r'^__debug__/', include(debug_toolbar.urls)), 32 | ] + urlpatterns 33 | -------------------------------------------------------------------------------- /disquaire_project/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for disquaire_project project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "disquaire_project.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "disquaire_project.settings") 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError: 10 | # The above import may fail for some other reason. Ensure that the 11 | # issue is really that Django is missing to avoid masking other 12 | # exceptions on Python 2. 13 | try: 14 | import django 15 | except ImportError: 16 | raise ImportError( 17 | "Couldn't import Django. Are you sure it's installed and " 18 | "available on your PYTHONPATH environment variable? Did you " 19 | "forget to activate a virtual environment?" 20 | ) 21 | raise 22 | execute_from_command_line(sys.argv) 23 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | dj-database-url==0.4.2 2 | Django==1.11.4 3 | django-debug-toolbar==1.8 4 | gunicorn==19.7.1 5 | psycopg2==2.7.3 6 | pytz==2017.2 7 | PyYAML==3.12 8 | sqlparse==0.2.3 9 | whitenoise==3.3.0 10 | -------------------------------------------------------------------------------- /store/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/__init__.py -------------------------------------------------------------------------------- /store/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /store/__pycache__/admin.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/__pycache__/admin.cpython-36.pyc -------------------------------------------------------------------------------- /store/__pycache__/apps.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/__pycache__/apps.cpython-36.pyc -------------------------------------------------------------------------------- /store/__pycache__/forms.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/__pycache__/forms.cpython-36.pyc -------------------------------------------------------------------------------- /store/__pycache__/models.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/__pycache__/models.cpython-36.pyc -------------------------------------------------------------------------------- /store/__pycache__/tests.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/__pycache__/tests.cpython-36.pyc -------------------------------------------------------------------------------- /store/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /store/__pycache__/views.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/__pycache__/views.cpython-36.pyc -------------------------------------------------------------------------------- /store/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.utils.safestring import mark_safe 3 | from django.core.urlresolvers import reverse 4 | from django.contrib.contenttypes.models import ContentType 5 | 6 | from .models import Booking, Contact, Album, Artist 7 | 8 | 9 | class AdminURLMixin(object): 10 | def get_admin_url(self, obj): 11 | content_type = ContentType.objects.get_for_model(obj.__class__) 12 | return reverse("admin:store_%s_change" % ( 13 | content_type.model), 14 | args=(obj.id,)) 15 | 16 | 17 | @admin.register(Booking) 18 | class BookingAdmin(admin.ModelAdmin, AdminURLMixin): 19 | list_filter = ['created_at', 'contacted'] 20 | fields = ["created_at", "contact_link", 'album_link', 'contacted'] 21 | readonly_fields = ["created_at", "contact_link", "album_link", "contacted"] 22 | 23 | def has_add_permission(self, request): 24 | return False 25 | 26 | def contact_link(self, booking): 27 | url = self.get_admin_url(booking.contact) 28 | return mark_safe("{}".format(url, booking.contact.name)) 29 | 30 | def album_link(self, booking): 31 | url = self.get_admin_url(booking.album) 32 | return mark_safe("{}".format(url, booking.album.title)) 33 | 34 | class BookingInline(admin.TabularInline, AdminURLMixin): 35 | model = Booking 36 | extra = 0 37 | readonly_fields = ["created_at", "album_link", "contacted"] 38 | fields = ["created_at", "album_link", "contacted"] 39 | verbose_name = "Réservation" 40 | verbose_name_plural = "Réservations" 41 | 42 | def has_add_permission(self, request): 43 | return False 44 | 45 | def album_link(self, booking): 46 | url = self.get_admin_url(booking.album) 47 | return mark_safe("{}".format(url, booking.album.title)) 48 | 49 | album_link.short_description = "Album" 50 | 51 | 52 | @admin.register(Contact) 53 | class ContactAdmin(admin.ModelAdmin): 54 | inlines = [BookingInline,] 55 | 56 | class AlbumArtistInline(admin.TabularInline): 57 | model = Album.artists.through 58 | extra = 1 59 | verbose_name = "Disque" 60 | verbose_name_plural = "Disques" 61 | 62 | 63 | @admin.register(Artist) 64 | class ArtistAdmin(admin.ModelAdmin): 65 | inlines = [AlbumArtistInline,] 66 | 67 | @admin.register(Album) 68 | class AlbumAdmin(admin.ModelAdmin): 69 | search_fields = ['reference', 'title'] 70 | -------------------------------------------------------------------------------- /store/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class StoreConfig(AppConfig): 5 | name = 'store' 6 | -------------------------------------------------------------------------------- /store/dumps/store.json: -------------------------------------------------------------------------------- 1 | [{"model": "store.artist", "pk": 2, "fields": {"name": "Francis Cabrel"}}, {"model": "store.artist", "pk": 3, "fields": {"name": "The Kinks"}}, {"model": "store.artist", "pk": 4, "fields": {"name": "Jeff Beck The Kinks Chris Andrews"}}, {"model": "store.artist", "pk": 5, "fields": {"name": "Chris Andrews"}}, {"model": "store.artist", "pk": 6, "fields": {"name": "The Easybeats Lulu"}}, {"model": "store.artist", "pk": 7, "fields": {"name": "Them"}}, {"model": "store.artist", "pk": 8, "fields": {"name": "Van Morrison"}}, {"model": "store.artist", "pk": 9, "fields": {"name": "The McCoys"}}, {"model": "store.artist", "pk": 10, "fields": {"name": "The Hollies"}}, {"model": "store.artist", "pk": 11, "fields": {"name": "The Tremeloes"}}, {"model": "store.artist", "pk": 12, "fields": {"name": "Aaron Neville"}}, {"model": "store.artist", "pk": 13, "fields": {"name": "John Fred and His Playboy Band"}}, {"model": "store.artist", "pk": 14, "fields": {"name": "Francoise Hardy"}}, {"model": "store.artist", "pk": 15, "fields": {"name": "Lulu"}}, {"model": "store.artist", "pk": 16, "fields": {"name": "Donovan"}}, {"model": "store.artist", "pk": 17, "fields": {"name": "The Bystanders"}}, {"model": "store.artist", "pk": 18, "fields": {"name": "The Supremes"}}, {"model": "store.artist", "pk": 19, "fields": {"name": "The Rolling Stones"}}, {"model": "store.contact", "pk": 1, "fields": {"email": "mala@gmail.com", "name": "C\u00e9line"}}, {"model": "store.contact", "pk": 2, "fields": {"email": "lola@gmailc.om", "name": "lola"}}, {"model": "store.contact", "pk": 3, "fields": {"email": "lola@gmail.com", "name": "C\u00e9line"}}, {"model": "store.contact", "pk": 4, "fields": {"email": "jonathanjeanvoine@gmail.com", "name": "Jonathan Jeanvoine"}}, {"model": "store.contact", "pk": 5, "fields": {"email": "lol@g", "name": "Lola"}}, {"model": "store.contact", "pk": 6, "fields": {"email": "chou@chou.com", "name": "Sia"}}, {"model": "store.contact", "pk": 7, "fields": {"email": "", "name": ""}}, {"model": "store.contact", "pk": 9, "fields": {"email": "hey@you.com", "name": "Ama\u00ebl R\u00e9chin L\u00ea Ky-Huong"}}, {"model": "store.album", "pk": 34, "fields": {"reference": 1, "created_at": "2017-08-09T16:10:46.977Z", "available": true, "title": "All Day and All of the Night", "picture": "http://www.soundstation.dk/images/products/large/17/132117-a.jpg", "artists": [3]}}, {"model": "store.album", "pk": 35, "fields": {"reference": 2, "created_at": "2017-08-09T16:10:46.986Z", "available": false, "title": "Hi Ho Silver Lining", "picture": "http://www.somanyrecordssolittletime.com/wp-content/uploads/jeff-beck-hi-ho-ps.jpg", "artists": [4]}}, {"model": "store.album", "pk": 36, "fields": {"reference": 3, "created_at": "2017-08-09T16:10:46.991Z", "available": false, "title": "Yesterday Man", "picture": "https://ring.cdandlp.com/eddys/photo_grande/115195447.jpg", "artists": [5]}}, {"model": "store.album", "pk": 37, "fields": {"reference": 4, "created_at": "2017-08-09T16:10:46.995Z", "available": true, "title": "Friday On My Mind", "picture": "https://images.recordsale.de/600/600/cdpix/e/easy_beats._the_easybeats-friday_on_my_mind.jpg", "artists": [6]}}, {"model": "store.album", "pk": 38, "fields": {"reference": 5, "created_at": "2017-08-09T16:10:47.001Z", "available": false, "title": "Here Comes the Night", "picture": "https://img.cdandlp.com/2014/10/imgL/117188316.jpg", "artists": [8, 7]}}, {"model": "store.album", "pk": 39, "fields": {"reference": 6, "created_at": "2017-08-09T16:10:47.007Z", "available": true, "title": "Hang On Sloopy", "picture": "https://www.recordsbymail.com/uploads/2-25-16-3/741587.jpg", "artists": [9]}}, {"model": "store.album", "pk": 40, "fields": {"reference": 7, "created_at": "2017-08-09T16:10:47.012Z", "available": false, "title": "I'm Alive", "picture": "https://img.cdandlp.com/2017/02/imgL/118583436.jpg", "artists": [10]}}, {"model": "store.album", "pk": 41, "fields": {"reference": 8, "created_at": "2017-08-09T16:10:47.017Z", "available": true, "title": "Silence Is Golden", "picture": "https://www.recordsbymail.com/uploads/4-6-15-1/727153.jpg", "artists": [11]}}, {"model": "store.album", "pk": 42, "fields": {"reference": 9, "created_at": "2017-08-09T16:10:47.021Z", "available": true, "title": "Tell It Like It Is", "picture": "https://images.recordsale.de/600/600/cdpix/a/aaron_neville-tell_it_like_it_is(1).jpg", "artists": [12]}}, {"model": "store.album", "pk": 43, "fields": {"reference": 10, "created_at": "2017-08-09T16:10:47.026Z", "available": true, "title": "Judy In Disguise (With Glasses)", "picture": "https://images.recordsale.de/600/600/cdpix/j/johnfredhisplayboyband-judyindisguise(withglasses).jpg", "artists": [13]}}, {"model": "store.album", "pk": 44, "fields": {"reference": 11, "created_at": "2017-08-09T16:10:47.030Z", "available": false, "title": "All Over The World", "picture": "https://img.cdandlp.com/2017/03/imgL/118664562.jpg", "artists": [14]}}, {"model": "store.album", "pk": 45, "fields": {"reference": 12, "created_at": "2017-08-09T16:10:47.035Z", "available": false, "title": "To Sir, With Love", "picture": "https://img.cdandlp.com/2016/11/imgL/118373380.jpg", "artists": [15]}}, {"model": "store.album", "pk": 46, "fields": {"reference": 13, "created_at": "2017-08-09T16:10:47.040Z", "available": false, "title": "Sunshine Superman", "picture": "http://2.bp.blogspot.com/-f3YXAB4CIkU/Tpk8_Cl0l8I/AAAAAAAAAOU/dRcKP7Tv5rQ/s400/donovansunshinesuperman.jpg", "artists": [16]}}, {"model": "store.album", "pk": 47, "fields": {"reference": 14, "created_at": "2017-08-09T16:10:47.045Z", "available": true, "title": "98.6", "picture": "http://images.45cat.com/the-bystanders-986-pye-2.jpg", "artists": [17]}}, {"model": "store.album", "pk": 48, "fields": {"reference": 15, "created_at": "2017-08-09T16:10:47.049Z", "available": false, "title": "The Happening", "picture": "http://2.bp.blogspot.com/-ebBCW6bBL2k/UBLN1zSB6hI/AAAAAAAAAHg/7BZotayUC-c/s1600/The+Happening+..jpg", "artists": [18]}}, {"model": "store.album", "pk": 49, "fields": {"reference": 16, "created_at": "2017-08-09T16:10:47.054Z", "available": false, "title": "Jumpin' Jack Flash", "picture": "https://1.bp.blogspot.com/-L1xW7Iwfp3s/WJZo4V6J2lI/AAAAAAAAZ2w/AwEEsZ90vVoHoSNoDu-PYkvFgM1kp5FdgCPcB/s1600/the_rolling_stones-jumpin_jack_flash_s.jpg", "artists": [19]}}, {"model": "store.booking", "pk": 5, "fields": {"created_at": "2017-08-11T16:03:00.384Z", "contacted": false, "album": 36, "contact": 3}}, {"model": "store.booking", "pk": 6, "fields": {"created_at": "2017-08-11T16:42:33.585Z", "contacted": false, "album": 46, "contact": 4}}, {"model": "store.booking", "pk": 9, "fields": {"created_at": "2017-08-11T18:01:06.434Z", "contacted": false, "album": 38, "contact": 6}}, {"model": "store.booking", "pk": 11, "fields": {"created_at": "2017-08-12T19:45:23.128Z", "contacted": false, "album": 44, "contact": 9}}] -------------------------------------------------------------------------------- /store/forms.py: -------------------------------------------------------------------------------- 1 | from django.forms import ModelForm, TextInput, EmailInput 2 | from django.forms.utils import ErrorList 3 | 4 | from .models import Contact 5 | 6 | 7 | class ParagraphErrorList(ErrorList): 8 | def __str__(self): 9 | return self.as_divs() 10 | def as_divs(self): 11 | if not self: return '' 12 | return '
%s
' % e for e in self]) 13 | 14 | class ContactForm(ModelForm): 15 | class Meta: 16 | model = Contact 17 | fields = ["name", "email"] 18 | widgets = { 19 | 'name': TextInput(attrs={'class': 'form-control'}), 20 | 'email': EmailInput(attrs={'class': 'form-control'}) 21 | } 22 | -------------------------------------------------------------------------------- /store/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/management/__init__.py -------------------------------------------------------------------------------- /store/management/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/management/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /store/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/management/commands/__init__.py -------------------------------------------------------------------------------- /store/management/commands/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/management/commands/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /store/management/commands/__pycache__/add_albums.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/management/commands/__pycache__/add_albums.cpython-36.pyc -------------------------------------------------------------------------------- /store/management/commands/_private.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/management/commands/_private.py -------------------------------------------------------------------------------- /store/management/commands/add_albums.py: -------------------------------------------------------------------------------- 1 | import os 2 | import logging as lg 3 | 4 | import yaml 5 | from django.core.exceptions import ObjectDoesNotExist 6 | from django.core.management.base import BaseCommand, CommandError 7 | from store.models import Album, Artist 8 | 9 | 10 | lg.basicConfig(level=lg.DEBUG) 11 | 12 | 13 | class Command(BaseCommand): 14 | help = 'Add albums to the database from a yml file located in data/' 15 | 16 | def handle(self, *args, **options): 17 | reference = 0 18 | # open file with data 19 | directory = os.path.dirname(os.path.dirname(__file__)) 20 | path = os.path.join(directory, 'data', 'albums.yml') 21 | with open(path, 'r') as file: 22 | data = yaml.load(file) 23 | albums = data['albums'] 24 | for album in albums: 25 | # Create artists 26 | artists = [] 27 | for artist in album['artists']: 28 | try: 29 | stored_artist = Artist.objects.get(name=artist) 30 | lg.info('Artist found: %s'%stored_artist) 31 | except ObjectDoesNotExist: 32 | stored_artist = Artist.objects.create(name=artist) 33 | lg.info('Artist created: %s'%stored_artist) 34 | artists.append(stored_artist) 35 | # Find or create album 36 | try: 37 | stored_album = Album.objects.get(title=album['title']) 38 | lg.info('Album found: %s'%stored_album.title) 39 | except ObjectDoesNotExist: 40 | reference += 1 41 | album = Album.objects.create( 42 | title=album['title'], 43 | reference=reference, 44 | picture=album['picture'] 45 | ) 46 | album.artists = artists 47 | lg.info('New album: %s'%stored_artist) 48 | -------------------------------------------------------------------------------- /store/management/data/albums.yml: -------------------------------------------------------------------------------- 1 | albums: 2 | - title: All Day and All of the Night 3 | artists: 4 | - The Kinks 5 | picture: "http://www.soundstation.dk/images/products/large/17/132117-a.jpg" 6 | - title: Hi Ho Silver Lining 7 | artists: 8 | - Jeff Beck 9 | The Kinks 10 | Chris Andrews 11 | picture: "http://www.somanyrecordssolittletime.com/wp-content/uploads/jeff-beck-hi-ho-ps.jpg" 12 | - title: Yesterday Man 13 | artists: 14 | - Chris Andrews 15 | picture: "https://ring.cdandlp.com/eddys/photo_grande/115195447.jpg" 16 | - title: Friday On My Mind 17 | artists: 18 | - The Easybeats 19 | Lulu 20 | picture: "https://images.recordsale.de/600/600/cdpix/e/easy_beats._the_easybeats-friday_on_my_mind.jpg" 21 | - title: Here Comes the Night 22 | artists: 23 | - Them 24 | - Van Morrison 25 | picture: "https://img.cdandlp.com/2014/10/imgL/117188316.jpg" 26 | - title: Hang On Sloopy 27 | artists: 28 | - The McCoys 29 | picture: "https://www.recordsbymail.com/uploads/2-25-16-3/741587.jpg" 30 | - title: I'm Alive 31 | artists: 32 | - The Hollies 33 | picture: "https://img.cdandlp.com/2017/02/imgL/118583436.jpg" 34 | - title: Silence Is Golden 35 | artists: 36 | - The Tremeloes 37 | picture: "https://www.recordsbymail.com/uploads/4-6-15-1/727153.jpg" 38 | - title: Tell It Like It Is 39 | artists: 40 | - Aaron Neville 41 | picture: "https://images.recordsale.de/600/600/cdpix/a/aaron_neville-tell_it_like_it_is(1).jpg" 42 | - title: Judy In Disguise (With Glasses) 43 | artists: 44 | - John Fred and His Playboy Band 45 | picture: "https://images.recordsale.de/600/600/cdpix/j/johnfredhisplayboyband-judyindisguise(withglasses).jpg" 46 | - title: All Over The World 47 | artists: 48 | - Francoise Hardy 49 | picture: "https://img.cdandlp.com/2017/03/imgL/118664562.jpg" 50 | - title: To Sir, With Love 51 | artists: 52 | - Lulu 53 | picture: "https://img.cdandlp.com/2016/11/imgL/118373380.jpg" 54 | - title: Sunshine Superman 55 | artists: 56 | - Donovan 57 | picture: "http://2.bp.blogspot.com/-f3YXAB4CIkU/Tpk8_Cl0l8I/AAAAAAAAAOU/dRcKP7Tv5rQ/s400/donovansunshinesuperman.jpg" 58 | - title: '98.6' 59 | artists: 60 | - The Bystanders 61 | picture: "http://images.45cat.com/the-bystanders-986-pye-2.jpg" 62 | - title: The Happening 63 | artists: 64 | - The Supremes 65 | picture: "http://2.bp.blogspot.com/-ebBCW6bBL2k/UBLN1zSB6hI/AAAAAAAAAHg/7BZotayUC-c/s1600/The+Happening+..jpg" 66 | - title: Jumpin' Jack Flash 67 | artists: 68 | - The Rolling Stones 69 | picture: "https://1.bp.blogspot.com/-L1xW7Iwfp3s/WJZo4V6J2lI/AAAAAAAAZ2w/AwEEsZ90vVoHoSNoDu-PYkvFgM1kp5FdgCPcB/s1600/the_rolling_stones-jumpin_jack_flash_s.jpg" 70 | -------------------------------------------------------------------------------- /store/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.3 on 2017-08-03 15:42 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | initial = True 12 | 13 | dependencies = [ 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='Album', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('reference', models.IntegerField(null=True)), 22 | ('created_at', models.DateTimeField(auto_now_add=True)), 23 | ('available', models.BooleanField(default=True)), 24 | ('title', models.CharField(max_length=200)), 25 | ('picture', models.TextField()), 26 | ], 27 | ), 28 | migrations.CreateModel( 29 | name='Artist', 30 | fields=[ 31 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 32 | ('name', models.CharField(max_length=200, unique=True)), 33 | ], 34 | ), 35 | migrations.CreateModel( 36 | name='Booking', 37 | fields=[ 38 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 39 | ('created_at', models.DateTimeField(auto_now_add=True)), 40 | ('contacted', models.BooleanField(default=False)), 41 | ('album', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='store.Album')), 42 | ], 43 | ), 44 | migrations.CreateModel( 45 | name='Contact', 46 | fields=[ 47 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 48 | ('email', models.EmailField(max_length=100)), 49 | ('name', models.CharField(max_length=200)), 50 | ], 51 | ), 52 | migrations.AddField( 53 | model_name='booking', 54 | name='contact', 55 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.Contact'), 56 | ), 57 | migrations.AddField( 58 | model_name='album', 59 | name='artists', 60 | field=models.ManyToManyField(blank=True, related_name='albums', to='store.Artist'), 61 | ), 62 | ] 63 | -------------------------------------------------------------------------------- /store/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/migrations/__init__.py -------------------------------------------------------------------------------- /store/migrations/__pycache__/0001_initial.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/migrations/__pycache__/0001_initial.cpython-36.pyc -------------------------------------------------------------------------------- /store/migrations/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/migrations/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /store/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | 4 | class Artist(models.Model): 5 | name = models.CharField('nom', max_length=200, unique=True) 6 | 7 | class Meta: 8 | verbose_name = "artiste" 9 | 10 | def __str__(self): 11 | return self.name 12 | 13 | 14 | class Contact(models.Model): 15 | email = models.EmailField('email', max_length=100) 16 | name = models.CharField('nom', max_length=200) 17 | 18 | class Meta: 19 | verbose_name = "prospect" 20 | 21 | def __str__(self): 22 | return self.name 23 | 24 | 25 | class Album(models.Model): 26 | reference = models.IntegerField('référence', null=True) 27 | created_at = models.DateTimeField('date de création', auto_now_add=True) 28 | available = models.BooleanField('disponible', default=True) 29 | title = models.CharField('titre', max_length=200) 30 | picture = models.TextField("URL de l'image", ) 31 | artists = models.ManyToManyField(Artist, related_name='albums', blank=True) 32 | 33 | class Meta: 34 | verbose_name = "disque" 35 | 36 | def __str__(self): 37 | return self.title 38 | 39 | 40 | class Booking(models.Model): 41 | created_at = models.DateTimeField("date d'envoi", auto_now_add=True) 42 | contacted = models.BooleanField('demande traitée ?', default=False) 43 | album = models.OneToOneField(Album) 44 | contact = models.ForeignKey(Contact, on_delete=models.CASCADE) 45 | 46 | class Meta: 47 | verbose_name = "réservation" 48 | 49 | def __str__(self): 50 | return self.contact.name 51 | -------------------------------------------------------------------------------- /store/static/store/css/business-casual.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Start Bootstrap - Business Casual (http://startbootstrap.com/) 3 | * Copyright 2013-2016 Start Bootstrap 4 | * Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap/blob/gh-pages/LICENSE) 5 | */ 6 | 7 | body { 8 | font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif; 9 | background: url('../img/theboatthatrocked.jpg') no-repeat center center fixed; 10 | -webkit-background-size: cover; 11 | -moz-background-size: cover; 12 | background-size: cover; 13 | -o-background-size: cover; 14 | } 15 | 16 | h1, 17 | h2, 18 | h3, 19 | h4, 20 | h5, 21 | h6 { 22 | text-transform: uppercase; 23 | font-family: "Josefin Slab","Helvetica Neue",Helvetica,Arial,sans-serif; 24 | font-weight: 700; 25 | letter-spacing: 1px; 26 | } 27 | 28 | p { 29 | font-size: 1.25em; 30 | line-height: 1.6; 31 | color: #000; 32 | } 33 | 34 | hr { 35 | max-width: 400px; 36 | border-color: #999999; 37 | } 38 | 39 | .brand, 40 | .address-bar { 41 | display: none; 42 | } 43 | 44 | .navbar-brand { 45 | text-transform: uppercase; 46 | font-weight: 900; 47 | letter-spacing: 2px; 48 | } 49 | 50 | .navbar-nav { 51 | text-transform: uppercase; 52 | font-weight: 400; 53 | letter-spacing: 3px; 54 | } 55 | 56 | .img-full { 57 | min-width: 100%; 58 | } 59 | 60 | .brand-before, 61 | .brand-name { 62 | text-transform: capitalize; 63 | } 64 | 65 | .brand-before { 66 | margin: 15px 0; 67 | } 68 | 69 | .brand-name { 70 | margin: 0; 71 | font-size: 4em; 72 | } 73 | 74 | .tagline-divider { 75 | margin: 15px auto 3px; 76 | max-width: 250px; 77 | border-color: #999999; 78 | } 79 | 80 | .box { 81 | margin-bottom: 20px; 82 | padding: 30px 15px; 83 | background: #fff; 84 | background: rgba(255,255,255,0.9); 85 | } 86 | 87 | .intro-text { 88 | text-transform: uppercase; 89 | font-size: 1.25em; 90 | font-weight: 400; 91 | letter-spacing: 1px; 92 | } 93 | 94 | .img-border { 95 | float: none; 96 | margin: 0 auto 0; 97 | border: #999999 solid 1px; 98 | } 99 | 100 | .img-left { 101 | float: none; 102 | margin: 0 auto 0; 103 | } 104 | 105 | footer { 106 | background: #fff; 107 | background: rgba(255,255,255,0.9); 108 | } 109 | 110 | footer p { 111 | margin: 0; 112 | padding: 50px 0; 113 | } 114 | 115 | @media screen and (min-width:768px) { 116 | .brand { 117 | display: inherit; 118 | margin: 0; 119 | padding: 30px 0 10px; 120 | text-align: center; 121 | text-shadow: 1px 1px 2px rgba(0,0,0,0.5); 122 | font-family: "Josefin Slab","Helvetica Neue",Helvetica,Arial,sans-serif; 123 | font-size: 5em; 124 | font-weight: 700; 125 | line-height: normal; 126 | color: #fff; 127 | } 128 | 129 | .top-divider { 130 | margin-top: 0; 131 | } 132 | 133 | .img-left { 134 | float: left; 135 | margin-right: 25px; 136 | } 137 | 138 | .address-bar { 139 | display: inherit; 140 | margin: 0; 141 | padding: 0 0 40px; 142 | text-align: center; 143 | text-shadow: 1px 1px 2px rgba(0,0,0,0.5); 144 | text-transform: uppercase; 145 | font-size: 1.25em; 146 | font-weight: 400; 147 | letter-spacing: 3px; 148 | color: #fff; 149 | } 150 | 151 | .navbar { 152 | border-radius: 0; 153 | } 154 | 155 | .navbar-header { 156 | display: none; 157 | } 158 | 159 | .navbar { 160 | min-height: 0; 161 | } 162 | 163 | .navbar-default { 164 | border: none; 165 | background: #fff; 166 | background: rgba(255,255,255,0.9); 167 | } 168 | 169 | .nav>li>a { 170 | padding: 35px; 171 | } 172 | 173 | .navbar-nav>li>a { 174 | line-height: normal; 175 | } 176 | 177 | .navbar-nav { 178 | display: table; 179 | float: none; 180 | margin: 0 auto; 181 | table-layout: fixed; 182 | font-size: 1.25em; 183 | } 184 | } 185 | 186 | @media screen and (min-width:1200px) { 187 | .box:after { 188 | content: ''; 189 | display: table; 190 | clear: both; 191 | } 192 | } 193 | 194 | /* CUSTOM */ 195 | .brand a { 196 | color: white; 197 | text-decoration: none; 198 | } 199 | 200 | .brand a:hover { 201 | color: #999; 202 | text-decoration: none; 203 | } 204 | 205 | .artist_name { 206 | font-size: 20px; 207 | font-weight: normal; 208 | } 209 | 210 | .intro-text { 211 | font-size: 40px; 212 | font-weight: 300; 213 | } 214 | 215 | .detail-separator { 216 | padding-bottom: 25px; 217 | } 218 | 219 | .clearfix { 220 | padding-bottom: 40px; 221 | } 222 | 223 | #search_form { 224 | width: 43%; 225 | margin: auto; 226 | text-align: center; 227 | } 228 | 229 | .form-group.has-feedback .form-control { 230 | padding: 6px 5px; 231 | color: red; 232 | } 233 | 234 | .errorlist { 235 | margin: 10px auto; 236 | } 237 | 238 | .errorlist .error { 239 | color: red; 240 | } 241 | -------------------------------------------------------------------------------- /store/static/store/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/static/store/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /store/static/store/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/static/store/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /store/static/store/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/static/store/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /store/static/store/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/static/store/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /store/static/store/img/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/static/store/img/bg.jpg -------------------------------------------------------------------------------- /store/static/store/img/intro-pic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/static/store/img/intro-pic.jpg -------------------------------------------------------------------------------- /store/static/store/img/slide-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/static/store/img/slide-1.jpg -------------------------------------------------------------------------------- /store/static/store/img/slide-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/static/store/img/slide-2.jpg -------------------------------------------------------------------------------- /store/static/store/img/slide-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/static/store/img/slide-3.jpg -------------------------------------------------------------------------------- /store/static/store/img/theboatthatrocked.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oc-courses/deployez_une_application_django/8b7c3dd9ba19eb115ee6b9de66361354eb1647fb/store/static/store/img/theboatthatrocked.jpg -------------------------------------------------------------------------------- /store/static/store/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.7 (http://getbootstrap.com) 3 | * Copyright 2011-2016 Twitter, Inc. 4 | * Licensed under the MIT license 5 | */ 6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jt |
I'm lost. I'm like a king without a throne.
4 |L'album que vous demandez est parti écouter Sarah Vaughan à la suite d'une rupture sentimentale.
5 |Nous partons à l'instant même le secourir !
6 |Oops ! I did it again.
7 |Une erreur s'est produite. Nous sommes actuellement en liaison directe avec Britney pour investiguer sur les causes du drame.
8 |{{ artists_name }}
14 |Demandez-nous de mettre de côté {{ album_title }} et venez le chercher dès demain en magasin !
18 | 34 | 35 | {% if errors %} 36 |{{ artist.name }}
25 | {% endfor %} 26 |L'album {{ album_title }} vient d'être retiré des rayonnages. Une main délicate a déposé votre nom sur sa couverture et l'a rangé en vous attendant. Dépêchez-vous ! {{ album_title }} trépigne d'impatience et chante déjà vos louanges.
9 |