Import: Paris.py #16

This commit is contained in:
Julien Palard 2023-02-10 15:29:09 +01:00
parent c5220012e0
commit ee621768e2
Signed by: mdk
GPG Key ID: 0EFC1AC1006886F8
10 changed files with 350 additions and 0 deletions

View File

@ -0,0 +1,350 @@
![](static/hkis-home.png)
::: notes
Remercier ceux qui nous hébergent.
# HackInScience
<!-- .slide: data-background="static/background.jpg" -->
## Hackinscience
<br/>
<b>Julien Palard</b>
<tt>Paris.Py #16</tt>
## Julien Palard
- Python core dev / freelance
- CPython documentation translator (french only)
- Python teacher/coach, at
- Makina Corpus
- Center for Research and Interdisciplinarity
- Sup'Internet
- …
julien@python.org, @sizeof, https://mdk.fr
# HackInScience
Back in 2015, we started a project with the CRI of Paris Descartes: A
one-week intensive Python class. ![](descartes-and-cri.jpg)
::: notes
"The Center for Research and Interdisciplinarity" en anglais.
- Ouvert à tous : élèves de l'université, chercheurs, public.
## Pedagogy
We were aiming for 50 students per week, so we had to adapt,
we needed:
- A short Python introduction (slides and a teacher).
- Lots of exercises, sorted by difficulty.
- A bot to correct exercises, live.
- 2 to 3 highly available teachers in the room.
- Short optional lessons about very specific topics.
- Rules, teaching best practices.
::: notes
Rules like: never touch a student keyboard: they're here to learn.
## 2015: Focus on content
We started by focusing on exercises (needed to give a course) and the
correction bot (needed to scale).
Workflow from a student point of view:
- Clone the exercise repo
- Do exercises
- git push
- Receive a mail with the correction
::: notes
It was crude, but it worked.
We automated exercises corrections (like exercises unit tests) using a
Python script.
## 2016: Focus on confort
Antoine Angot developped a website so students do no longer needed to
use git. Emails were no longer needed, which is nice too.
::: notes
Thx bro!
Turns out that teaching git took a lot of time over teaching Python...
And emails were easily marked as spam even with SPF and DKIM configured properly.
## 2017: Focus on content, again
The year to enhance existing parts, to rely on them, this is also the
year of... many repositories:
- One for the website
- One for the exercises (markdown files)
- One for our internal documentation
- One for the correction bot
- One for the ansible playbook
::: notes
Exercises had a check.py and a solution.py
Internal documentation == teaching best practices.
## 2018: Migrating to Django
Jérôme Schneider started to migrate the website to Django.<br/>
(So we could modify it more easily.)
::: notes
Thx bro :)
A nice part was templates: the syntax was almost the same.
# Show me the code!
So what is it now? 181 lines of Python (first fully working version), it
should fit in a few slides ;)
::: notes
Today it's more like 700 lines of code, mainly little tweaks
and personalisation.
# Django models
```python
class Exercise(models.Model):
title = models.CharField(max_length=255)
check = models.TextField()
solution = models.TextField()
wording = models.TextField()
```
::: notes
Already know Django? Focus on the content.
## Django models
Helps in generating:
- DB migrations;
- Admin pages;
- Forms;
- Views (Using class-based views);
- API (Using DRF);
- Queries ("ORM" as humans say).
::: notes
A Django Model makes the code aware of the database structure.
- Autocompletion
- ...
# Django view
```python
class ExerciseListView(LoginRequiredMixin, ListView):
model = Exercise
template_name = "hkis/exercises.html"
```
::: notes
How to read this Mixin thing?
Read: ExerciseListView inherite first from LoginRequiredMixin, then on ListView.
So LoginRequiredMixin can place its method before ListView, like intercepting them.
## Django view
![](static/hkis-exercises.png)
## Django view
```python
class ExerciseView(LoginRequiredMixin, DetailView):
model = Exercise
template_name = "hkis/exercise.html"
def get_context_data(self, **kwargs):
"""Add student answers.
"""
context = super().get_context_data(**kwargs)
context["answers"] = self.object.answers.filter(
user=self.request.user
).order_by("-id")
return context
```
## Django view
![](static/hkis-exercise.png)
# Need an API now
```python
class ExerciseSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Exercise
fields = '__all__'
class ExerciseViewSet(viewsets.ModelViewSet):
queryset = Exercise.objects.all()
serializer_class = ExerciseSerializer
router = routers.DefaultRouter()
router.register('exercises', ExerciseViewSet)
```
::: notes
Why DRF use a router? Because there's many views in a ViewSet.
## Need an API now
![](static/hkis-api.png)
::: notes
A nice feature: The API replies with HTML when asked for, so
it's browsable using a web browser.
# Need an admin interface now
```python
from django.contrib import admin
from website.models import Answer, Exercise
admin.site.register(Answer)
admin.site.register(Exercise)
```
## Admin interface
![](static/hkis-admin.png)
## Admin interface
![](static/hkis-admin-markdown.png)
::: notes
We're using markdown to redact exercises.
## Admin interface
![](static/hkis-admin-check.png)
::: notes
This is the Python script used to check an exercise.
# We need lives updates, now!
So when a student submit an answer, he gets a correction as soon as possible.
We can use `Django Channels` for this.
## Django Channels
Need first to setup some kind of high level router:
```python
application = ProtocolTypeRouter(
{"websocket": AuthMiddlewareStack(
URLRouter(website.routing.websocket_urlpatterns))}
)
```
and
```python
websocket_urlpatterns = [
url(
r"^ws/answers/(?P<user_id>[0-9]+)/(?P<exercise_id>[0-9]+)/$",
consumers.AnswerConsumer,
)
]
```
## Django Channels
Note the `ws/` prefix, it's usefull once in production:
- nginx → gunicorn, for HTTP
- nginx → daphne, for websockets
## Django Channels
We're disambiguating it nginx side:
```
location /ws {
proxy_pass http://unix:/run/hkis-website/daphne.sock;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location / {
proxy_pass http://unix:/run/hkis-website/website.sock;
proxy_set_header Host $host;
}
```
# The future
Display exercises as a tree, with subjects like datascience, web,
low-level, and so on as group of leafs of the tree.
::: notes
So one could navigate to its preferred subject.
# Questions?
- julien@python.org
- Twitter: @sizeof
- IRC: mdk on #python-fr (freenode)
- https://mdk.fr
- https://hackinscience.org

BIN
static/hkis-CRI.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
static/hkis-admin-check.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
static/hkis-admin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
static/hkis-api.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
static/hkis-exercise.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
static/hkis-exercises.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
static/hkis-home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 KiB

BIN
static/hkis-stats.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB