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