← Back to Show Notes

Transcript: Django 3.1 Preview - Mariusz Felisiak

Hello, welcome to another episode of Django Chat, weekly podcast on the Django web framework.

I'm Carlton Gibson, joined as ever by Will Vincent.

Hello, Will.

Hi, Carlton.

Hello.

And this week we've got back with us my fellow fellow, Marius Feliciak, who's here.

Hello, Marius.

Thanks for having me.

Thanks for coming on.

What are we going to talk about?

We were going to talk about something.

Django 3.1, Carlton.

Right, so yeah, we're going to talk about Django 3.1, which is in beta now.

So Mariusz, go on, you're the guest.

You tell us, what are the highlights?

What are we looking for?

Well, tell people when it comes out.

Yeah, so we have a final version at the beginning of August, on 3rd August, I think.

And released candidates two weeks before it.

So currently is the best time to try it, to install it on your existing projects and see

if everything works properly, especially with new features.

So everyone that uses, for example, JSON field from Django contrib package can now try to

use it directly from Django models.

That's probably the easiest way to contribute to Django, to try the pre-release packages.

Yeah, because this is going to come out July 15th, so there'll still be a couple weeks

for folks, and we'll link to, there's a very comprehensive release notes that go through

all these things, but we're going to spend this episode talking about them a little bit.

Yeah, so currently we have beta released, and on July 20th we'll have our first release

candidate, and on 30th August the final release.

Okay. And the JSON field was done by Sage,

who is a Google Summer of Code student from last summer.

I want to talk about the features, but I also,

if the two of you could take off your humble hats

and just talk about what do you two have to do

to prepare a new release?

Because I know there's a whole lot of steps,

but just to let people know,

what are all the things you have to do

to get something ready to be pushed out?

So we have a release schedule.

we have really detailed instruction what to change when what should be done before the release so

we just need to remember to do not omit any step yeah and to update it when we make a change

exactly something's broken the big issue i think is the point releases like so like 3.0 or 3.1 or

you know 3.2 like the major releases they're the difficult ones because they're only once

every nine months and the steps are there's a lot more steps it's like what did we do last time oh

yeah, like trying to remember all those pieces can be, you know, can be tricky.

And it's like, oh, and why aren't the docs building with the, you

know, the Chinese translation?

Yeah, exactly.

There is a lot of small steps that, that should be done.

Like for example, open pull request in read the docs or add a new classifier

to PyPy or add pre-release to Django project to really run docs build, et cetera.

Well, and this is your, what is it, second, third major release

that you've been a fellow for, Marius?

Which one is it now?

The second.

Just the second, okay.

Yeah, just the second.

And honestly, the first major release

that we are making totally without Tim, I think.

Yeah, so Tim Graham, I mean, we've had him on,

and I just recall Carlton telling me about, you know,

um doing it um largely on his own but with tim's help and so i imagine you went through a similar

process of all the little steps that are documented and perhaps not documented but i think tim's still

secretly watching because every so often there's a comment and it's really insightful and to the

point and he's like you know and has this been updated or something you know something really

like minutiae exactly um okay so let's talk about the highlights of of the release so one of them is

that uh it requires python 3.6 and up right it's not supporting lower versions of of python um yes

yeah so three so 3.5 is still supported oh it is like it's it's still within yeah i'm no no no

sorry sorry i'm supported oh sure yeah yeah for python version right um i mean it's in uh what

they call extended support so it's only security fixes now for Python 3.5 but in order to move

Django forward like the three point so at the last two so for 3.0 for 3.2 for the LTS we drop

the version and then that will happen again probably for 4.2 will probably go 3.7 so this

This policy is quite clear. We are dropping Python version only after the LTS version.

Django 2.2 will end its extended support after dropping support for Python 3.5.

So they will not support Python 3.5 before Django 2.2 will end its extended support.

Python 3.6 will be supported a bit longer, so Django 3.2, for example, it's not enough to drop support for Python 3.6.

Well, so these are all the things as a developer that make Django great to work with because it doesn't break on you.

But I know it requires lots of extra work for you and the two of you and others in the community to maintain that non-breaking support.

Well, today, just today, Marius was fixing a test failure on 2.2 against Python 3.5.

like you know and ah it that gets harder and harder as you get you know when 1.11 was at the

end and we were still supporting 2.7 on 1.11 and like like a number of fixes every month were

