speaker 1: Thank you. Yes. Thank you, everyone for joining to this talk. Okay, let's begin our talk regarding Jago's framework and how to make it. And you go to the next level. So first of all, who are used, a jaguas framework or no janguas framework? So great. I don't need to make a review. So who am I? Carlos Martinez. I'm from Colombia, bacdeveloper at uit. You can follow me Twitter on GitHub. And also I have on a small in this columombia, there's the place that I came from and run out the Python Bogota group. We have a meet tup for about 2500 members right now. I also do photography time to time. I have a daughter and I do travel photography. So let's begin. We're going to start with a five minute api and we're are going to do something like have users create events, have promoters for events and to create tickets. While we are doing this one, we're starting to think about these five topics, how to display different data based on context. For instance, I don't want to to get the same fields for an event inside our ticket. For instance, how to get better performance, how to filter information inside the api, configure permissions, and how to render results in different formats. Let me get out of here and let's take a look how our first version of the api is going to look like. So this is our ticket endpoint. As you can see, I'm sending out a nested object for event and also for user. On each ticket that I get, user has only fields, doesn't have any nested object in particular. And for promoter, for evsorry, I got the same, but only promoter is the nested object. So that's it. That's everything the api is working. But no, the problem is here that we have here is if I got only ten items, I guess I have right now. Yeah, it's not quite much a word fi. I get responses in about. speaker 2: let's take a . speaker 1: look how much time is taking king. It's about 100 milliseconds. But let's start to create a few more tickets. Always happens. These kind of things. Come on, tike. Give me one circle please. Maybe I'm in the wrong branch. Yep, that was the reason. Okay, sometimes happens. Okay. Right now I'm creating 5000 new tickets for this api, including promoters and users. So it is continue going to create a few more. And what we're going to see in our api is that all these response times is going to grow bigger and bigger and bigger every time. So our api is not done. So first of all, something that we can start to thinking about is when we have nested objects, we can reuse our serizers. So instead of have different serizers for what is a representation of an event and inside our tickets and create a news analyzer class, we can start to to use something called dynamics Zers. So we can reuse our logic in one serizer and use it for different purposes and different sections of the api. So this is a dynamic analyzer class that you can use is based on mosterilizer from jgo's framework. But the difference is that it has a different attrito get fields. And that's what does really Detrick. Then you can create, for instance, in this case, an event zer with an space to get the representation that you expect to get for this particular nested object. So you can define static methods to get those fields in this particular serierizer. So if everything works fine, you continue creating more things. Let me continue there. Just . speaker 2: create too much. speaker 1: So that's the main thing that you can do with dynamics related. So you can, for instance, create a static method to get location fields, but you can get only a noone method to return ID and name, for instance, if you needed to. So that's the way you can create those particular methods. That way you can save time, reuse logic within the seral Lazer that you already create, and there is no code duplication. So what about getting better performance? As you can imagine, we started pretty good. We started pretty fast. There's no issues, but the things started to get worse and worse when we get more users involved in our application. So let's see if that already finishes. Come on. Well, I'm going to stop this and let's take a look to how it is working now. I mean, in the right one branch. So let me switch back to the wscenario right now. Previously I just read about 15000 elements is trying to render that information. And you can see here how the kdjango is making too many queries to the api sorry, to the database to get all the information that I am asking in this particular endpoint. So until Jungo doesn't get all that information, is not going to respond. So that's the reason we should start to use prefedge and prefedge. What really does it will create for us a different query to a database to try to get all data that we need to make our representation for our serializer really easy. And in just one query, if that's the case, for instance, let's take a look to what happens when you get ticket objects dot all. It just only is going to create a select with all the fields form the table that you need. But when you add select related, what is going to do is going to get all the fields related to that model in particular that you have relation in that moin particular. So here is the same query, but now gets not only the information about ticket, but also the information about user. So it's not going to go again to a database and make 100000 of queries, but instead it's going to be just one. So that small change is going to save you a lot of time, is going to save you a lot of head edges. So that's the important thing that you need to take a look how to get everything in just one query, the perfect related is going to be all one, which is useful. But keep in mind, that is great for many, too many relationships. And the previous one, as we can see, we get where user ID equals to users dot ID. So that way is making the relationship between them on perfecrelated is going to be a little bit different. But even though it's going to be better than not making any preferelated, so in this case in particular, it's going to do two queries. The first one to get the information about eticket, and the second one is going to get the information about the events. But it's going to select only the ideas that they need to get the information that they expect. So for instance, you make a filter for tickets and you are getting just a set of tickets that is going to create a different set of ids that is going to query for the table erso. It's going to be way smaller. Also something that you can do and you can improve is to use the profege object. What really help you out is to get the information that you really need for that particular representation on the api. So if you get if you see here inside the profedge related, instead of having the string of the related field, I'm getting a preecobject inside a setting string of the attribute or the external or the key, and I can create a new query set and select the things that I really need. So with that dot only, I only asking for in this case, ID, a name. So the query is going to be a little bit more smaller. And when you have a lot of data to get in, it's going to make the change. So let's take a look if that already finishes. Yep, it takes two minutes and 5s to complete it. So our user is gone from the application is not going to continue with us. So prefetch and related and select related is a must to when our applications are growing. Next that we can do is to start to make filter how to get our information in a better way. One package that is really useful to get this is to use jungle url filter. You can set up two ways. The easy way is this one. You only add Jungo filter vant for url filter integration drf and you can select the filters that you expect to get filters on. And with this in particular, you will be able to get to do something like this. So you can go for the endpoint events and you can filter to get a set of ids if you need to, or you can get the name and make sure it contains any particular screen that you expect to get. Or if a related object has some particular name in this case, and you can start to filter even more complicated things. So it's going to help you to get complex queries inside the url, but you can also make it without less and use a model filter set that you can reuse on different endpoints with the same thing. The same logic is pretty similar to make a serializer a more serializer. All right, so but we already make prefetch. We already make a few things regarding filtering. What about cash? Acwe can start to use the jungle powerful cash ache that we have out of the box. So to do it, you need to activate those middle ter words Res with a red row arrow and make sure that the common millware is in the middle, somewhere in the middle. And to make it work using Jungo's framework, you need to call these two decorators variant cookie with a method decorator, variarian cookie, and the decorator to get catcha page. And you can set up them time that you want if you need to. And I recommend it to make it select and create A K prefix. So that way you won't forget how to invalidate . speaker 2: your cache. At this point. speaker 1: if you set up this and it's working, is going to give you a better performance. Please do not forget to invalidate cash in some way. So drop these lines of code somewhere in your code to make sure that when something change, the cache is invalidated at the right time and not after the time expire. But there's something else that we can do to improve our performance using cash. One is a really good package called Django cash hops. And what is going to help you out is to cash old orm transactions that you are doing, and you can cache multiple query sets. So to use cachoyou need to start to work in using rethis. So to use it, you had to stops ps, as many packages array, set up your Reis cache. And you can use these configurations to set up a few things regarding what you expect to cash. Ups start to make cash for you. And you can set up your own models and your applications to be cash. So you can define what operation is going to be cash by default, what is going to be the timeout by default on different applications and different models if you need to. And you can define to create a cache for everything, but it's not quite recommended because you may up having cash on different things that you really don't want to. So if you need to, you can also make cash. You can use cash ops to make it by yourself. So as you can see, we have this get query set from a mold uset, and you can define your query as expected. But at the end, you append dot cache and open a closing parentheses. With that, it's going to be cash in Reis and you will get the results not through from your database, but instead from Reis. So it's going to help you out with performance. But what about permissions? What we can do to improve our permissions. Actually, Jungo already has a very great permission system, but we can try to use something called dry permissions and is going to improve our experience. Has any other package we installed with pip drirest permissions added to our styled apps? And what we are going to do is to in our bset, we're going to add permission classes, this line over here, and you can define if that's a public endpoint or is required of education cation, but also add dry permissions. And now you can start doing something like this. So in your models, you can define a set of global permissions. In these cases, these examples are has permission to read, has permission to write, or has permission to create. So you get access to their request. Up this point, you can say you can get the user and you can make some validayou, can get require permission, require an attribute inside the user or anything from their request. So you can define different sets of rules for each and one. And you can also have object permissions. So it's not only global, but also you can have access to the instance itself and make some validations. The first example is going to make like the user is related to that particular object. And also you can require, as I mentioned before, I require a particular permission already granted for that user. That is a request esting access. But even though we can add also permission not to only the object, but also to a field or an action. So if you have a field and you want to protect, to get right to a particular field, you can set up this method and you can protect this particular change. And if you define in abuse set and different action, you can use it with a name and you can make a restriction over there. And so all the logical regarding permission is going to be only on each model. So it's easier to find where the actual . speaker 2: logic is there. speaker 1: but you can customize a little bit more. Maybe you want to share a set of permissions within different models. One way to do it is to create our custom permission. So this is based on reframework permission itself. And you can use it four different, because you only need to implethe implement the method has permission and has some utilities. For instance, safe methods are going to be get meta and options. So if you are given in this case, access to where make requests to that method. But it's not one of these methods is going to require a permission before you can grant Ted access for patch boot post. So then ta can help you out to add this permission to a different view set. And then you can protect in a different way that particular buset that you add that permission. speaker 2: But how to use then dry permissions . speaker 1: when you are outside of a model view set, if you create an api view, you're going to see that it will throw you an error because there is not a key request. So important in those cases, you will need to create your fererilizer with context is going to required to provide a request. Otherwise, it's going to throw you an error because the model has not a way to get the request and and run all your logic that you are defining there. And last one that I want to bring to you guys to take your api to another level is to use some renders. So yesterday, we saw this package working when using automagic. So this is going to be another example is very, very useful to and very easy to implement. So on your model view set, you only need to add this particular class xls file mixing. And inside renderer classes, you need to add xlrenderer. So with that in mind, you can create excel files just calling the api by creating by arenina a new header or making explicitly on the url. Don't forget, if you need to, if you want to, to get to continue having the api html bu from your, from jungorest framework, don't forget to add brosible api render. Otherwise is going to be just json or excel. speaker 2: All this code is going . speaker 1: to be available on this repo. I'll give you a couple seconds. You can take a picture and let's take a look to how it works after we do all that things . speaker 2: to this api. speaker 1: So let's take a look. So I'm going to change the branch to muright now. And our previous response took two minutes, a little more, and now is only 124 milliseconds. Of course, it's paginated, but that's the idea to get quicker responses. And we are getting the event and the user here, and you can see here, remember last time I tried to do this, these are the logs to all the queries that the jungle was doing to get that representation. And now this is it. This is what he's really doing right now to get all that information. So it's a very small query. Our developed team is going to love us to do the kind of thing, that kind of stuff ough, but of course, you can get even a little bit more is going to take extra time to render. It depends on how many data you want to get. In this case, I'm getting all almost all that does set now 10000 items, but it's getting 7 mb of data at this point, and it took about three minutes. So maybe that's not what you're expecting to get. That's not exactly maybe what you need, but you can define the limits using the jungle reframework by gination. So well. speaker 2: that's it for now. speaker 1: I want to thank you to my team at uit and also for the client that I work with building engines. That's where all the mahappens and I learned that all these things. So thank you. Et titrage?