![](static/hkis-home.png)
::: notes
Remercier ceux qui nous hébergent.
# HackInScience
## Hackinscience
Julien Palard
Paris.Py #16
## 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.
(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[0-9]+)/(?P[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