talks/2018-paris.py-16-hackinscie...

351 lines
6.5 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

![](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