cours_02.md 5.59 KB
Newer Older
Bonnegent's avatar
plan ok  
Bonnegent committed
1
2
% Django par la pratique #02
% Sébastien Bonnegent
Bonnegent Sebastien's avatar
cours 2    
Bonnegent Sebastien committed
3
4
5
6
7
8
9
10
11
12
13
14
% version 2018

# Interface d'administration

## Prérequis

### garage/models.py
- Garage
- Vehicule
- AFaire
- Entretien

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
15
16
17
18
19
20
### un venv
~~~
$ source /opt/venv/django/bin/activate
$ pipenv run ...
~~~

Bonnegent Sebastien's avatar
cours 2    
Bonnegent Sebastien committed
21
22
23
## Développement
### Lancement du serveur de développement
~~~
24
$ ./manage.py runserver
Bonnegent Sebastien's avatar
cours 2    
Bonnegent Sebastien committed
25
26
27
28
Performing system checks...

System check identified no issues (0 silenced).
September 28, 2017 - 13:29:48
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
29
Django version 1.11, using settings 'conf.settings'
Bonnegent Sebastien's avatar
cours 2    
Bonnegent Sebastien committed
30
31
32
33
34
35
36
37
38
39
40
Starting development server at http://127.0.0.1:8000/
~~~

## Consultation

### Adresse
- http://localhost:8000/
- http://localhost:8000/admin/

### Création d'un compte administrateur
~~~
41
$ ./manage.py createsuperuser
Bonnegent Sebastien's avatar
cours 2    
Bonnegent Sebastien committed
42
43
44
45
46
47
~~~

## Ajout de nos classes

### garage/admin.py
~~~python
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
48
49
from .models import Garage, Vehicule, AFaire, \
                    Entretien
Bonnegent Sebastien's avatar
cours 2    
Bonnegent Sebastien committed
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

admin.site.register(Garage)
admin.site.register(Vehicule)
admin.site.register(AFaire)
admin.site.register(Entretien)
~~~

### http://localhost:8000/admin/
- rafraichir l'affichage
- créer des objets dans les différentes classes

## Personnalisation
### garage/admin.py
~~~python
class EntretienAdmin(admin.ModelAdmin):
  list_display = ('vehicule', 'kms', 'date', 'montant')
  date_hierarchy = 'date'
  # ordering = ['date'] >> class Meta
  search_fields = ['vehicule__marque',
                   'vehicule__modele']

admin.site.register(Entretien, EntretienAdmin)
~~~
Bonnegent's avatar
plan ok  
Bonnegent committed
73
74
75

# MVC

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
76
## Modèle Vue Contrôleur (~MTV)
Bonnegent's avatar
plan ok  
Bonnegent committed
77
78

### Modèle
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
79
- garage/models.py
Bonnegent's avatar
plan ok  
Bonnegent committed
80
81
82
83
84
85
- logique métier
- intelligence

. . .

### Vue
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
86
- garage/templates
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
87
- garage/views.py
Bonnegent's avatar
plan ok  
Bonnegent committed
88
89
90
91
92

. . .

### Contrôleur
- Django
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
93
- garage/urls.py
Bonnegent's avatar
plan ok  
Bonnegent committed
94

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
95
## Définition
Bonnegent's avatar
plan ok  
Bonnegent committed
96

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
97
### Wikipedia
Bonnegent's avatar
plan ok  
Bonnegent committed
98
~~~
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
99
https://fr.wikipedia.org/wiki/Modèle-vue-contrôleur
Bonnegent's avatar
plan ok  
Bonnegent committed
100
101
~~~

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
102
103
# 1er page web
## Vue
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
104
105
106
107
108
109
110
111
112
113
### garage/views.py
~~~python
from django.http import HttpResponse


def home(request):
    """Page d'accueil"""
    return HttpResponse('ça marche !')
