Day 2 Lightning Talks

This video features Dr. Russell Keith-Magee at DjangoCon Europe 2019 in Copenhagen, Denmark.

Day 2 Lightning Talks
0:33:00
Published April 23, 2019
328 views

Lightning talk host: Russell Keith-Magee, https://twitter.com/freakboy3742

Lightning talk 1: ...
Lightning talk 2: ...
Lightning talk 3: ...
Lightning talk 4: ...
Lightning talk 5: ...

Summary

The lightning talks cover practical Django and Python techniques alongside community projects. They recommend keeping Django configuration in environment variables, organized by setting groups and accessed with tools such as django-environ; adding django-stubs and mypy to catch incorrect types across models, relations, querysets, and settings; and using wrapper objects, model fields, logging formatters, and template tags to redact personal data by default. Other speakers describe the small acts of kindness behind the Django community, efforts by Python Scholars Namibia to expand access to computers and training, and a cautious pattern for storing request-wide state with thread-local storage without leaking data between requests.

Key takeaways

  • Keep secrets and environment-specific values out of hard-coded Django settings, use environment variables, and organize settings by functional groups rather than deployment environment.
  • django-stubs and mypy can type-check Django models, relations, settings, query results, and Django REST framework code, though the stubs still need contributions and wider testing.
  • Privacy can be applied by default in an existing Django application by wrapping personal data, controlling its representation through context managers, and redacting it in logs and templates.
  • Small gestures such as sharing stroopwafels or sending appreciation messages can create happiness and strengthen open-source communities.
  • Python Scholars Namibia is expanding coding clubs, computer access, training days, and partnerships that provide computer labs to schools, and welcomes mentors and donations.
  • Request-wide state can be stored with thread-local storage and set and cleared in middleware, but it remains indirect state and must be used sparingly and never confused with safe global state.

Summarised automatically from the transcript.

Transcript

5,361 words · auto-generated Show

Automatically transcribed, so expect mistakes in names and technical terms.

0:02

Speaker 1: It's uh handling sensitive data like database passwords, tokens to third party APIs, etc. It's also sharing settings between your team members and as we all know uh Django settings is a regular Python code so it could have some tricky and non-obvious logic. Uh there are different approaches uh to sell uh to solve these issues, so let's briefly uh talk about the most popular ones. So settings local approach, it's maybe the most simplest and the most uh older uh thing. So uh you split your settings to uh base settings in settings. py and environment specific settings to settings local. py.

0:48

Speaker 1: This approach partially solves issue with sensitive data, uh, but still it has a lot of disadvantages. Uh so The next approach is uh separate settings file for each environment. Uh with this approach you uh separate uh your settings by environments till you have this base file So it's like an extension of previous uh method. And it's solved this issue with different environments there in version control system. and it's easy to share uh settings between developers, but still you need somehow handle secret mm secret data and still you have this inheritance. The next approach is uh

1:34

Speaker 1: environment variables. And this is just some basic example and has some issues, so let's have a look on advanced example. Um instead of using OS. environ uh directly it's better to write some uh wrapper and to uh handle k error and also you can add their default values and type conversion. But it's better to use a third party application. Uh we will talk about uh it uh later in several slides. Uh so this approach has a lot of uh advantages. Uh finally we have configuration uh separate from code. You have environment parity between all your servers, there is no inheritance, and also there is a theoretical grounding for using environment variables for configuration.

2:27

Speaker 1: It's 12 factors. So 12 factors, it's a collection of recommendations to build uh web apps uh to be easily deployed and scale in cloud. It was created by Heroku, a well known cloud uh hosting provider. And in terms of this talk, we are interested in configuration factor, which literally says that we need to use environment variables for this. So if you're not familiar with 12 factor, I strongly recommend you to check their website. They have really clear explanations for each factor and architecture all in all. And now let's go back to the tooling and we found that uh Jenga Environ it's a very convenient up.

3:12

Speaker 1: It has a really nice API that handles all type conversion, uh default values, etc. So let's have a look on examples. That's how your settings look before. That's how they look after applying Django Environ. So the code became clearer and more readable. Please check this up. Several words about structure. We recommend to split your settings, but not by environment, but by groups. And this case you can differentiate it from Django, third party, and your custom settings And if your uh project uh will be growing, you can implement each of this file as a package and split it more granularly.

