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

6.5 KiB

::: 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.

::: 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

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

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

Django view

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

Need an API now

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

::: 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

from django.contrib import admin
from website.models import Answer, Exercise

admin.site.register(Answer)
admin.site.register(Exercise)

Admin interface

Admin interface

::: notes

We're using markdown to redact exercises.

Admin interface

::: 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:

application = ProtocolTypeRouter(
    {"websocket": AuthMiddlewareStack(
        URLRouter(website.routing.websocket_urlpatterns))}
)

and

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?