causing issues only on 2.7 only on 1.11 it's like we forgot that we've got to go back and change it

because of this and you know it just gets harder and harder a lot for that long-term support as it

gets older well and that's and that's uh the type of work too that volunteers just really don't want

to do either um because it's really not that much fun but it requires a lot of focus and expertise

to do so hence the fellows um so 3.1 so what's the headline i mean i'll tell you what i think

and you guys can tell me what it actually is to me when people ask me it's you know async uh views

are in there there's json fields i'm excited about the new pathlib in the settings file

so when you run start project now um it will default to pathlib which just makes

setting your pathlibs a lot easier but there's a host of other features um and maybe we could

just start with async so what's what should people take away from 3.1 async is it you know

the question is is it finally ready to use in a django project or what are we waiting on i will

leave it to carton he's he's he's an expert oh yeah no yeah it's ready to use um so the first

thing is don't change anything just keep running your whiskey server and then all of a sudden you

want to um make some api requests to pull up from data from a couple of places and so you can now

just make define without changing anything else you can define an async death view like so instead

of a def view which is a sync function you can find an async def view which is an async function

and then you can make use httpx or you know whatever your favorite networking library is

to go and make the api calls you want to do concurrently and django will run that for you

in a in a thread pool in a thread it'll run that that single view in a thread and you'll get

concurrency in fetching the api views but you haven't had to change anything else so for a lot

of people and a lot of use cases that's that's kind of what you want to do for years for years

now i've been spinning up node.js projects on the side in order to make concurrent requests to the

ape to an api in order to pull together data for a client and then the last few years we've been

able to do that with python web frameworks instead of spinning up no but now you can just define that

view in your django project and that's super and that's without doing anything else async related

um well and that relies in part on i've just been updating my books and one thing that

in 3.0 when you run start project you get the asgi.py file with the asgi server that

powers all this so someone who's updating if they just update from like 2.2 to 3.1 do they need to

manually add the asgi.py file or right no but so this is this is the so there's there's two

This is the amazing thing about the Vue's implementation,

is it will run async views fully within the WSGI pipeline.

So you don't have to change anything

to do this first level of asynchronicity.

Oh, you don't need ASCII.py at all.

You can continue to run Whiskey with Garnacorn or whatever you're using,

and you can just define these single async views to make use of concurrency

within a thread pool to go and do things right.

And that's why it's so beautiful because you can just literally upgrade

and then you just think, oh, I'd like to try fetching two HTTP requests

simultaneously, and then when they're both back,

I'll combine them and return them to the client.

And you can do that without anything else.

It's like, ah, this really is dipping your toe in async.

You don't have to change your way of thinking very much.

You know, you just have to write this one async def view.

So that's what's super.

And then the step up, the second step,

is if you wanted to get involved with response types that are more interesting.

I don't know, let's say you want to do server-side events

where you open a connection to the client

and every so often you pump some more data down to it.

So I don't know, like a ticker tape application, this would be the textbook example here.

You open a connection and the server can every so often feed you some more information.

These kind of more interesting things.

At that point, you'd need to switch to ASCII and you'd need to create an ASCII.py file.

And then you'd either use Daphne or Uvicorn or Hypercorn or one of the ASCII servers.

So this is instead of Garnicorn as your application server to serve your ASCII pipeline.

And what's amazing, and the other side of the amazingness, is that if you switch to ASCII, all your sync views will continue to work exactly as they had.

Because underneath the hood, Django is determining, is this view an async view or a sync view?

And if it's an async view, I'll serve it the right way.

And if it's a sync view, I'll serve it the right way as well.

Now, there's a certain performance overhead to that.

There's a certain context switching.

Every time you context switch, there's a really small performance penalty.

So if you're really, really, really after throughput, then you need to make sure that you're running ASCII with only ASCII middleware, with only ASCII view at the end.

And if you've got ASCII all the way through, then you don't get any context switching performance benefits.

But for most use cases, that extra teeny bit of throughput, that's not what you need for most use cases.

Certainly not when you're beginning.

Does that sound about right, Maris?

That's kind of my answer.

I can only add that if you really would like to use the entire async stuff,

then you should probably learn with Python 3.7,

because in Python 3.6 it is still a bit immature.

And, of course, everything works properly,

but still

I think

this journey has begun

in Python 3.6

and in 3.7