4:01

Speaker 1: And uh as we all know, uh naming variables is the most hardest part of the development. So this work as settings too. We cannot imply on Django or third party settings, but we can follow these simple rules for our custom settings. So let's give them uh meanful names, uh use prefix uh with a project name for our custom settings and write descriptions. So Let's quickly summarize keep environ uh keep settings in environment, uh don't hard code, uh split settings into group and follow naming conventions. This is the link to slides and other resources. Also, please check article on our blog site. Thank you.

4:53

Speaker 2: Thank you very much, Alexander. Uh our next speaker is Seth. Seth, you can jump up on stage and get ready. Um so Well, I I arrived in in uh Denmark for the first time uh on Tuesday and uh on the train coming in from the airport, I actually had a really broke up a start up a really interesting conversation with a local who told me Piece about a bit of history about a Spanish gentleman who came to live in Denmark named Juan, who's who's come down, become very, very well known in Denmark. For the impact that he's had on politics and the sort of the Danish way of life. Juan was just universally loved by his neighbors. He was just a quiet guy, lived by himself. kept to himself, but uh but but was just a r uh a model for for what a citizen should be, you know, uh came from Spain, came to live in Denmark, became a model f

5:38

Speaker 2: a model citizen. Uh and uh everyone was sort of wondering how how does he get to be such a good citizen? Um are we ready? Do we have slides? No? No, we still don't have slides yet. Okay. Um so uh His next-door neighbor sort of found out about found out about uh about one first and came over and had a bit of a chat with him and sort of find out what was going on and and learned this sort of really this really, really valuable lesson. And took it back and started to live his own life following the same rules and patterns that that Juan had taught him in this in this really, really simple conversation that had happened. And and again, sort of the message started going all of a sudden there were two people living next door to each other that were living the best possible life And everybody around them started to notice that

6:24

Speaker 2: here are two very, very happy people living the best model of what it is to be a Dane in the in in the modern world. We're still going? Still waiting for slides? Okay. Yes, we have we have slides now. All right. So we will continue the story of one after Seth Yastrov talks to us about type-checking your Django. Thank you

6:52

Speaker 3: Hi, I'm gonna talk about type checking your uh Django project. Um so if if you don't know, uh Python has uh uh uh type annotations uh added since python three and you can also put them in uh you can also put uh type annotations in your python two code with some type comments. Um Uh myPy is uh a type checker. Uh you can install it and let's say you have a function uh and you want to annotate the um The argument uh and return type, you can call it with the wrong type, in this case string, although it should be an int, you get an error. So that's great. But what if you want to type check your Django code?

7:38

Speaker 3: Well there are stub files which define the uh interface uh for all sorts of Django functions, classes. and so on. Um it's a project on GitHub by um Maxim Kornikov and other people have contributed as well. You can just pip install it uh to your project. So let's say I made a a Django uh project uh and I want to type check it with my Pi. So I make a um a MyPy uh INI file and add in some uh options and then run it and I get this error about need some type annotation, something in the settings. Let's see. And if I add this uh plugin

8:25

Speaker 3: to this config, the plugin comes with the stubs, it will not complain. And this uh plugin does some cool magic stuff so that you can actually type check uh some of the cool Django features like the Oran. So if you try to construct some uh uh object uh model and it doesn't have uh actually the attribute you're uh you're using, it will uh tell you about that. Um Let's say you have a character field on your model and you try to pass it a none, but it's not nullable, uh, it will complain about that. Let's say you have um

9:12

Speaker 3: yeah, let's say you uh have a relation to a foreign key, uh to a related model. And you try to access uh that on another model and access field on that, it will also be able to follow that relation and uh type check that field. So in this case you can't uh add one an integer to a string is name on the publisher. Um And finally, a more complicated example, if you are using this uh values list uh function to to get in this case just one value from uh uh query as your result, in this case the the name field of this uh

9:58

Speaker 3: person model, uh then you should get a string back, but because you are only asking for the first row, you might get a a none back if the the row didn't exist. So actually um If you try to pass this to a function that takes a string, it will complain because it might have a it might actually be none and we had the strict optional setting uh enabled on my pie. So this is very cool. Um there are also non-Oram stuff uh these stops. Um there are stops for pretty much all of Django, but it's probably not entirely correct or incomplete um

10:43