~~~

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
114
115
116
117
## Routage d'URLs
### conf/urls.py
~~~python
from django.contrib import admin
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
118
from django.urls import path, include
Bonnegent's avatar
plan ok  
Bonnegent committed
119

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
120
121
urlpatterns = [
    path('admin/', admin.site.urls),
Bonnegent's avatar
plan ok  
Bonnegent committed
122
123
~~~

Bonnegent's avatar
Bonnegent committed
124
125
. . .

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
126
127
128
~~~python
    path('', include('garage.urls')),
]
Bonnegent's avatar
plan ok  
Bonnegent committed
129
130
~~~

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
131
132
133
134
135
## Routage d'URLs #2
### garage/urls.py
~~~python
from django.urls import path
from . import views
Bonnegent's avatar
plan ok  
Bonnegent committed
136

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
137
138
139
urlpatterns = [
    path('', views.home, name='home'),
]
Bonnegent's avatar
plan ok  
Bonnegent committed
140
141
~~~

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
142
143
## Frontend (JS mais pas trop)
### Bootstrap
Bonnegent's avatar
Bonnegent committed
144

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
145
146
- https://pypi.org/project/django-bootstrap-static/
- https://getbootstrap.com/
Bonnegent's avatar
Bonnegent committed
147

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
148
149
150
### Installation
~~~
$ mkdir -p garage/templates/garage
Bonnegent's avatar
Bonnegent committed
151
152
~~~

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
### conf/settings.py
~~~python
INSTALLED_APPS = [
    # ...
    'bootstrap',
    'fontawesome',
]
~~~

## garage/templates/garage/home.html
### head (v1)
~~~html
{% load static %}
<!doctype html>
<html lang="fr"><head>
<meta charset="utf-8">
<meta name="viewport"
   content="width=device-width, initial-scale=1, 
            shrink-to-fit=no">
<title>Garage</title>
<link rel="stylesheet"
   href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<script defer 
   src="{% static 'fontawesome/js/fontawesome-all.min.js' %}">
</script></head>
~~~
Bonnegent's avatar
Bonnegent committed
179

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
180
## garage/templates/garage/home.html
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
181
### body (v1)
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
182
183
184
185
186
187
188
189
190
191
192
193
194
195
~~~html
<body>
{% block content %}<p>Bienvenue !</p>{% endblock %}

<script src="{% static 'bootstrap/js/jquery.min.js' %}">
</script>
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}">
</script>
</body>
</html>
~~~

## Modifier la vue
### garage/views.py
Bonnegent's avatar
Bonnegent committed
196

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
197
198
~~~python
from django.shortcuts import render
Bonnegent's avatar
Bonnegent committed
199

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
200
201
202
203
204
def home(request):
   return render(request, 'garage/home.html', {}) 
~~~

## garage/templates/garage/home.html
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
205
### avec navbar (v2)
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
206
207
208
209
210
211
212
213
214
215
216
217
218
219
~~~html
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
  <a class="navbar-brand" href="/">Garage</a>
  <button class="navbar-toggler" type="button" ...
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" ...
    <div class="navbar-nav">
      <a class="nav-item nav-link active" href="/">Accueil</a>
      <a class="nav-item nav-link" href="#">Véhicules</a>
    </div>
  </div>
</nav>
~~~
Bonnegent's avatar
Bonnegent committed
220

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
221
222
223
224
225
226
227
228
229
230
## garage/templates/garage/home.html
### avec navbar (v3)
~~~
{% if user.is_authenticated %}
...
    {% if user.is_staff %}
    ...
    {% endif %}
{% endif %}
~~~
Bonnegent's avatar
Bonnegent committed
231

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
232
## Connexion des utilisateurs
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
233
234
235
236
237
### conf/urls.py
~~~python
# ...
path('accounts/', include('django.contrib.auth.urls')),
# ...
Bonnegent's avatar
plan ok  
Bonnegent committed
238
~~~
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
239

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
### garage/templates/registration/login.html
- le template doit être présent

### garage/urls.py
~~~python
from django.contrib.auth.decorators import login_required
~~~

## Afficher la liste des garages
\center\includegraphics[height=5cm]{supports_cours_02/get_url.png} 

## Les vues génériques (views)
### garage/views.py
~~~python
from django.views.generic import ListView
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
255
from .models import Garage
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294

class GaragesListView(ListView):
    model = Garage

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['menu_garages'] = 'active'
        return context
~~~

## Les vues génériques (templates)
### garage/templates/garage/garage_list.html
~~~python
{% extends "garage/home.html" %}
{% load staticfiles %}
{% block content %}
...
~~~

## Les vues génériques (urls)
### garage/urls.py
~~~python
from django.contrib.auth.decorators import login_required

app_name = "garage"
...
    path('garages/',
         login_required(views.GaragesListView.as_view()),
         name='garages'),
...
~~~

## Les vues génériques (templates)
### garage/templates/garage/home.html
~~~python
<li class="nav-item {{ menu_garages }}">
    <a class="nav-link" href="{% url 'garage:garages' %}">Garages</a>
</li>
~~~
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
295

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
296
## Bonnes pratiques pour la partie Front
Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
297

Bonnegent Sebastien's avatar
Bonnegent Sebastien committed
298
299
300
- Pensez à utiliser le mode développeur (F12)
- CDN, attention aux dépendances extérieures
- limité le chargement des JS