it really works well

and I think that's

as well I'd just be up to date because

async.io is still evolving

and you know there's still debates about the API

and how it looks and what the

recommended call

paths are and all this kind of stuff

and so if you're going to be using async then

do yourself a favor and get one to 3.8 or the latest versions rather than trying to run it in

3.6 because you're going to create yourself lots of issues there i see see issues on channels or

on daphne where it's like oh no if i updated to 3.8 this issue went away well as ever it's like

a car carlton right you have to tune it up and yeah you have to send you you have to send your

car in for a service so yeah i wonder as well and i don't have an answer to this but i'll pose it to

you to youtube anyways if perhaps one of the ways people start so one of the things people think

with async is oh now i can maybe replace redis or some of these other services that are q-based

things and i mean that's an imperfect statement but i think that's one that someone could think

that could you disabuse you know either of you of of that comment like oh yeah async django so now i

don't need you know redis or memcached i say this because i've had that thought and because i'm asked

that by my readers so it is out there so okay so you're not going to get rid of like you memcache

is totally different kettle of fish right you're caching server you're not going to get rid of that

and if you're using redis in that same um ballpark you're not going to get rid of it so not for

caching but for like queue stuff if you're using right but if you're going to use redis as a queue

you're probably not going to get rid of that either right so in principle we will be able to

create hooks for lightweight background tasks that will just be able to spin off using an async i go

and do this async task in the back now starlet tom christie's framework has got that kind of

ability already in it and we're you know we keep looking at that and thinking oh maybe you know

3.2 3.4.0 who knows um but it's not going to replace a queue you know it's not lightweight

background tasks yeah replacing your full your your queue with years of um battle tested coding

behind it no i don't think you're going to replace that keep keep django queue keep celery if you're

using that or huey that came across yeah i saw you you um you mentioned that someone wrote a nice

post about using huey with django so that's a nice lightweight option but don't like don't you know

you're not going to replace those instantly like maybe over time but this stuff is still fresh and

young and what sort of oh yeah we could do this doesn't mean it's you know the same as right

wrapping an existing task or function with a decorator and it just happening by itself because

all of that's written i thought you'd say that i just wanted to tee that up so you could

disabuse that statement and i mean the cool thing about starlet too just with async is you know

there's this fast api framework that uses starlet under the hood and um i'm sure you know we in the

django community will take some inspiration from how that's going but that seems to be

i don't know if there's examples of it at scale but it's very people are enjoying using it i've

heard a number of developers who've built smaller things with it and really really liked it i think

microsoft are using it um a lot into you know in their stack around azure and things like that so

you know it's very popular and what's really great with ASCII is so cool like because every

every level of ASCII is a middleware it's it's every app every bit of every middleware and every

view is an ASCII app right it's a it's so you can nest yeah you well it's kind of like an onion but

it's kind of like a tree as well in that you can nest them inside each other and you can you can

have a middleware that would root between two ASCII apps so let's say you're using Django and

then alongside of it you want web sockets where we've got channels which is you know where you

need still go for web sockets even now and then but let's say you've got something that's written

in fast api you could put that next to it and it would from the same server and you could route it

within your kind of ascii framework and and combine the best of both worlds and if there's a nice

middle ascii middleware out there that you want to use where you can wrap your django app in that

ascii middleware and you know it's a lovely position for us to be in it's kind of really

what's the word I want

like fertile

it's a really fertile

environment for us

to be building web apps

in now

I think I'm quite excited

about it

well and Marius

this is a question for you

so testing

how does async testing work

or how will it work

because there's some

there's some of that now

and then going forward

how should people

think about that

yeah so

with async use

and mid-race

we also added

a lot of

chunks that

can be used

for testing

like a special, a separate class of test client. So there is currently there is

an async client that is built-in in the testing framework that can or should be used for async stuff.

To be honest, for me it was a big challenge to review the entire change

relative to async views, middlewares and testing. But I think that's something that

probably allowed us to find at least a few smaller regressions, where a person that

is not an expert in async world try to work with. I think that's now I'm a bit better in it

but still so for async tests you can now use async client you still can use the same methods for

testing GET, POST, or anything else, it is just called with await, so it needs to be awaited.

And instead of that, everything works similarly.

But as well, there's one thing to note for test case, which is if you could define an async def

test in a test case, it will run in the right context and be run in an event loop for you.

So you can test asynchronous functions using Django test.testcase.

Yeah, that was pretty.

That was very nice.

Which is nice.

Marius, if I could have you answer this.

Can you describe to people what it's like mentoring a Google Summer of Code student?

Because we've had them in the past.

We have several now.

They add major new features.

But I don't know if people, I know that people don't know what the mentoring role is like.

So could you talk about maybe specifically with Sage?

So we've had him on and, you know, he's a student.

He added cross-DB JSON fields, so not just in Postgres.

What is that process like for you as a fellow to mentor someone?

It was pretty smooth, to be honest,

mainly because Sage was really a hard worker.

So he made a lot of job on his own.

So he made a lot of investigation

about how it is supported in different DBs because it's not really a straightforward thing.

Because we have different implementation in different DBs, we have PostgreSQL where

there is a native field here, but in other databases we have, for example,

text field that is just looks like JSON field. It's, for example, text field with some extra

constraints that are built in a database so it's extremely complicated but it was really

a nice experience to be honest the hardest part was to polish it at the end because it contains

a lot of small pieces in different parts of Django so we have changes in schema we have changes in

introspection in different lookups implementation decoders encoders we need to duplicate old fields

we added some extra system checks etc so a lot of different pieces that are on the different layers

in in django i can say that it was the biggest pull request i think that i ever merged to django

it touches around 3 000 lines yeah it's it has more than 400 comments

so before before clicking match you need to check 400 comments and see if all of them are addressed

properly well i think it's a great feature i mean it speaks to sometimes people you know want to

to know what database should i use with django and it is true that postgres has more features just

like search um and just because people have built them um so it's it's nice to have more uniformity

but it takes a tremendous amount of work obviously i have to say maris put just so much time and

effort into polishing the pr and like the different like you know sage got it in place during his

project it was there but then Maris went through and was able to adjust it and make sure it was

going to be maintainable in the long run and clear up the the implementations and the amount of time

he spent on it was a Herculean task it was it was fantastic and you know at the end there's this the

the way that key paths are determined if you try and do a look up on a nested JSON field you know

like so you've got my data with pets with you know dog Rex I want the the dog who's got the name

you know and you try and fetch that value that's really complicated um it's just mind-bogglingly

complicated and fortunately marius finds it hard as well so i wasn't too upset yeah you don't

understand like oh this is easy but you know to get that right and to get that into the state it's

it's in and it's ready and it's you know so well done marius i think that was super what i want to

ask though marius is if um if i've got so i've got my project and i'm on 2.2 and i'm using um

Postgres JSON field

what's the steps I have to take to upgrade

is it going to be easy for me or is it going to be difficult

it should be extremely easy to be honest

you just

you just

should change imports

from Django country Postgres

JSON field to Django

DB model

and honestly that's it

you also need to run

migrations

to create new migrations

but they will they should not impact your database at all yeah and even if the old fields are

deprecated then we still will keep the stub fields so you don't need to change historical

migrations that is the old field so it should be quite easy and that's it yeah okay super that's

well you've put me at rest beginners often ask about differences between databases and

almost you know almost without lying i can say well they work all the same you know certainly

for a beginner level project because the jenga orm but it takes you know herculean levels of work to

make that be the case so i just wanted to highlight that and maybe so there's currently

two google summer of code students um what's how's that going for both of you right i mean

there's i know there's a uh online you know progress the things they have to hit each time

but how much how much work is is that for the two of you on top of everything else you do

it's okay it's like um you know reviewing an extra pr and then you know every week or couple of weeks

i spend a teeny bit of time making sure i've caught up with the students and that you know

they're doing their thing so um casper is working on the django um stubs project which is like the

type stubs for django um and he's working on the my pipe plugin for that so that you know that will

hopefully be improved over the summer and he's we've just done the first assessment and he's

merged a couple of small prs and helped a couple of people and he's going really well

and then ahmad who's working on django itself is um helping to make the parallel the test runner

work in parallel for windows and also now put on modern versions of mac os so

recently mac os changed the default process spawning method to or forking method to process

start method to um spawn rather than fork which is a low level thing but the the difference is

a spawn is how unix does it and it inherits the parent processes memory space basically

whereas a spawn creates a whole new brand new process entirely um and from python 3.8

that's the default process start method on mac os because it will forking will stop working in a