Speaker 3: because a lot of it was generated with uh some tools. Um Yes, thanks. If you have a custom settings module, you can also specify that in a config file and it will uh understand that. And um You can contribute at GitHub. It's um uh actively developed and there's also a kiddo channel. And there's also a related plugin and stubs if you're using uh Django REST framework. Um so where to go from here? Um Yeah, the project has some tests actually on type checking the Django tests itself, which they don't all pass, so um there's some things ignored.

11:30

Speaker 3: Um but if more of them pass um then it's It kind of shows that it it's pretty legit or at least pretty accurate in not giving false positives. And you guys should try it out on your projects. Thank you.

11:51

Speaker 2: Thank you, Seth. Well our next speaker gets set up. So uh one has told his next door neighbor uh about this great secret and now we've got two people living their best lives, their best Dan ex Danish lives. Uh they uh then start the pi the people on the rest of the street, uh uh they notice this is going on, and so they come over and they say, so you know what's what's the what's the big secret here? And they Seth and uh sorry, uh uh Juan and the uh uh and his neighbor both share this this one little short secret about how to live your best life. And uh um yeah so okay we're ready. Um so our next speaker is Francois Seguin. Uh take it away

12:28

Speaker 4: Hey, bonjour. Hi, my name is François Seguin. My Twitter handle is Holdy. It's not an Indian restaurant in Liverpool in case You see some mentions. Uh I work at Polyconseil in Paris, uh company uh which among other things uh we make information systems. um behind electric vehicle charging uh and car sharing systems such as Source London and Blue LA in Los Angeles. So um uh switch careers uh actually uh a year ago uh I've been working at Polyconseil for six months and my mission at the moment is how to implement privacy by default in an existing Django app So we have a million lines of code uh approximately. So uh I couldn't afford to do it by hand and manually. Uh I'm not crazy and I'm very lazy.

13:14

Speaker 4: So um also if I missed anything that could cause uh a very bad personal data leak. So I'll take an example in logs. For example we what if we logged something very badly? Uh a customer would uh edit uh their details So we have uh an email address, we have a phone number, uh uh um birth date, some additional details. Uh what we wanted was some something with redacted values, something that would be anonymized or pseudon pseudonymized. So the solution we came uh to was for instance an example with uh strings. I have a variable that is a name, it's a string, the value is Jean-Michel, it's very French. And uh what we do is uh we wrap it, we give it an alternative value, and it turns it into

14:01

Speaker 4: uh a different object that has an original value, Jean-Michel, and an uh an alternative value which is redacted. So um what we do then is we wrap the callables. For instance, if I want to print the name, um it the the object we'll call the dunder astera uh method and this uh method the method has been redefined to check uh the context am I supposed to show the the original value or show an alternative value if it's supposed to be redacted then I return redacted and of course if not I return Jean Michel. So next for the fields um in the database we have a lot of customers So we have for instance a table with a type of Vaucan with Jean-Michel

14:48

Speaker 4: and have this new field now. So I need to do uh define a new mix-in. And this mix in just redefines two methods from db value. So from the database we wrap the value and the pre-save method that unwraps the value from the field to the database. We also have uh a model mix in uh which just redefines the set uh dunder the dunder method set hatch uh to wrap the value of fields that contain personal data. So if I do customer dot name equals Jean-Michel. This is the method that it's called. And to help with all that, two context decorators. So it's both a decorator and a context manager at the same time. Hide personal data and show personal data. And then we can imbricate them.

15:34

Speaker 4: So remember we had the logs at the beginning. So a very quick recap about logging. I have a message, I have a level. I give it to my Python object, the a logger, and um we has which has several handlers maybe. A handler can be uh logged to a file or to the console or uh send an email, whatever, and I can add a formatter. So what I do is When I don't want to show the personal data, I just use a decorator on the formatter. If I for some reason want to show the personal data, I can use the other uh decorator. And this is how I can uh obtain this very nice uh redacted log. Um so what are the next steps? Um obviously this is very very very simplified. There's room for improvements, and uh next step is of course

16:20

Speaker 4: open sourcing. I still have one minute. So as a bonus, also we have um custom template tags. How do we do that? In the template nodes, we check a permission to see if we can if we should show or hide um the value. Um and this template that can be used. with filters. So for instance, I can I can do a hello with a customer name. I just need to give it the custom the variable with a filter, in this case an uppercase filter, and give it the permission. The condition I also works with um a form and I can just add the uh a bootstrap filter if I want to.

17:05

Speaker 4: Um if you don't know what GDPR is, um it's a little late, but But there was an amazing talk last year at Django Europe 2018. It was by Will Hardy. It was called Protecting Personal Data with Django because it's the law. And this is For me. Not for me. Thank you.

17:29

Speaker 2: Thank you, Francois. And bonus points for having a hyphen in someone's name. I like it. All right, so we've uh uh Juan has converted his entire street and taught the entire street about uh this this this simple message about how to live your best life and uh it doesn't take long before when something like that happens that the government finds out. Um and so the local uh the local city found out about it and they were uh interested in finding out about this message. We'll find out a little bit more about that after Sasha Romain introduces us to a different secret. Uh take it away, Sasha.

17:59

Speaker 5: Thank you. So if you've seen me around or if you've been to more jango cons, uh you may have seen me hand out these delicious little cookies called strobe apples. I bring them from Amsterdam. They're like two waffles with some gooey sweet syrup in between. Very tasty. I've been doing this for a long time. I've been bringing them to DjangoCon for years at least. So far I've been involved in uh handing out about 56 kilograms of these cookies, uh of which 16 kilo was sugar. So I've contributed about 255 million calories of strobe waffle to open source communities. This is enough for an adult to live on for six months, uh but you would not feel well

18:45

Speaker 5: And then there's also the Secret Society of the Stropafel, which started some years ago. And you can actually become a member. There's a small initiation ritual and then you can get your hand stamped with our logo. Uh the secret is I don't actually know how many members there are because the stamp fades after a day, so I can't keep track. I think we have about 300. And um why am I doing all of this? Like when I meet new people here also they ask like, you know, what is the deal with the strobe in the jungle community? And I do it because it's just really fun. Um because like you know when I meet people for the first time sometimes they're initially a little wary, like strange person from Amsterdam handing out some food. I get asked a lot whether there's weed in it.

19:32

Speaker 5: And uh you know people who know me they sometimes get really enthusiastic. Like I've had people run down the hallway when they saw me uh again to ask whether I brought any strobe apples And so the fun is mainly in like how enthusiastic people get about this, because these cookies cost me about six cents. So you know it's not like a major effort And um basically the reason is for me like it's not just about the cookie, or I don't think it's just about the cookie for these people. It is also bringing them a little bit of happiness. It's a random gesture of kindness, even though it's small, and that matters to people. So, in a way, the secret society of uh the stropafel is actually the secret society of happiness

20:21

Speaker 5: And when we think about happiness, we often talk about we often think about very big things, about your life partners, about getting married, about children, about moving to a different country. And uh if you recognize the colors of my shirt, you'll know I know some things about big changes. But uh we often tend to forget how it can also come from really tiny things that really small acts of kindness, small gestures, can make a really big difference. They can make someone feel better after they've had a bad day or or something happened or they're just not not feeling so well Small things can add up for them. And one of the ways in which you can contribute to this is a project Mikey mentioned earlier, open source happiness packets.

21:10

Speaker 5: Which is basically a platform where we try to get people, mainly in open source, to say nice things to each other. So if you uh saw a talk from a speaker that you really liked or you had a conversation with someone that that make you feel good or you learned something or cheered you up, then you can send them a happiness package. We've had 930 cents since we first launched this in Budapest. And uh a lot of them are public also. And uh so some of my favorites include it is people like you that make me truly happy to be involved in open source. These are public with permission And uh you all deserve way more praise and accolades than I can possibly give. And there are another hundred public on the website. So um

21:56

Speaker 5: We've had 930 cent and there are enough people here that I'm sure we could get to a thousand. Uh I'm sure there are A lot of people here who've met someone that they appreciated something that somebody did for them. Maybe it was a converse organizer, maybe a speaker, volunteer. uh anyone really. But also like happiness packets are not the only way. There are so many small acts that we can do. Uh that maybe we don't even think about so much ourselves. That don't take so much effort But they can make a big difference to everyone else, to someone else. Don't all start bringing unhealthy foods because that doesn't scale. But there are many ways. Uh so my name is Sasha. I've been called the monarch of straw raffle-based happiness.

22:41

Speaker 5: Please join the Secret Society of Happiness.

22:52

Speaker 2: Thank you, Sasha. While our next speakers get set up, so one has been been called on by the state gov by the local city government. They've invited him into a meeting, one goes into this meeting so that he can help share this message about how he lives his his best life, the message that he shared with his uh his neighbors and the uh and the rest of the people on his street. And the the government's really really interested about this and wants to expand the program. Um we'll find out more about what they did uh after Karina and Jessica talk to us about Pinam scholars

23:21

Speaker 6: Good afternoon everyone. So my name is Jessica and I want to talk to you about Pynam Scholars. Pinam Scholars is a subgroup of the Python Amebia Society And um there are Python coding clubs in high schools. Okay, so um one of the things that we have always been struggling with is computers. So this picture was taken at one of our Friday classes We have two hour classes on every Friday except for when it's school holiday or when the kids are going home. So we have always struggled with computers as I just said. And um we have done plenty of things to overcome this or be able to practice even without um uh computers. So um what I want to uh say that I have not really said in a lot of talks that I have

24:08

Speaker 6: heard is to thank uh the Cardiff no The Cardiff University, because they've always, when they have a representative coming to PyCon Namibia, they've always brought at least one computer that they are not using. So and that's one of the uh the computers that we are using there. So we share them. We have four now and we share them. Some break and so forth, but currently we have four that are working. So I want to send them a special thank you So one of the things that we do is what we call Computer Day. I've spoken a lot about this or extensively about this uh at DjangoCon Europe 2018. So if you want to know how we do it and know in depth about it, uh you can watch the video online

24:54

Speaker 6: on YouTube. So uh what uh what we have been trying to do this year, what we are trying to plan to do is that we extend it to be a six day uh training instead of just a two-day conference because we have had schools from villages that join the society and we don't want them to come all the way just to come for a two-day conference. So we want to change it and extend it for six days. So if you want to be involved in terms of coming to be a mentor or a tutor um or teach about something in Python, we are more than Happy to have you on the team and collaborate with you. Yeah, so we have uh had six schools now this year that joined the society. So we are quite happy about that. And that's one of the schools in the north.

25:40

Speaker 6: And that's what happened after we drove 13 hours to go to that school. So that's why we want to extend computer day to be a six days thing instead of just two days. Right, so one of the things that happened this year is also that we had uh we joined or we finalized a partnership with NSDO and ASB Hamburg. So NSDO is a Namibia Sun Development Organization So they um give matrices, school desks, uh use computers from that are donated by ASB Hambeck And um I heard about them through a I've been a teacher for three years, and I heard about them through a parent because I was always complaining about the lack of computers at the school and things like that, and then she introduced me to this guy

26:25

Speaker 6: So when I spoke to him he told me no we give computers to primary schools and we give computers to schools that are dominated by the Sun community because they are marginalized And so after a few meetings, I convinced him to give computers to schools that are not dominated by the Sun community and secondary schools So this year we had our final meeting and we met the ASB Humberg group and we are now going to receive computers from them. So they are going to be Let's say giving uh a full computer lab or like twenty computers to a school and then we give them like an amount of money to help them cover the cost that they incur when the computers come. So um Namibia has about uh

27:11

Speaker 6: one thousand they have more than one thousand seven hundred schools, so we have a long way to go. They are not Going to help. So we have had um a couple of things that we also try to do that we've been doing to try and raise funds. And uh Karina will be talking to you a little bit more about that. I met her at uh Young Ocon Europe 2018 and she has helped me especially with the emotional worrying of things and things like that. So she's going to talk to you a little bit more. about hey ideas.

27:43

Speaker 7: Hello. I'm going to talk more about the ways that that we could uh uh uh help uh uh to contribute. Well there is a Patreon uh link uh uh probab We will post it on Slack also and you can donate uh directly here on the on the letting. But also you could could get more creative ways could find more creative ways to to do this for example uh well I myself I um pledged to give a uh free one day beginner lesson uh for three people uh who uh in in London Uh so you can but you

28:30

Speaker 7: you can also do the same the same, uh but maybe something different like guitar lesson or you could uh uh make a plush jungle corny jungle pony or uh uh maybe you have some other ideas uh uh to give us rewards for other people who donate uh uh to

28:51

Speaker 2: Thank you very much. Okay, so we have one last speaker. Uh this is this the the the local city government has found out about one. They've they've met with one, they've come up with a grand plan for you know we can we can do this. This is actually quite a simple thing to do And but unfortunately, before they actually got to the point where they were able to deploy this uh this grand plan out, uh Juan was abducted. Uh and they and the abductors took him out to uh to a golf course. Uh and they was was he there in the middle of the golf course and uh uh there was like they were trying to to stop him because they like they they didn't want the the whole society to change. They were like they liked things the way they were. Uh and there was, you know, there was a it was tense. There were there was uh there were there was yelling.

29:36

Speaker 2: Juan's a very nice guy, very calm guy, obviously, you know, living his best Danish life. Um and there was this there was a struggle, and unfortunately Juan was shot And uh we'll find out what happened after that after we have uh Christoph Buyenovitz.

29:54

Speaker 8: Hi, uh I'm Chris. Uh you can find me on GitHub and Twitter with my handle at Bunivic. Uh I'm currently working at Blecto. I'm a senior software developer and head of Warsaw Office and I'm going to talk you really quickly About uh keeping a request wide state in Django. And that's not to be confused with global state, because global state is very bad. It lacks isolation, you can leak Pretty much anything to another request. So for example, user data and Django tries really hard to get rid of pretty much all instances of uh global state that are uh still there. And we should be striving to do as well in our applications. An example of request-wide state is, for example, uh

30:40

Speaker 8: internationalization in Django So whenever we use uh the I-18N framework, which includes also the the middleware, we're actually not passing around the language around. We keep that in something that's called uh thread local storage. And uh as a matter of fact it doesn't have any magic involved, it's just using uh common Python construct In such a way that allows us to obtain and read the data from any point in our application, including our library code, at any point in a request cycle. So a really quick code uh example is uh we can have a state file which just uses

31:27

Speaker 8: uh one simple import and a pair of getter and setter. And we can use that from from middleware to set the object at the beginning of a request. Uh and then reset it at the end of the request. That's fairly important because we don't want to uh leak the data to later requests. And at any point after this middleware runs uh and before it returns We can access the data. So uh you can put anything you need uh in the application, for example, library code or uh some custom code related to location

32:12

Speaker 8: and geographical bindings for example or um maybe you want to keep the request itself as as in this example for debugging purposes Yeah. And you need to use it with caution, please. Don't don't abuse that. Uh You generally still want to pass variables around like in normal like any responsible programmer would do. That is pretty much still a global state, but it's bound to a one request. So you just solve some issues with isolation, but uh it's still a bit messy and indirect way. It just helps resolve some issues. Okay, so that's it. I think we have two more minutes left. That was a quick one.

32:57

Speaker 8: Thank you.

Questions this talk answers

How should I manage secrets and environment-specific Django settings?

Keep configuration in environment variables rather than hard-coding it or inheriting settings by environment. Use a tool such as django-environ for defaults and type conversion, and organize settings by functional groups rather than by environment.

Discussed at 0:00

How can I use mypy to type-check a Django project?

Install Django stubs, configure mypy, and enable the plugin supplied with the stubs. The plugin can check Django-specific behavior such as model fields, foreign-key relations, query results, and nullable values.

Discussed at 7:38

How can I add privacy by default to an existing Django application?

Wrap personal-data values so they expose either the original or a redacted value depending on context, then use model and database-field mixins to preserve that behavior. Context decorators can control whether data is hidden or shown, including in logging and templates.

Discussed at 13:14

Why does Sasha hand out stroopwafels at Django conferences?

She does it as a small, inexpensive gesture of kindness that gives people happiness and helps create connections in the open-source community. The broader point is that small acts can make a meaningful difference.

Discussed at 19:32

How is Python Namibia helping schools that lack computers?

PyNam Scholars runs coding clubs and computer-focused training, shares donated computers, and is expanding Computer Day from two days to six. It also partnered with Namibia Sun Development Organization and ASB Hamburg to provide computer labs to schools.

Discussed at 23:39

How can I keep request-wide state in Django without using unsafe global state?

Use thread-local storage with a getter and setter: middleware sets the value at the start of a request and resets it at the end, allowing application or library code to access it during that request. This improves isolation, but it should be used sparingly because it remains indirect state.

Discussed at 30:40

Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.

More videos by Dr. Russell Keith-Magee

More videos from DjangoCon Europe