future version and so from python 3.8 the django test suite doesn't run in parallel on mac os which

is a real pain it's like wow because it goes from like six minutes to about 20 it's this is not a

good change so you know we're hoping to get back up to parallel running on mac os and on windows

and he's hoping to add oracle parallel running as well because the the oracle test suite currently

takes over an hour or something it's like come on oracle but if we could and only because we

can't run it in parallel but if we could get that working then you know that we could cut our ci

times and we could run oracle tests more often because often we don't run them because they

take so long um and so it's quite a good project and that's really interesting and tom forbes and

adam johnson helping with that and david smith who's a new contributor is helping to on the

project management side as well so there's lots of people involved great well at google in particular

has been very generous to django both with google summer of code the some season of docs which um

we've been django's been accepted for they also donated five thousand dollars to django security

efforts earlier this year so django's been a big help or google has been a big help to django

excuse me um okay so other features so there's so many i mean there's so many features in 3.1 i

don't know you probably can't keep them all straight in your head what is there to say

about pathlib i mean it's more elegant than the current way of doing it but that's that's a

a novice answer what what are the two of you excited about with pathlib you know why was it

added because it's it's a major change to swap that out it's more readable that's for sure yeah

less yeah less things that type okay so what is it tell me tell me what it is marius what's

What's this path lift thing all about?

From Django 3.1, basically all settings support path lift

instead of the old way to do this.

So we use all OS hooks to create proper paths.

There's still except set strings as well, right?

Nothing's going to work.

Yeah, exactly.

So it's, if I've got a path, so like, um, the classic one is based in your settings,

right, and that would normally be, what was it, os.path.absoluteDir.blah, blah,

about their name dot their name like this kind of horrible construction you do and then

now you can just create a path which is path of the file and then you know it's it's an object

yeah fire parent and that's it yeah it's just a lot easier to use i mean and you and people have

been you've been able to use it on your own before but now that it's just baked in and when you run

start project boom beginners will have it so i think it'll make yeah but also you couldn't there's

lots of settings you couldn't parse it to so there's two things so one is that everywhere

that a path is needed it will accept a path object is instead of as well as a string and there's

there's one place inside the code where we have to cast back to a string that's in for sqlite

because it doesn't yet accept a string in that a path object in that place but we cast back for

you so everywhere that in the settings that you would have used a string you can use a path that's

the first bit and then the second bit is that we've updated the template so that when you create

a new project they automatically yeah use these new pathlib objects what else i mean so just you

know thinking about things that people will see when they use 3.1 so one is the admin right there's

a side the sidebar has been improved a little bit easier navigation on it i believe yeah so we have

totally new side part on the left side on the screen that make navigation

really easy currently. Well it's kind of cool you've got a bit you've got all

this giant screen you know real estate and you've got you know we now use a

little bit more of it more. Yeah you don't need to use breadcrumbs to go back

right few screens ago you can just choose a different model or a different

change this or another

different view that is

delivered that you are currently using.

Right, yeah, that'll be a lot easier than breadcrumbs.

There's also an

auth change. I'm checking

the notes here, but the

hashing algorithms change, right?

It's SHA-256 instead of

SHA-1? Yeah, exactly. So SHA-1

is still safe,

but

we decided to change

hashing algorithms in multiple places

to be honest. So

Currently, by default, it is not used anywhere in Django, so cookies, sessions, signer, password reset mechanism, all of them are currently using SHA-2.6.

And still, all support for old hashing algorithm remains until Django 4.0.

So, even if you update to Django 2.1, then everything should work properly, even with old hashes.

And we set the secure referrer policy now.

Yes, that's the other one I was going to...

So, that now defaults to a different, more secure setting.

I think it's same origin now.

Yeah, same origin.

Right. So, what that means is you won't send cookies to, I don't know, third-party or requests from third-party sites, right?

Yeah. And actually, I had a question about that because it was changed in 3.0 in the deployment checklist. And I'll put a link. It's in the Django forum. Carlton, you and Adam Johnson, because I think Adam Johnson made the change.

Adam knows most about this kind of stuff. He's holding it. He's got Google Calendar reminders to check the spec to see, you know, when it's all updated.

Well, because it baffled me too, because there was, you know, it changed and there were four options and I was like on Mozilla and I was like, oh my God, what is this thing?

So the interesting thing with secure referrer policy that people have hit is Chrome now, if your site is embedded in an iframe, right?

So if you're like Disqus as a sample, then Chrome...

Or Google Maps if you toss in a site.

So, okay, if you were serving Google Maps, then Chrome defaults to not sending a cookie there unless you specifically set the string value none in for the secure referrer policy.

And that was a change that just came in in 2.2.

And so people on 2.2 are having to create a middleware to work around that.

And, okay, it's not a tiny thing.

But from 3.1, you can just set that in your settings file and that would just work.

there aren't many people who are embedding their frames in their sites in iframes but

those who are they will you know that's useful for them yeah i want to ask because 3.2 is already

in process um it's on the way ahead it's on the way um marius what are your thoughts on what can

we look forward to in 3.2 you know nine months after 3.1 comes out in august so currently i have

one big release blocker in my mind

so I would like to add functional indexes to Django

in Django 3.2

so I think that currently is the biggest feature that I would like to include

in the next release. What about you Carlton, anything?

Well yeah, so one thing that didn't quite make the cut for Django 3.1

was proper reload

support for run server when you're running with ascii so at the moment the way the best way to

get that is probably to install channels and use channels version of run server um there is a you

know it's another option out there django ascii run server i think it's called um which which

pulls in daphne and will do the runs the reload for you um so that replaces the run server command

we need to get that in because it's not a great situation where for 3.1 people will be run server

but they won't be getting reload um under the ascii environment so we'd like i'd like to get

that done for 3.2 i'd like to get that in for 3.2 when was when was reload added to run server

because i remember using django before that was the case you had to quit and start i mean i know

it was it was a while ago but as a you know as a user i remember that was one of those things i was

like oh this is so nice that i don't have to quit and restart my server all the time maybe it was i

don't know 1819 something like that but makes me feel a bit like a dinosaur i'm like i used to have

to stop and start this server all the time i seem i seem to recall there being like phases of it as

well it sort of had yeah that's true would detect python changes but not any other things so i don't

i can't remember exactly what but i mean like you if you add a new tempate folder that was never

picked up i don't know if it is these days right well and part of it is because you you know if you

make a change to your settings file that's you know needs to be those environment variables loaded

in and so i think that was later on the reloading you know the html and css came earlier anyways

a usability thing so any anything else this is you know we wanted to dive a little bit deeper

into the 3.1 and 3.2 shed some light on the role of fellows and it honestly makes me feel a bit

better about i've been grumping around about updating my books but thinking about all the

things the two of you have to do for Django in terms of back support makes me feel a lot better

so thank you for that all I'd say is that I don't think there's there's not that much

explicitly on the roadmap I mean async was the big thing right okay so that's in now and okay

we'll see what happens so you know that needs to grow it needs to mature people need to start

using it you know who knows where it goes next there'll be loads of features to the ORM coming

over the next nine months that you know it's constantly ticking over and wow there's just

the changes that are made over time are just super but 3.1 is just well 3.0 point you know

extra number right it's just it's not a massive breaking change it's not a massive

jump it's that evolutionary thing that django does so well um and 3.2 will be more of the same and

you know that's what's exciting about it is because you can be on the latest version without

worrying how about you marius we will not remove any features in django 3.2 so if you will bump to

3.1 then you are safe yeah well and and you know so this comes out july 15th we're recording it um

two weeks before um people can still go and pip install dash dash pre django and try out 3.1 and

you know if you find any weird breaks do let the django community know but it should be in pretty

good shape yeah no run it against your ci please um you know yeah the ci yeah and tell us what

what went wrong yeah because currently it's it's easier to fix it then you will need to wait for

a month for a minor release to fix anything well marius thank you for joining us to talk about

what's coming in 3.1 i know i've been you know looking at your pull requests and

i have some sense of the work that you and carlton do but not a full sense but it's a lot

to make it smooth and um so thank you for all that work thanks carlton do you want to take us out

where can people find more info on django or the podcast right well on django you go to

docs.djangoproject.com and you know releases and read the 3.1 release notes so you go forward

slash 3.1 and releases it'll be in the notes yeah yeah oh we'll link to how to upgrade too

there's there's django docs on that we're linking to how to upgrade your version properly okay

that's a good idea and then we're obviously django chat and we're chat django on twitter

and there's a website, djangochat.com.

And yeah, join us next time.

All right. Bye, everyone.

Bye-bye.

Thank you.