Professional RESTful API Design using Python Flask | Jorge Escobar | Skillshare
Search

Playback Speed


  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Professional RESTful API Design using Python Flask

teacher avatar Jorge Escobar, Technologist, entrepreneur and open source fanatic

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Introduction 1.1

      1:07

    • 2.

      Introduction 1.2

      1:09

    • 3.

      API Definitions

      10:39

    • 4.

      Uniform Interface in Detail

      13:21

    • 5.

      Set up Core Environment

      2:24

    • 6.

      Basic Container Structure

      7:30

    • 7.

      Running the Containers

      4:50

    • 8.

      Pluggable Views

      12:22

    • 9.

      Installing and Using Postman

      7:03

    • 10.

      Our First POST

      9:10

    • 11.

      HTTP Status Codes

      8:53

    • 12.

      A Real CRUD

      9:21

    • 13.

      PUT and DELETE

      12:03

    • 14.

      Simple Authentications

      6:55

    • 15.

      Testing our Simple Authentication

      7:16

    • 16.

      Token API Model and API Endpoints

      14:22

    • 17.

      Token API Views and Decorator

      6:07

    • 18.

      Install bcrypt and Test Tokens

      14:00

    • 19.

      Building the App's Tests

      7:42

    • 20.

      Token Tests

      4:48

    • 21.

      Starting the Store End Point

      3:24

    • 22.

      The JSON Schema Library

      8:42

    • 23.

      The Store API File

      6:34

    • 24.

      Trying out the Store's End Point

      8:17

    • 25.

      Implementing PUT and DELETE

      10:38

    • 26.

      Implementing Pagination on GET all Stores

      7:52

    • 27.

      Store Tests

      11:42

    • 28.

      Pet Endpoint Initial CRUD

      9:34

    • 29.

      Finishing Pet GET, POST and Postman Tests

      10:15

    • 30.

      Pets PUT and DELETE

      4:52

    • 31.

      Pets Tests

      7:45

    • 32.

      Pets Pagination Tests

      3:13

    • 33.

      Get all Pets in a Store Endpoint

      8:52

    • 34.

      Test the Get all Pets in a Store Endpoint

      5:27

    • 35.

      Search Pets with Filters

      7:22

    • 36.

      Conclusion

      1:18

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

567

Students

1

Project

About This Class

This course will teach you how to build a professional API platform using pure Flask, without any supplemental libraries, so that students can learn the fundamentals of RESTful API design.

In today’s world, dominated by gorgeous JavaScript user interfaces and mobile applications, the ability to build a scalable and well architected API is key to be able to supplement those applicationsand ensure that clients and servers communicate with the proper interfaces.

The course covers the basic concepts of the RESTful API pattern and then goes into detail and step by step building an API platform that will cover the six constraints of the architecture. Students will learn the industry-standard and will follow best practices for API architectures.

If you already know the basics of Flask and you are interested in how to design, architect and build an API platform, this is the course for you.

The course is divided in 2 sections:

  • Introduction which covers all the concepts necessary to understand what is a RESTful API and its six constraints

  • A step by step explanation building a Pet Store API that will include an authentication layer, a Store endpoint and a Pet endpoint as well as search functionalities

The course has more than 5 hours of video tutorials as well as the source code at the end of each section, so that you can follow along with the coding process.

The course can take anywhere from 3 to 10 days to complete based on how much material the student completes daily.

Additionally we’re constantly updating the course, adding contents thanks to the feedback of our students.

Join this course and continue your path to becoming a professional backend web developer!

What are the requirements?

  • A computer with internet access and administrative access to install packages
  • Good understanding of how to use the command line interface, internet and code editors
  • Good knowledge of the Flask web framework

What am I going to get from this course?

  • You will learn the fundamental concepts for the design of RESTful API platforms
  • You will be introduced to the RESTful API constraints
  • You will learn how to setup an authentication API layer
  • You will learn how to effectively build API endpoints

What is the target audience?

  • Programmers and developers with basic Flask knowledge who want to learn how to design and build professional API platforms
  • Application architects who want to understand better how to build API applications
  • Startup CTOs who want to understand better best practices for API design
  • Computer Science Students who want to get exposed to real life API building concepts

Meet Your Teacher

Teacher Profile Image

Jorge Escobar

Technologist, entrepreneur and open source fanatic

Teacher

From Zero is an educational project created by Jorge Escobar, a technologist, entrepreneur and open source fanatic with more than 15 years of experience in the development of web applications in New York City.

Jorge has worked in well established companies like Yahoo!, Univision and MongoDB and has also been the technical founding member of various successful tech startups that have received multiple rounds of venture capital.

The biggest problem Jorge has experienced during his career is finding well rounded developers and he interviewed hundreds of them for positions in the teams he was leading. A constant pattern (no matter if candidates came from a good university or had a few years of experience) was the lack of practical, real world knowledge.

That's why Jorge... See full profile

Level: Intermediate

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Introduction 1.1: hi and welcome to professional rest. Will AP I design using FIFA flats. I should like no AP ice are the interaction layer between your database on your clients. However, it is not that simple to build a good FBI that are certain fundamental concept you need to understand. That's what this course is about. We will start with a theory and the concept necessary for you to understand what a good recipe lady. I should have go over in detail covering the particle, and then we move on to actually coding from scratch and without using any rest for library . A robust AP I platform that will leverage those fundamental concepts and put them into practice. AP I sort of the most important piece of knowledge a modern backing application developer needs to have in his pocket and this course there in case you will learn the right way how to successfully the sign architect and code a standard compliant breast plate. Here. See you inside 2. Introduction 1.2: higher. Welcome to professional rest ful ap. I design using bison flask. What do we want to accomplish in this course? Well, we want to build a rest ful AP application from scratch. That follows industry standards. We're gonna first look at the theory behind what arrestable FBI looks like. And then we're gonna code bed by bed and a step by step, a flask application that has all the industry standards off on a P. I service one of the prerequisites you need to know. Python basics on. You should know flask. Introduction and advance. As you know, I have two good courses. One for introduction to flask on the other, a more professional flask application course. What do you need to complete the course? You need to have a computer that has the latest docker client installed. And we're gonna installing that docker service mongo db as our database and of course, flask. So let's start the journey 3. API Definitions: Hi and welcome to professional rest ful AP I design using flask. My name is Jorge Escobar and I'll be your instructor in this new, exciting course where we're going to explore how to build efficient on professionally designed A p I services for anything that you need on a P I four can be to power a platform that you want other people to be, um, kind of like interacting with. Or you want to have people to, ah, consume that via a mobile application, which is a very common use case for AP ICE today. So let's get started. Um, so what is a P? I mean so AP I stands for application programming interface, and it's a set of routines, protocols and tools for building interactions between clients and servers. And what this means is that you're creating a layer off communication between your application, your platform and something out there that's consuming the data and interacting with it. As a matter of fact, you can have an FBI that's right only where you're only giving. That's a weather information for people wanting to get, whether for their for their specific locations, or you can do like a read, Write a p I. Where you have a you know, social application where you're creating users and you're reading and writing posts and and things like that. So it's always this concept of having to separated entities a client on a server that are talking through this through this layer through this Ah, um specification or specified way of communication that's called an a P I. So, uh, what is rest? Rest stands for representation. Representational state transfer. I needs networked hyper media architectural style. Typified, by the way, which means that let's say you have on a P I, and maybe I can have any form. But when you say arrest full FBI, the connotation there is that you're using Web style approach is to be able to serve that content, to be able to interact with those clients, and we're going to see a little bit off more information about that. But the key thing here is that you think about the objects or the data. There were your returning as if they were Web pages with some meta data for, like, next on previous page and things like that, and also you need to think about the way that you interact. The client tracks with your platform is using HDP verbs. So get post, which we've seen in other flus courses. And then we have others like put and elite, which are not so common unless you're starting to work on an A P eyes. Um, so let's take a look at what the six constrains foreign ap rest ful. Maybe I look like so you have to have a uniform interface. He has to be stateless. It has to be fashionable. It has toe conform to decline server pattern. It has to be a layered system on optionally. It gives coat on the man. So we're gonna see each one of these in some detail. The 1st 1 which is unique foreign interface. I'm gonna explain to you in a in A in a second lesson, because I think it's a heart of rest Will FBI. So I want to, like, go into detail on that one. So we'll go there in a second. So the next one is ah, stateless. So what the stateless mean? It means that the the the rest Ah ah, request that you're giving to the to your platform are basically isolated instances they don't have a session toe go with or they don't know what happened before or what's gonna happen, You know, after, and it doesn't like, you cannot identify that those requests by saying, Oh, this is user X Y C Stateless means that every time you do a request, everything that you need to serve or to basically fulfill that request needs to be embedded in that you know, outgoing or incoming requests. And then you're gonna provide back based on those parameters the data that that request is needing where we are requiring, so that this means that every single request is it's a new entity of its own. And it doesn't know anything about, you know, feature past or what's happened so far in terms off the, um of the of the workflow eso that stateless catchable. That's kind of like you can more or less think about cashing, which is, you know, kind of like storing static copies off request. This is related to that and and what rest ful AP ICE must confirm to is that you must tell declined. That's requesting your content. If they can cash or no cash the responsive, giving them so that, um you can have a more scalable platform. And this is kind of like related to let's say, if you have thousands of requests, you know, per second but you could tell decline, for example, that Sam requesting John those, you know, profile. Um, that profile is not changing all the time. So you can tell the client when you return back the profile information. Hey, you know, you can cash this request or store that rictus request locally for, let's say, a day so that will reduce the number off request that you're getting from that climb because maybe another user is requesting the same. You know, John, those profile and you don't have to regenerate and reheat the database and all that. You can let the client decide that you know they can. They can cash that information and the way you you give this information to the client is basically through the cash control. HDB made a data header. And as you can see in that example, you're saying max H equals 1 20 which is like second. So this means that the request I'm giving you back or or the response. I'm giving you back you can safely store for for two minutes. And there's not gonna be changes in the meantime. So, you know, be be confident that you can, you know, you don't have to, like, request this information back within 120 seconds. Um, so there next, um, go strangers client server. So clients ever means that, um, there's a separation between the the suppression of concerns between the client and the server, which means that the client doesn't know what the, um uh what the servers kind of like set up. It's like, what database are the using or what? Um, what is that? The structure of the data that cannot think it's kind of like completely separated on the same way the server is not interested or doesn't have to know that the client is an iPhone six s or an android phone or a automated system that's getting information. Kind of like a Twitter firehose kind of thing. The server is is doesn't know anything about the client. And every time I request comes in, you're just gonna like percent information based on the request back to the client. So, you know you're not like concern about what the client looks like. Um, the next constraint is layer system. And this is talking about, you know, a client cannot tell what are the layers or what is the set of behind the request that you're giving them. And this this can kind of like allow you to do, like, load balancing and have multiple application servers, or even have readies cash servers that are serving cached versions off the information? The client doesn't know that. So, for example, in this in this graph, you can see that there's like, you know, the cloud is Internet, and then the the black box on the on the left hand side is a client, and, you know, he's kind of like making older request to the server. The server is the black books on the right, and then the server has a database that can be like serving those requests or can be serving those requests through like like I said already Scotch layer. So it doesn't really matter how you presenting that information back, and that gives you the the ability to scale your A P I platform without breaking, you know, kind of like the graceful AP I constraints. So, um, the last one and this one is optional. And to be honest, it's not used. Ah, lot. It's called on the man and called on The man is basically you know how like before, you know, in the Web, like maybe a few years ago there was like Java applets and the Java pets were like self contained little programs that were running your in your browser. And he was like a little maybe a little watch or a clock, you know, or a little game or meaning game soul, the a P. I will wrestle a B I, um um spec tells people that they can, you know, provide not only data objects, but they can also provide snippets of code. And I could see this, like being like, nowadays, maybe a flash, a mini flash application or something like that. But it's not very used. And this country constrain, it's not really kind of like something that you you're gonna use often. Um, so that is that Is that for the, you know, bottom five constraints. So I'm gonna talk to you about the uniforms interface in the following less and so stick around 4. Uniform Interface in Detail: welcome back. So we're gonna continue looking at the, uh, the constraints, and we're gonna look at the uniform interface constraint, which I feel like it's the most important. So let's check out what that looks like. So the uniformed interface is divided in four parts. One is resource based. The second is manipulation of resource is through representations. The third year self descriptive messages and the fourth is hyper media as the engine off application, state or hate owes. So let's go through each one of those. So for the resource based, this is basically every resource is identified. Using you are rise as resource identifies. So what these kind of like translating to is that the actions that you're gonna take or the requested you're going to make are ordered or are Have a A Cherokee and structure through the your eye. And your eyes, you might remember, is the part of the euro of the euro that doesn't have the H two b whatever. Whatever server dot com part. So you take that out the first slash and on, that's that you or I, um, and um, that is it's gonna be telling off what type off requests or what are you requesting? And you're going to design your A P I using those your l's or your eyes as you're structure . So let's see an example. For example, if I hit a p i slash b one slash border So that is a new your I. But what you're looking at here is that you are hating the A P I section of the website. You're you're hating the version one of the A P, and you might have. You know, man, it multiple versions. And now you're selling telling the AP either you want to get a list off the orders. So as you can see here, there's some you know, it's kind of like a here key, and and there's a structuring their that the a p I is defining through a good, um, structuring off the off the your eye that you're gonna use to request information. But let's see another example. So this one is now I'm looking at a P I. V one orders 15 44. So, as you might imagine, 15 44 is an order i d. So what you're saying here is that give me the the detail off this disorder alone. This over 15 44. And as you can start to see, there's there's a structure there. If you get orders, only you're gonna get probably a list of all the orders they even hit orders. 50 44. You're gonna get only the details of that of that of that order so elegant and professionally be eyes are set up that way. You're and the way I like Think about it. Is that orders? Is the flask up? Whereas we have, you know, the folder orders and then inside you have use models, tests, etcetera that should more or less match the first part of that, you or I, and then the 2nd 1 is more like a like an I d like, you know, it's It's kind of like a view. Oh, our controller kind off situation where you're or if you're passing that I d then then just returned back that I d. So we're going to see these things in practice when we start working on our FBI. So, um, the one thing that you need toe think also in in in this in this gulf stream of the resource constraint is that they're resource Is that your, um um, that you're sending to the client are separate from the from the representations or or the structure that the that resource has inside your A P I. So, for example, when you request orders and and, you know without without the I d, you're not going to get like a query are gonna get, like all the like, the fields that are on the database, you're going to get some structure information and that usually has a, um, a structure that is defined depending on what the client looks like. If it's, ah, it's a computer if it's a mobile application or what they needed specifically. So, for example, you could return html XML or Jason. So but the thing toe to think about here is that you're not just gonna, like dump, you know, the whole query when you got the orders or are all this older fields. But you're gonna like, you know, return something that structure and that you're gonna be defining in your in your a p I definition. So the 2nd 1 is the manipulation of resources through representation, and they say this kind of like it's tied with how the clients will ask for what type of representations, Um are going to be thrown back at them or returned based on the on the except http header that they're sending. So, for example, a client that is a mobile application might say, Hey, I need the orders 15. 44 But I want it in Jason format your A P. I should be intelligent enough to read that except http header that they're sending you and returned back the information in the in the format that they're asking where us maybe like ah, Web based or a browser based application or client might be requesting html. And you're gonna know throwback instead of the orders in a Jason Foreman, maybe, ah, snippet of html with the with the different fields off that order in HTML format. So you're a P. I needs to be flexible enough to accommodate and and throw back or return information or data using the thea the data that the client is requesting. Um so the 3rd 1 is self descriptive messages, and what these entails is that the, um, the request themselves are represented via the HDP verb that declined is asking. And we went through a little bit of this owner flask courses, which is, you know, the get requests. Remember that when you do a get request, you send all the fields in the actual You're also you have, like, a question mark. You know, uh, field name equals feel data. I'm percent. That said All right, that's again request. Whereas a post was more like within the body off the off the http request you were sending , you know that the actual fields that you were, um, you were posting toe toe, toe the server, right? Well, in a p I world get post put and elite are actually, they're what we call the crowd that create read, update and the lead operation. So Gadd means I'm going to send a request to get something from from the from the FBI. If I send a post, it means I'm creating a brand new record. And I'm sending that the data for that, for the record in the post, you know, data payload of the H two B request port is an ah, one that that we haven't used a lot and you don't use normally like in in Web applications , But it may be, as you do use, which is another update. So you're not creating a new record. But you're basically saying update this this record these order with this new information that's a has a new you know, invoice total or you want to modify the items within that order. So you use put to do the that. That update on the lead, which is an actual http verb, is as you know, you didn't tell Torrey it references. You want toe the leader record, and, of course, you need tohave the proper authentication, and you have to have the authorization toe the live records. But if you are, if you're implementing that and you have the proper authentication than you're able to delete records. So that's self descriptive messages. And the last one is hyper media as the engine off application state or hate ALS, which is a weird kind of like word. But what this means? When I read this, I was a little bit confused and I couldn't understand what they were talking about. But it's in a nutshell. What this is, is that your your a p i. If it's arrestable a p I. He needs to act like a webpage in the sense that you can send not only when you get the orders you know a request. You're not only dumping the orders back to the client, but you're also putting some major links that say there are total off 1500 orders. This is page number one. And if you want to look at the next page, this is the euro that you need to hit. So envision that when you when you when you hit orders, even though we're returning Jason information, which is what we're going to be used reusing mostly think of it not only has just data, but think of it as if it's an application. It's a webpage. And you have like a table where you see the the order like dump. But it's only the 1st 10 results, and they have, like, a previous next on the bottom. And you also have, like, some sort of like, maybe bet breadcrumb on the top. So that's what hey does means is that you're a B. I should kind off like use hyper media on major links and things like that to kind of like , Tell the client A I'm here, but you can also do these things. Or if you want to update the balance, you can do this operation, etcetera. So let's see. Kind of like an example of that. Um, so here we have a, um a get request to get account number 12345 So the top line is kind of like what the client sent to the FBI and the HDP 11 200. Okay, is what the FBI is returning. And as you can see there you have, like, you know, the account number, you have the balance currency, and you could stop there. You could say, OK, that's all. But since you're doing hey, does your also having this link Rehl, which is an actual, like valid HDP, you know, or extreme el tagging. And you say If you want to the pass it, you can do a count. 12345 slash the pass it. If you want to withdraw, you know, and you get the idea. You're kind of like helping the client toe maybe make decisions, and that includes transferring or close in the account. But there's another layer to this. So let's say, for example, that now the ah, this a counties is overdrawn. And as you can see on the balance on the currency oh, are on the balance field, you see that? It's minus 25. So the a P I hear should be intelligent enough to say, Wait a minute. So the only action that the person can do here is deposit like meaning. Get this account back to, like, positive, Right. But they shouldn't be able to withdraw. They shouldn't be able to transfer, or they shouldn't be able to close this account. So, you know, the great lines is what we're going to like make disappear. And this is what you're going to get if they the the account balances is negative. So this is hey, does right there's like, You're not only returning data, you're also like reacting to the data that you're kind of like using so that your, um, your client is able to make the right decisions, and you're like kind of like guiding thread, guiding them through the proper channels. Um, so that's that. That's that's that the whole thing I know there's a lot of fear here, and unfortunately, I must wrestling before. Do I just give the students kind of like these concepts as we go along? But I think even if you didn't get the whole thing, it's fine. You can review this later when you've done the course. Or maybe, you know, review it. Ah, at a later time. But this will give you kind of like a very good. Um um, you know, handle off. What a professional. Well, the sign rest will FBI looks like. So let's start courting our FBI application. 5. Set up Core Environment: welcome back. So in this lesson, we're gonna start setting up our basic environment. And as I mentioned, we're gonna use Docker, the doctor client for Mac or Windows. And if you have a linens machine, then you can use the docker system or library for for limits. But I guess most of us are gonna be working on the docker client for Windows or Mac on. You don't have to know Dr in detail. I'm gonna go step by step. The only thing that you need toe do beforehand always download the doctor climbed, um, for your for your machine. And if you want to know more about docker and learn more how toe fed up your docker file and you know, Docker compose. I have a course that you can check out. But in the meantime, let's just, you know, start doing things that by step and just follow along, and so let's start. Okay, so the first thing you want to do is you want to go to docker dot com and get started with Docker here. And after that, you're going to get a download doctor for Mac. Um, if you're on a Mac, of course And if you scroll down, there's a doctor for Windows as well. Although they should be positioned in the operating system that you that you have. But in any ways you download that. And after that, you're going to get the the little docker Aiken, Um, and follow just the, you know, the set up installations after you have downloaded the Docker client, um, and you we run it. You should see this little whale there. And it should say, Dockery's running now. One thing and this I mentioned on the on my course you should have the file sharing volume that you're gonna use for your application in here. In my case, you know that I'd like to work on the O. P. T. Ah folder. So I have o p t. There. And if you don't see the you know the father there, just like click Plus and then go to the folder that you want to add and ah, and then, you know, apply and restart is going to like, you know, just shut down and come back again. So make sure that you have that checked 6. Basic Container Structure: in this lesson. We're gonna set up our base container set up using docker file. We're going to write a docker, compose CMO, and we're also gonna have the application factory for the flesh application. So let's quickly coat through this. We've seen this set up in in other courses, so we shouldn't be seeing any anything new. So let's go ahead and do that, Okay? Here we are in our terminal, We're going to go to the O. P. T folder, and right now, I don't have anything in there. So I'm gonna create my my folder, and I'm gonna call this pets Dash a p I. So now we have better be I there. We're gonna see the to it and clear this great cream with Come on, K and s. So let's start from the very beginning, I guess. Ah, the requirements. Txt. So in order for me to do that, I'm gonna start my Adam editor. And here I'm ah, pets. Ap I So when I do any file and call it requirements txt and ah, Requirement 60 has all these libraries. Some of those you have seen, we're gonna use flask your 11 flat script find Mongo, Mongo engine flask, mongo engine and then by B crypt and Jason Scheme is the one that we haven't seen before. But it's ah, it's a very useful Jason validation library that we're gonna be using. Now, remember, you need to put all these exact numbers and and libraries in this order for ah you to be able to follow along the course. Otherwise you'll see little problems here and there and ah, on and off course. If if you post some question regarding you know, some library and you're not following this requirement 60 I'm not gonna be ableto help you . So that's our requirements. Txt. The next thing we're gonna do is a setting speed. Why? And we're gonna have ah, secret key. Debug equals true. And we're gonna use Munger to be host and mongo db Devi. That's ah for Flashman. Go to be And here we need to be using Munger TB. Ask the host. So that's that. Let's go ahead now and create a manage b y, which we use with, uh, the flesh script. And again, nothing too complicated. Here. We said that path where the file is, then we import Monier and server from flat script create an app. This is like the factory method or factory pattern. And then we at the command drone server, which is gonna run on 4 5000 And finally, we run the application. If it's if it if it's being run from the from the terminal. So, um, so far so good. Now, let's create a application fee Y, and this is gonna look like the following. We're gonna import flask and mongo engine, and then we know start to be us A viable for the Mongol engine. Instance, we're gonna have a create up, um, application factory application, uh, setting up with the settings B y and allowing the overwrites from test starting there d be . And then we're gonna just important blueprints from home views. We're gonna have a home app and then registered that blueprint. Now, notice something here. Um, I think that in the repository, I have slightly different version of this. I think it says flask. Dottie Exterior mongo engine. But beginning with flask, I think Cyril 10 or 11 that changed to, um to be used like this flask on the score. Mongo engine. It will work the other way around, but I think you're gonna get some deprecation warnings. Now, let's go ahead and create the home folder and we're gonna have AAA, innit? File. They're so that it's, um, consider a python package. So in it not be why we put nothing on that file. And then we're gonna have a views p y here. And we're gonna have the following on that file. When our import blueprint, we're gonna register that blueprint. And they were gonna say that on that route, we're gonna print Hello, world. This is so yet, you know, we know that the container is working properly. Okay, We're almost done. Let's create the docker file and the doctor file. So I'm gonna look like this. So we're gonna have a base image with 3.4 slim. We're going to run and apt, get update and installed these libraries. Then we make a local directory in the container and said that asked the working directory, and then we copy all the code that we have in here. Run peeping stall and start listening to 5000 when we started the container. And finally we issued the command by 13 minutes. B y ro server, which is Theo the you know, the flask script endpoint. So that's almost it. The last thing is, the doctor composed piano. So we need the stalker composed the e m o. And this is what we put in there. Version two services web with this volumes installed. Now, remember, those volumes need to be the same as the one that you have in your local computer. Um, And then we're gonna have a DB, which is pulled from the image Mongol 302 And we're gonna call that container. Betsy P I d. Be one and the Web container pets ap I Web one. Um, and this has to be this, like your local directory. So in my case, it's, um, this folder here ups opt bets, a p I, and that should match that one there. And then locally, we're gonna have that in there. So that's it. That's all we need to get our initial container set up. So let's go ahead and ah, and build this container 7. Running the Containers: welcome back. So in the last lesson, we set up our basic docker container that's gonna have both an application container and a database container. And now we're gonna test building this container and seeing if everything is working correctly. So let's get started. Okay, so the first thing we're gonna do is we're gonna have We're gonna put ourselves in the O P . T. Ah, bet's FBI folder or whatever folder you decided that you were gonna use and make sure that you have your docker compose file in there. Also, make sure that you have DACA running. I think I'm not running it here, so I'm gonna just start it and I should take a couple of seconds and one studies up. Then we're gonna use the following. We're gonna say docker, compose, build and what? That's going to do it. It's going to ah, look at the docker compose. Um oh, that we have here and build those images for or or the, you know, container images that then we're gonna be able to run from. So let's do that. So now it's getting all the, um basically the libraries that are described on the docker file for the for the Web application folder. Okay, now it's running the requirements. Txt perfect. So now it's Ah, it's built e the containers. And now we're going to, um basically copy the not copy. Wrong the, uh, manganese be server separately from the Observer. And the reason for that is that when we have to restart the application server because we have made some errors or need to, like, a hard refresh the code we don't have toe, you know, bring down all the docker containers on, bring them that back up. We're just gonna do that with with the application container. So we're gonna bring the database, um, among going to be by doing doctor composed up Dutch Day, which means demon and then DB. And now the docker container for the mongo DB is running. And we can check that by doing Dr P s. And you can see there we have um, the ah among go here. I have a another container, I guess from I guess this is from the other course. I'm gonna stop that container so that we don't get confused. Turn off Wi do Ducker ps. You see that? Among the DVD's running there. Now we're gonna run the, um, the application server. But we're gonna do a trick here that I covered on the docker course which is running it with the service ports option, which allows us to do PDB said trace on the on the container on any piece of the code. And it'll stop and allow us to investigate or ah, the bug, our application. So let's go ahead and do that. Perfect. So it says that it's running now on HDB seriously. Or 5000 which is the local directory. I mean, local host. And if we start another browser here and we put local host, we have Hello world. So that's our container that's running on. We can check that. It says in the world here on the home V S B y. If we change that toe Hello, world exclamation point and save. We should see that that this was reloaded, that it detected a change. And if we reload the page, you see the changing. They're so perfect. We have a functioning container that has Mongo DB and a Web application. Um, and you'll see that it list Ah, um all the operations here in this window. You can run this as a demon as well if you pass dash D. But for now, we'll just ah, you know, be happy and celebrate that are set up is it's up and running properly. 8. Pluggable Views: in the last lesson, we successfully created our flats container, and now we're gonna create a first initial version off the a p I n point. Well, there's no not going to be fully set up as the prophet Professional one or the Production one. But I want to introduce guys to flask probable views and then set up a very basic pets endpoint so that you can start grasping the concepts around flask puggle views. So let's start taking that up. Okay, so let's take a look at plausible views, and this is new from version or 0.7. Um, and probable views are inspired by the generate views from dango, which basically allows you to do views based on classes instead off making them functions. And he is a basic example. You have typically have a show users and, um, and that users will get ah, you know, first get all the objects from the database and then render the template passing the users toe that toe that plane template. If you do this as a plug of a view, you instead create a show users views of class. Are you suppress it from flats views and they have these concept of dispatching a request, and then you put users there and then return the render template. And then you you do this. You add the Ural Rule and then have the view function v the method off that show users view . And this is a little bit complicated toe to grasp if you haven't used, you know, probable views or or class based views in in the angle. But it's essentially a trying to get more abstract or disconnect the the templates from the from the actual methods or things you're trying to do. So, for example, you could do something that that's like a list view, and it's a very generic Um ah, method or class. And then you would have something like a use review, which is a subclass of, at least for you. And then you were passed just like these two things, and you immediately now are able to, um, to show anything that's a list of things without having to repeat that over and over again . Um, it's ah, it's something that's ah, easier to grasp by practicing with it a little bit, but I won't ask you to do that because we're not gonna use this specific implementation of the plan of abuse, but rather we're gonna use something called the method based dispatching, which is perfect for rest Philadelphia ap eyes and the here. What we're going to do is we're gonna have, um, a class for each AP. I method that is is going to have different methods, and you can just to find them by, get post etcetera. And then you can add a rule for that user endpoint to return the, um, that class and Ah, and, you know, intelligently route if it's again, if it supposed etcetera. Um, but we're going to see that asses We go along in this very first bets example. So let's start building a, uh, that basic bet, um, endpoint so that we can kind of, like start getting the concepts off the probable views and how we can use that. So I'm gonna close this tops here, and I'm going to create a new, um, a new folder called Ah uh pet. And that pet is gonna be the ah, pet endpoint. And of course, we need to have a needed me. Why there? And we're gonna have a ah views fuse B Y, and we're gonna have on a P I p. Why? Which is the one where we're gonna have the actual class for the probable view, and we're going to fill that out later. But the first thing we want to have a screen, a blueprint and add that to the application people, I So let's start that. So here we have, um, uh, from, uh, pet views import pet up and then register that blueprint that register below print bread. Okay, it's another we fight it that now we can start working on the A P I p. Y. And what this is gonna have is we're gonna use the meth abuse. Like I said so from, uh, flask views, import method view and from flask import his son. If I request and abort, we're gonna need these. These three things on our on her pet, a p I. So the first thing we're gonna do is we're gonna, um we're going to create a pets array. And of course, this is so that we can check this out very quickly. But the idea here is that this would be stored in a database, not in a in a dummy array or static. All right. Right. But I just want to get like this out, um, up and running. So I have my, uh, in a great three. Ah, pet objects here. And these are actually my lovely bets, Mac, Leo and Brownie. Okay, Next thing we're gonna create is a method for this to, um for the get and you just put that get. And in return, they certify the ah, this bets array that we were the funding here on the class, and we should put out a little space in there. Okay, so let's save that. And now we're gonna, um, go to their views, B y. And we're gonna allow the, um this this view to access that plug above you. So But the first thing we're gonna create the blueprint for this like we defined. So from that a p I import that a p I, which is this. Um Well, I forgot to put the glass here. That's right. So So I have I have the class here class bet a p I, and this is a sub method off method view. Now. We so see how we have method view here in the top. So method view is that class, um, and we're sub classing it on payday p I and that method has a get, um, get method a post method, a delete on, put just like the create read you update and delete methods off an A p I and, um and here we can We can, ah, reference self pets because it is a class. So this is this is the self that bets that were defining there. So this now we're importing from parity our import therapy, which is this this class here. Perfect. So now let's continue on. So we have, um the pet app is gonna be the blueprint off, Um, the bet up and then name. And now notice how we're gonna do this as the probable views that we example that we check their earlier soap it up. Add rule. Sorry. At your a rule, and we're gonna have slash pets and notice that I'm ending this with a with a slash. So we're not doing this as you might expect, and this is very important. This is kind of like an A P I, um um Syntex, which means that it kind off like think about it as a folder, right? When you when you're typing a folder, you put that slash at the end. And what that means is that we're going to create a collection off objects that are within that folder. That's kind of like the, um, the thinking behind it. But just remember that to put ah ah slash at the end, if you're going to get a set of things from the, um from that a p i n point. So then we're gonna do view function equals that a p I ask for you and then pets Perfect. So see how simple it looks Very simple, very elegant. So we have our blueprint. We have the baby I being imported from our bet a p i B y. And we just instance she ate the blueprint. And then we just add a rule that says, If somebody hits the pets, endpoint just passed us the view function the ah Perry p I. Class and in the class we're gonna define Gadd posts and all the things. But for now, we're just doing the get part of it. So let's see that, um, we had that running. I take this on on, get up So you guys can access it, But let's, um so if I can get that running again theories. Oh, okay. Perfect. So now if I hit the local the host slash, uh, pits, I get the result there. And let me put this on a little smaller so you can see that that it's being returned aside . Jason, list off objects. So perfect. This is this is working perfectly fine. Um, And now let's go ahead and create a post method. But before that, we're going to explore something, a tool that's gonna be very useful. Um, that's called Postman. So I want to introduce that to you. And, um, it's It's a indispensable tool for for a P I, uh, development work. So let's check that out. 9. Installing and Using Postman: on our last lesson, we instance, created our first version off the A p I with a very basic bet endpoint that allows us to do a get request and get back a list off pets that we set up as a sauna Ray within the class. But now we wanna, um, do more complex stuff, like do posts and, um, maybe send some some payload data within those requests. And it is a hassle to do this using the browser or even a terminal, um, like, terminal like command line. So instead, there's a very good tool called postman that I've been using for many years now that allows you to, um, manage and create this this request and get back the results in a very nice fashion. Nicely formatted. So let's check out how to install postmen and how to use it. Okay, so let's go ahead and, uh, find the, um, post mint. A p I you can do post meant for Mac, and this was initially a, um a plug in, and it still is applauding for the for chrome, But but then they built a kind of like the native, um ah program or application for you to download. And there's one for Mac windows in chrome. So I'm gonna use the one for Mac, which is the computer I have and it Ah, it now is downloading right here. And then you just clicking there and you should have it on your downloads, and then you just drag and drop on your applications. So now I have postman in there. Um, and that's it. It's pretty pretty easy. So now I'm going to, um, double click there, click open and here have post manned. No, Um, if you want to, um, like, store and synchronize your A P. I like endpoints o r or request. You can sign up and you can use global, which is, I think, what I did. Um, or you can put your email using and passport. And it's a useful thing, because if you're, let's say, testing this on on your computer at home and, uh and then you want to something, you know, in another computer in the office, maybe you can just, like, sink the account, and then you'll have all your collections, um, off off endpoint tests. But for now, let's just skip that and this is like the main, uh, the main screen for the application and the way you tested out with you. Initially, you just do a get request here, so I'm gonna to It's to be, um, local host and then pets, which is what we had on the, um right here on the browser. And we got this results here. Right? So if I do that and they hit send see how I get the, um I get the formatted version off the off the Jason Hodges, which is really nice. I mean, I like to get these things like formative and stuff. Um, so here it's saying that you can save your request so that you can manage it. And that's what I was telling you. If you register, you can synchronize these things across different computers. But so what I'm gonna do is I'm gonna create a collection, and hopefully you'll have, um, you'll have the ah, the synchronized version of this and ah, I'm going to I don't need this. This is kind of like a test one. He's gonna delete that, and I'm going to create a new collection, and I'm going to call it bets a p I and you can do this for your like, you know, every application, your writing and stuff. So within a collection that you can have requests. And now I can save this requires because I know that every time I use, um I wanted to the get requests. I'll do it with this. You're all right. So I'm gonna save this, and it's going to say in which collection and I'm gonna say pets, A p I And here you can put a description. Um, I usually like to put a the name as theatrical like, um, the finishing what this is doing. So I'm gonna say, uh, get pets endpoint or something like that. Um, and then you're safe and you have your descript use descriptive, you know, information there. So that's this is within the pet. CBS. So if I click on pets FBI, see how he gets, um called collapsing there. Now, what I also do is you can create sub folders. So if you have, let's say the pets FBI, you can create a so folder here and and then I will do anything. That's the that's related toe bets. I can create that folder there and then I can drag. There's, like, you know, kind of like long clicking and dragging it to the pets. And now I have my sub folder with my request there. Why? Because, um afterwards I'm gonna have a store, you know, and point that I might get older endpoints. So then I have all everything kind of like nicely organizing their So that's that's basically postman in in a glance. It's a really good a piece of software that I used, you know, I like I said, I've used for years when he just started as a chrome plug in, and now that he has, it's, ah, standalone version. It is really useful. So with this, the next step would be to create a post endpoint for pets and it see how we do that. 10. Our First POST: Welcome back, eso in this lesson, we're going to see how we do. Um, actual post which, as you know, post A is equivalent to creating a new record. Um, and as we saw in the last lesson, we started to use postman as a method or a way to be able to interact with our A p i in an easier way. And he's gonna really shine in this in this new example, which is setting up an object that we're gonna send toe the post endpoint on our pets ap. So let's take it up. So here we are. Are are a p. I bet a p I and we're gonna add a new method, which is the post method. So what we're gonna do is the following. We're gonna define a post the same thing as the US itself, and then we're gonna check if there's no, um, Jason payload on the request. Or if the name name is not on the on the request, Jason, then we're going to return a, uh, a 400 error, which is on we're gonna take a look at some of the h two because but that's kind of like a , you know, kind of like an expected heir. So then if we have those things, then we're gonna, um, basically add a an i d toe the length off that rape that's array and increasing by one. And then we're gonna have the name that's been passed on the post, Toby, the name on that pet object. And finally, I'm going to upend the that object to the to the array and return. Um, that new object, which is kind of like a regular, um uh, let's say mechanism or or ah, philosophy when you create a new record, is that you kind of, like throwback to decline the record that you just created so that the client can confirm that that you created the right record and, um and also we're gonna have a us you can see here a two a one, which is a another edge to be code that's meant to say this was created and, um or basic or brother. The request was received, and I'm going to Ah, I actually created a new record, so we're gonna take the HDB coats in a bed, but let's just start stick with this. I'm gonna save this. And I have docker here running in, uh, in my computer. So I'm gonna go now to Postman, and we're gonna, um, basically create a new, um, a new request that is gonna be opposed. So here I select post. And as you can see, I selected a new tab. Um, in this plus sign, I'm gonna create I'm gonna put the pets here. Oh, and I also forgot. I just noticed when I was checking the recording that this didn't have a trailing space. So, as you can see, there's a little red dot in there. That means that this hasn't being saved here in the collection, so you can do Ah, um, comment S O R, uh, thing you can do collection. Oh, here, you this safe. Or you could do commend this. So I'm gonna save this. And now that that endpoint has being safety here in the Indian, the collection so perfect. So now have the post. But as you know, Post doesn't send the actual request or the data on the on the euro like the get request us . So I'm actually half. I have a body here that is a, um, kind of like, a tab that I can pass to the to the request. And here I'm gonna send a raw, um, most select role here. You can select form data. Um, you can select Ah ah, for mural encoded. You can have binary. Like, if you're if you're uploading images, and here you can select what? Type off off, um, raw data. And I'm gonna select Jason here. Now. What that does is now you see it Headers has a new option there. If I click there, I see that it says content type application. Jason. So we're sending this on the header. So the climbing sending this with hair saying, Hey, Mr A P I I'm sending you a request. Have some some data in the body on that content type is application, Jason. So that's that's how you, um, send in and tell the FBI what type of content you're setting, which is part of the arrest. Full. A. P I, um constraints, as we saw earlier, is that the climbing forms what type of off information it's it's sending, and also through the through the verbs, the post here they get. It's also communicating What the what you're, um, your request or what? What your intentions are when you are when you're posting this. So ah, here. I just need to add something like this. I just put a ah bracket and then a foot name. And then I'm gonna put, um, my hamster's name Lalla. So that's that's gonna be the request. So when I send this, it's going to go into the, um into the post here, and it's gonna have the name on the request, Jason. And then I'm gonna be able to add that to the to the object and then append toe this tow this bets, uh, array. So let's go ahead and try that. I'm gonna let me save this, and it's going to say where I'm going to save it. Um, I'm gonna say this is post pets endpoint, and then I'm gonna put this election pits a p I in the pets folder and safe. So now I have the post in their second. See? Okay, Perfect. So let's try it out. I'm gonna put some light in here and then send perfect, so lets there's a lot off information here that I want you to look at. So one, I get status to a one created. And as you can see, postman has this very nifty library off HDP codes that says the request has been fulfilled and resulted in a new resource being created. So we have created up essentially a new resource. It also tells us how much it took and the size off the of the response back, which was 204 bites on that. You can see. Here's what the server return. You can see that I D four is now the the I d for that, Laleh. And of course, it makes sense because we had, um, up to number three here. And additionally, response back with headers, which include information about the content, length off of the returned information. It also says that it's it's gonna return back application Jason Format. He has a date of the request and also what type of server, which in this case, it's a you know, uh, work soy by fun. 34 So this is automatically put by the by flask, and it's it's really useful for for clients. But in any case, we have successfully, um, created a new record here and Of course, this stays in memory. We're not saving this anywhere on a database, but in any case, it's still a pretty good idea or concept off. What? Um, the different endpoints for For this a p I is gonna start looking like 11. HTTP Status Codes: in the last lesson, we took a look at creating a new record using the Post Request. And of course, we got this kind of like a brief introduction into image to be caught, which was to a one with, um, which corresponds to creating a new object, um, in image to be called. But I wanted to, like, briefly go over some of the http status code because I think it's important that you start getting acquainted with ease and really make sure that you're returning back the correct air Northerners, the correct status codes because they're very specific to operations. And I have This is a very good resource that I'm gonna put the link to on the course, which goes over some of the, uh, or most of the status goes but also puts a little kind of like star on the main ones, and we're going to go through them quickly. So let's start with S 0 200 So two x axis, it's toe oneto four, and any code that starts with with number two, the 1st 1 is 200. Okay, which eyes Essentially a request has has succeeded. That's the one that we returned back on the ah, here on the get. Although we don't specifically say there, but flask is returning it for us. But maybe it's a good thing to just, like, you know, explicitly Call it out. And as you can see, return in in in flask allows you to put this little comma and then an amidst typist Ask old code, which is really useful. Um, so let's say that so let's continue looking at the some of the status codes, Um, and noticed that when I click here, I got this, like little like expanded, uh, section and here excess also, what you should have on the head on the post and trace, which is, you know, different, different, kind of like, uh, methods or h to be, um, kindof requests out that were doing, but, um, so 200 it is okay to one means that they're just like we saw before is fulfilled and resulted in a new resource being created. Um, the You know, the newly created resource can be referenced by the your eyes. Return in the entity of the response with the most Pacific your eye for the resource given by location. Header field. We have not done that. So where we just returned? As you remember, the, um we just returned the resource itself or we didn't return this. And this is a good thing to start thinking about, which is there Hate owes kind off like, approach to things. Right. So we're gonna fix that in in a in the next lesson. The next one is two or four. No content. And this usually means that, um, the request Waas was received and he was properly, um, process. But I don't need to give you back any any any data because you didn't modify the resource. Um, and I think we use this when we do the elite. That's right. So on the lead, because you're building the record, you don't necessarily need to return the old record because that's already deleted. Eso you? Usually you don't want to return that 200. Okay, because, um, it's kind of like, OK, I got the responsible. You're not telling me anything about it. It's just like I got to response so to a four was created for that. It's kind of like I'm giving you a confirmation that I got the request and I did something , but I'm not sending you back, Um, the any object or any date So to a four piece. Perfect for that. So now we get into the 400. Usually don't. These are air. So 400 bad requests. That means that the requests Ismael Foreign, it means that you're supposed to be sending something or you're not sending that back. We got that one here on the on the post. If there if the person or the client is not sending the Jason request or is not sending a field called name in the request, we're sending a 400 which is the correct way to refund to that. Um, so 400 means that you did send, um, you know, the information on we got some some some information, somebody or some get request. But you needed to do something else. Either. Include new, uh, new fields over there. You know the name of the field. It's not correct, that kind of thing, Uh, for a one will see when we when we have authorization. Which means that kind of like a log in, right. We're gonna implement a an application log in eso that Onley register applications can drive with our FBI for a one means that you are not sending the proper credentials. So I'm kind of like not, uh, you know, I'm not gonna be able to fulfill your your request, um, similarly four or three, even though the difference that little you know, kind of like different but it's related for three is returned when you do pass the correct log in and password, but you're not specifically authorized to do that. Action off may be creating a new pad. So, for example, let's say that you have one type of user that can get all the pets from your from your server, right? But you have another kind of like author or or admin user name and passport that allows you to actually create. So, um, this would be returned, for example, for the first user that it's only even though he's loved in and password are correct. He tried to like post and create a new object, and we returned that for three 44 means that I didn't find the resource, and this can be kind of like if you may spell the you know, the girl on. Usually that that's kind of the case. Are you misspelled? Um, the I d off a specific object or resource. So, you know, for four you've seemed for four in the past, when you kind of, like, go to a website and you missed mistyped the page name or that pitch was moved somewhere else and didn't return a a 300 code, um, for nine is conflict on. That means that maybe you're trying to insert a new pet that has the same name off on existing pet so you could return a for nine, meaning that the, um, that that the user is is sending information that's gonna be, you know, conflicting. And finally, the five, The 500 Siri's. They wonder you're gonna use the most ease. Five funding internal server, which is return when something kind of like bad happened on the server side. This would be like, you know, that ibex went down or the, um the application server, uh, is generating a mirror that's not being caught in a try except code. It's just like, you know, throwing up, you know, so flask will usually return back this automatically and and the client is informed that there's a phone for, AH 500 which is, you know, basically the there's a problem with the server, not with your requests or the way that you're doing things, but something on on our end. So said the main ones, you know, it's good to just take a look at some of these others and get acquainted with those. And we're gonna use ah, bunch off this on throughout the course. So let's go on. Kind of like start adding some made a data to our to our pets objects eso that we are, um, more kind of like, hey, does compliant. 12. A Real CRUD: So in the last lesson, we checked out the http status codes which is useful for the client to get information about what happened with the request that was supposed to tow the A P. I server. But now what I want to do is work a little bit more on that pets endpoint and ah, making more hate, owes compliant, have some made a later there as well as enabling getting a specific a pet through their I d . On also implement the put and the lead methods. So let's start doing that. So let's start by heading over to the pet of use B y. And I want to, um, make this more, I guess, Ah, a little bit more scalable. And what? I'm going to just go. I'm going to replace um the view Toby a, um a viable so that I can then make different methods for it. So the one when I do this is I'm going to do a pet view, which is gonna be equal to the pet ap I ask of you auf pet, a p I so announce me to now insert that line too, to the different methods. So the 1st 1 I'm going to do is I'm going to the get But this is the get for all the pets. So I'm going to do this pet up at our euro pets. And when I pass on, you can do this Default paid I d. Because remember that we're gonna tow a individual, get later on, um and this one would be for all the beds. And here can do pet view us the view function, and then the methods that are gonna be for these for specific your rule is gonna be get. So this answer is going to be when we pass bets. And but there's nothing else there, so that's to get older pets. But since the function over the over the method that I'm going to create here on a p I for for the get is gonna be no splitting to, um one. It's gonna be if you pass and I d and the others. If you don't pass the I d. And then I'm gonna put this default, Toby pet, I d equals none. So the next one going to do is the post, and it's gonna be similar at your rule and then pats. But here, I'm going to just put the method Toby post here we don't have, you know, different routes. It's just like that one route, cause you're always supposed to the to the pets and point. And finally, I'm going to do the method for the, um for the get individual I d put and delete because all those require an i. D. Toby passed. So I'm gonna say Pat's ain't interviewer off paid i d. They'll be functionally spent view, and then I'm going to have the methods get put and elite perfect. So now you see how we have, you know, the different use cases the 1st 1 would be when I get all the pets, and in this case, I have to pass. Bad idea was not because I'm gonna be expecting that on the on the a p I level. And then I'm gonna have the, um, the one for the post, which is create anyone that doesn't have any in the use cases. And then finally, when I pass pets with an interviewer pet I d. That can apply to get put on the lid. So no notice that we're not doing there they even then, Kind of like the switch cases in the interview itself, which is a nice thing that applicable views gets us that will be decided here. When? When we're when we called the Perry P I. It's gonna intelligently send us toe the proper method depending if we get post boat or delete. Okay, so the next thing I'm going to do is I'm gonna head over to the A P I and I'm gonna insert , um here. Ah, little bit of hate owes. So I'm gonna have the lynx, A lynx section that's going to say, What's the euro to get to that resource? So I'm just gonna copy and paste this and it says links and it's an array, so you can have multiple links in the object. But the one that were defining is self, And this rehl eyes theme. It's kind of like a use off hdb, um, acing taxes where this is saying, What's the relative, the relative kind off like what? What's the relation off this off this link and you can use rail self or you can use rail equals, I believe underscored new If we want open in a new window. But in any case, this is referencing itself. And it's saying to get to this resource, you need to go to this area treff, which is pets. Ah, slash one. Someone is the same thing here, but in this case is gonna be bets slash to. And as you can see, this matches the idea, right? So if you hit bets to, then it's gonna get Leo. If you hit, that's one you're gonna get, Mac. And finally, bets three. Then let's get Ah, let's get working on the get um, that was a bad joke. So we're gonna have a pet i d now, as I mentioned and remember what we did here, which is like, if if the if the pets function off get has no i d after it, then we're still passing. Paid I d known so that this doesn't break in here. See, that were required. This is a required parameter on the only function. So we're gonna say Eve, Um, if that i d and this is like if you want to get the, um ah, the specific pet, then you're gonna do the following. So we have the pets array and then we're this obstructing one, because remember that our race or least start at zero. So I'm just saying, get me the pair I d. That's being passed there. And and so threat one So that the i d for, um, for Mac, which is one would correspond to the zero element, and then for Leah would be the one element and so on. And then, um, we can get rid of this, and then we haven't else. Then we just say return. Oops. So this is for when I want to get all the pets pats. And then I just passed the, um the whole A ray in there. Okay, so that's that's to get function. Um, and the other thing that we want to modify here is through the is the links. So we're gonna have the same thing here, so I'm gonna have links. But I had the wrong thing, copied and pasted. He also links, and then it's gonna be relative self h era a raft pets, plus the string off the length off that pets. Ah, Ray. Um, plus one. So let's he have so have the strength off the length off self pets plus one So this is the length plus one here, and that's the string of it. Ah, why? Because I'm creating a new record and it's gonna be essentially one plus the, um, the number off elements in there. Perfect. Um, I think that's that's it for for the things we wanted to do. We're gonna do the the put on the lid on the next lesson, but let's start test this out. 13. PUT and DELETE: So let's try the ah, get requests first, um, and see if we get the same results. So we have to get endpoint here. Um, I have Dr Running, and I think I have the Yeah, this stuff is running a swell. So let's do we're getting here and perfect. So here I see the, um the different. Ah, let me see if I can. No, it is to copy. Um, I wanted to, like, expand this. Oh, there you go. A little bit. Okay. So I see their spits. You know, I d links HF pets. One real self. The name is smack the same thing with pets to etcetera. So that that worked. Really well, I'm not passing an i d. They're So that means that the, um, the function is is getting into this else case because there's no there's no path. And of course, this bed I d. Said being said to none because this is setting to known on the get request. Um, because I don't have anything after it. Um, where us when I do the individual one. Um, I have this pet i d. Afterwards. Um, and I actually think if we click on this. You see how it's clickable. I think it'll work, and it will create a new tab. But let's see that happens. Um, okay, perfect. So it create a new a new tab. They didn't send it for us, but it's saying get local pets one. So if I could send their great So I got in this case, you know, Max record by itself, it says its i d one and the links ourself and, uh, and the name. So if I change this to to, I'll get Leo. If I change this to three, I get Brown. That's awesome. So let's, um let's save this into the I guess. Let's rename this get all pets. Aim point. And then I'm going to save this Toby, get ah, one pet endpoint, and I'm gonna put it in the Mets collection. Awesome. So, um, let's try a post and see if we get, um, the correct, um, the correct results. So we have here, uh, see pet named Lalla. Since I think we were started, the server were We don't have la LA there. Yeah, we just have upto upto brownie. So let's send this and see what happens and perfect. We got bets for which is Lalla. And now if I try here and get four, I get Lalla there with her pets. Ah, Treff awesome. So see that it says that we haven't saved it. We don't want to save it because we just want to say that's one. So we'll leave it at that. The next thing we're gonna do is work on the put and delete methods. Okay, Now we're gonna work on the update operation, which is the put X to be method. But I wanted to give you ah ward off advice here because put can also be treated to update or create a record. And the create site comes if you are. If you give declined the option to, um, send on object with its own I. D. So, for example, let's say that I, instead of our creating the idea of the bet I I exposed a, uh, put a method where if you passed the i d, then the that Paris created with the idea that declined passes Um, I don't find that use case very often. So what I usually do personally is to use the put method as the update, and that is going to be kind of like how I use it in the rest of the course. But, ah, the caveat is that you can use put also under the HDP specifications, as a post. But but in a post where you allow the client to create a record with with an I D that declined arse elects, Um, and technically, if we want to update just one one field off record, often object. Then you use another exit to be method cold patch. The problem with patches that a lot off, Let's say you know where Klein's JavaScript, and and even more about clients don't support backs. Very well so but on again, Patch means that you send that idea and then just one feel to be updated versus put. You need to send the idea and all the fields. You cannot just send one field for that object I like, I said. Personally, I used put us assay patch, meaning that you can pass the I D and just one field or all the fields. But that is a something that I that I buy the sign us choose to do and I communicate that to the A P I and user. So, yes. So you guys have you know, this this this caveat in mind and make sure to read about about patch and put on the on the resource that I'm gonna put on the on the lesson. Okay, So let's work now on the put request here. And so we're gonna do the following. We're going to find the the method with the pet i d. As a parameter. And then we're gonna check if the request has a Jason object. Um, or if it doesn't have a name in the request, then we're gonna aboard with a 400 error, which is, you know, bad requests. Next, I'm going to reduce the count off the array by one. And I want to say pet name is equal to the request Jason name. And I'm going to return the object back to the to the user. Um, I'm gonna return here a 200 which means that the operation was successful and I'm returning back the on the object, but because it's not any object. I'm not returning a tour one, but rather a A 200 and ah, just so We understand what's happening here. The I'm subjecting one toe the bed I d. That's being passed because again Ah, race. Have a zero index for the 1st 1 So if you're passing, let's say a request to update Leo. You're passing a number two, but I'm actually I want to get the ah, the pet element off one. So this your Syrians his one right? So, um, that's it. That's the put on. Let's go ahead and do the delete. So you find the method the elite. And remember this this the lead is the actually be method. It's just not a function that we just are eternally calling that lead. And here I'm gonna call the del Key word for for a race, which is the leading the a specific ah, element off the off Thea of the array. And finally I returned an empty Jason object with it with a two or four and remember what we said about two a four. It meant that the operation went through, but that I'm not returning back any objects to the to the client. But I'm I'm by doing toe a forum confirming that the elite did go through Okay, so let's go ahead and try that on the on the postman client. So let's check out really quickly what the best that we have. So we have Mac Leo Brownie. So I'm gonna clone this post toe, um, to be a, um the put Because we're gonna have to pass the this body here with with with an updated name. So there's a function here whether you condone public eight. And let's rename that to be put. Ah, up they specific bet. And so we need to pass an i d. Here. So I'm gonna, um I lost the top here, and we saved this, or this is port Save and let me create a new top here. Let's put the put in there would get. So let's get all the pets again. So I have Mark, Leo and Brownie. So I'm gonna rename Brownie to Lalla. So that's pets Three to pat past Best three. And I put Lalla there. Okay, so when I do this, Operation Brown is gonna be renamed Lalla, So let's send that. And now get pets three its name Lalla, And notice that I got a 200. Okay, Which, um, it is basically accepting that the request was successfully processed and and it returns back the up, Um, And if we get all objects here, let's see, Yeah, we'll get a lot out there. Okay? So let's do a new one. And I'm going to do the the elite, and I'm gonna clone the get for that. So we're gonna call this elite, and I'm gonna delete the third record, which is Layla and ah, let me update this. Toby the lead. One pet, they save saving over. Right. Perfect. So now I'm gonna delete number three, which is lava. Let me send and perfect. I get a two or four, which means that the server process, the request, but there's no content returned back. And if I do, I get here. I see that are now only have Mac and view 14. Simple Authentications: So we've seen all the create great update and delete operations. The crowd operations for are very simple in memory, kind off pet, A p I and point. But now we want to, you know, take it up a notch. And when you're dealing with a P eyes, you are always dealing with authentication and authorization because security is a big thing that you should be thinking about so normally, what I would recommend, um, to do if it's if it's if you want to go, like all the way is to study how to enable off. So office, this protocol that a lot of the, you know, very professional ap I use is like Twitter. Um and, uh, it's it's a little bit complicated to set up, and I might do ah, many course or YouTube serious about setting up a python based off server. But what I've done in in projects in the past, both for myself and for professional applications, is a token based authentication, which is very similar toe off. But it's not 100% off. So, um, let's see how we can do this. It's ah, uh, kind of like I wanted to draw until that you guys can can check it out. Um, So what we're gonna do here is we're gonna have a, um we're gonna use the headers. So in eight in exit E p. You have basically, you know, layers off information. So we have, you know, the actually your eye where you can pass information. For example. Forget requests. Um, you have the body, which is what we saw when we were doing the post and, um, and put information, which is kind of like data. That's Ah, that's, um, part of the off the request, But we also have headers. And we saw the headers when we were talking about the, um you know, Jason application. Jason had her remember that. So it's it's very common that you use the headers also for, like, authentication. And what we normally do is we use this thing called on X header X dash. So X stash means that you're gonna be saying, you know, x up. I d for example, for the application I d or on and ex like Ah, it's a token. And this is kind of like a like a password kind of thing, where you where you have, like, information to be able to access your, um, your ah, your A p I content and you busted headers on every single request. Um, so the way it works and it's kind of like similar to having a user name and password, kind of like log in. It's it's ah, it's basically the following. You have a, um you haven't an app that that has re read write requests or access to your A P I and that app is gonna have a an app i d. And it's gonna have an app secret And think of this as the user name and password, right. So this is gonna work. They use her name and a password. Now, the thing is, you don't want to pass on every request, your use aiming passport, because it's kind of like, um, you know, if by any chance somebody reach those headers, you're gonna be exposed. So you want to separate, they use them in passport from the actual headers that you're passing. So the way it works is that, um, for step number one, you hit some sort of end point. That's kind of like get token, get on the score token, and then this. Get talking. You work, you're going to have, um a, um you're gonna pass on the on the post. Um, from the post request, you passed the up I d and the up secret. Now, this information you're sending on the post on the body on the data beast cannot be read by it. Bye bye. Servers that are intermediate servers. So that's a very secure, kind of like operation, right? And then on after you post, then you get back from the server. A a token. And this token is a random kind of like a combination of letters and numbers, and we'll see how we generate one of those. But it also have has an expiration off, Let's say X hours or a day. Um, Why? Because what you want to do is that because this token, you're gonna be passing on the headers. Maybe somebody can potentially read that on day will get temporary access to doing stuff with the A P I. But if you know the client detects somehow that somebody's reading this information or, you know, informs you, um then they can revoke this token and and then you know, you're your old, you're good. You the client or this hacker doesn't have your up i d in secret. They only have the the up I d and the token And that token is is, you know, generated often. So then after you have this token step number two is on every request. So let's say you want to get the pets endpoint. You're gonna pass the on the only headers you're gonna pass the F I T. And the token, and then on every request, you're gonna go through the request and say, Is this up idea and token, you know, registered somewhere and that's what we're gonna do. We're gonna, you know, store this on the talk is gonna be stored in the database. It has an expiration. So after a certain amount of time, that token is no longer valid. So the first thing we're going to do is we're going to create a decorator for every request so that we can check that the you know, the requests we're getting is it's a valid one and that the user has access to, you know, hitting the end points. So let's start working on that 15. Testing our Simple Authentication: Okay, So start working on that decorator and what we're going to do, Ace, create, um, a add app folder where we're gonna have the models and the views on the test for the app creation. And, um, um, testing off the different clients or the, you know, the user log in and password, so to speak. They are going to be accessing our a p I. So let's do that folder here, um, app. And then we want to create a being a B y so that python knows that this is a A module and we're going to create a decorator's B Y Not under the greater speed why? We're going to do something that you've seen in the past, which it's a decorator. So we start with the functional tools and import wraps. Then we're gonna import the request and J son, if I from flask and that we're gonna define this decorator called app required. So we create the regular decorated function with the arguments and keyword arguments. And so the first thing we're gonna check is even request headers, and we're gonna call this header an X up I d kind of like what I mentioned earlier. And if it's not, then we're going to return back a a Nair code 403 which is unauthorized. Then we're gonna set this up i d viable. Toby, the that X up i d header. And we're gonna also get the app secret, which is gonna be called a X app secret. I'm just gonna print it out on the on the locks eso that we see that this is stock are currently working. And for this first test, what I'm gonna test is that both the up I d, um the f i d said toe Jorge and the AB sequence is said toe my secret. And then if it's not the case, then we're also going to return an air message. Otherwise, we returned back the function, which means that the the function will will continue working from that point on. Perfect. So notice that I'm doing here the up i d and up secret being passed on the headers. Of course, we're gonna modify this with a token. This is the wrong way to do it. But I want to guys to to see how these potentially works. Okay, so now we're going to go to the pet, Um, a P i file and we're gonna add the decorator here. So we're gonna say from AP. Ah, decorators import up required. Okay. And, um, this is a special kind of, like method that probable views offers, which is just are able to pass decorators, I say a set list. So we're gonna say decorators equals up required, and it is a really nice, very see thing that that flask implements for us. So we don't have to use the at sign here because it wouldn't work right? It's a class is not a function so flask. If suit gives us these helper method, um, that we can we can just pass the decorators as a least off off decorators. In this case, we're gonna use only one. So let's see what happens when we try to request now the older pets. So let me clear this out and then just put the get l ah, get old pets and point. Now, if I send this, I'm getting on a four or three, which means that it's working correctly. And if I see the logs, I can see um, I guess it didn't it didn't print that in there because it ah see what it's doing. So if it's if it's ah by these none, then it's returning that for three. So we don't get toe print the up idea in secret. So that's working fine. But now let's said those headers. I'm not here in here, So see how we have key and value. So here, we're going to say, X up I d IHS Ah, we said Jorge, Right? So, Jorge, it's just like the user name. And let's just send that. Let's not send the secret to see what happens now. If I send this, I still get a 43 and receive the lock. Say something. Perfect. So see how it's printing the header here, the jorge bodied saying known for their for the app secret. So let's do that again. And this time it's too. The wrong passwords were going to say password. 123 again. Send it. I get a forbidden then Now I see the to ing there, but it's still not the right combination. So finally, if we set the right combination, which is my secret, and then send, I get a 200 okay, um and I forsee the body. I see that the pets are being sent back to me. Um, perfect. So that's how, like, the basic authentication works. Um and, ah, you know, this is a very good first introduction to To how we were gonna set up the the A P i ah authority authentication on on our pets application. 16. Token API Model and API Endpoints: in this new section, we're going to start building the rial token based application. And so we're going to start working on that using modern TV to store these APS on the credentials and also storing tokens that as you asi no, from the previous explanation have a an exploration, um, on those tokens. So let's start working on that. Okay, let's start by working on the models for the app, um, or the ups that are gonna be able to, um, logging or or access the the endpoints. It's where I will create a models B y and in that models people, I we're gonna set up the following first, We're not import the levy from the application, Then we're gonna create a model for the APS, and that model is gonna have a nap. I d which is going to be sort of like they use her name. And then we're going to also have a up secret, which is going to be sort of like the password. And we're gonna indexed ace by the up i d. There's a model we're gonna create or the other collection is gonna be the Axis collection , which is the where we store the tokens, so it's gonna have a nap, which is gonna be a foreign key or reference field as we call them on among go, We're gonna have a token which is just gonna be a string and finally was in a store. The expiration for those tokens. Perfect. OK, no, let's work on the a p I for the app. And so we're going to say that this is the A P. I ducked b y and what we're gonna do here, we're gonna have the two classes. Want to interact with the up creation and another for the Tolkien creation, which is going to be the access A B I. And it's fine if you put more than one AP I class on a single file, so let's start working on that. So we're gonna have, um, the method view from flats views imported. Then we're gonna need ah request, um, aboard and Jason. If I from flask, we're gonna use the B crypt library, and we're also gonna have the year I d two great tokens. And finally, the daytime and time Delta to check on the token validation. So we're gonna import the model from AP. Um, both the up and the axis. So these are first class. It's the up a p I. And we're gonna sit and in it function, which is going to say if the request doesn't have any Jason, let's just aboard that takes right off the bat. If if the request has Jason in it And if it doesn't, then we shouldn't continue on with with the class instance, aviation, then we're not define a post method, and the first thing we're gonna check if we have up i d or up secret in the request itself . Now notice we're not passing this on the headers anymore. We're passing this a supposed body because we're now doing the the right way and something you'll see here. Um, I I'm going to start using on error code. And this era coats are usually I make them strings off capital words with on this course in between, so that it's kind of like a constant and the client tending check for those errors. So if we don't have up I d or up secret, then we're just gonna return an error. Then we're going to check if the APP exists already. So we're gonna hit the mongo to be to get objects that have that same up i d If the up exists, then we're going to return on air saying that the up I d already exists I noticed, were using Cold Air 400. Now we have our else, So we're good to go. We're going to create the credentials. And one thing that I'm going to do here, I'm not going to store the passport plane because this is kind of like regular passport. I'm gonna be decrypted so that if somebody maliciously hacks the database, they don't get access to the to the actual passwords. And they should be always your practice when you're working with with passwords, even if its app passwords on ah, on an a p I server. And now, finally, we create the app object with the up I d and our hashed password, and then finally will return a result okay, back to the client and notice that I'm not returning anything here. I'm just saying result. Okay, so that's gonna be a 200 now. The next thing when I work on is the token side of things. So let's start working on that is gonna be called the access A P I and where do the same thing. We haven't in it. Which checks? If the request Jason is empty then would return a 400. Now, let's define a post method. Now, the Post here is gonna be to create a token. So we're going to check if there's no up I d or up secret in the body. - And now I'm going to get, um, an error message for the client. Next, I'm going to check that the APP exist. - And then else it means that I found the the app I d. First, I'm gonna just return the error there four or three. And here I'm going to generate the token. If Thea, if the password is, is correct, So we're gonna check with the B crypt library and take that that that's equal toe our database over the up secret that would return from the database. So if it's if it's if it goes through, then we exist with the little The existing tokens causes the one that we're going to say that is the new valid one for this app. So I'm just going to get all the access tokens that match this app and the lip terms. Next time when I generate a token using the U I. D library, I'm gonna set the tokens time, Toby. Now, and as we can tell, we're gonna use the you to see. And when I said that seconds and microseconds Toby zero were just interested in hours and minutes. And we're gonna set the expiry. Toby, 30 days from now. Finally, I store these only database itself name when I saved this and I want to generate the, um RFC 3339 Which is Theo? Extend. Erred for a p A s A p ice, too. Sorry. Return time for mitts in ah, in a PS. So you should use this whenever you you want to. I use ah, daytime's on your a p I. So we're gonna return the token and when it expires. And here we have one else. So they passport? What's not correct? The up secret. So we're just going to say, um returned an error code with incorrect credentials and return back to the client with that for three There. Okay, so the next thing we're gonna do is we're gonna return or work on the views off this a p i n point 17. Token API Views and Decorator: Okay, So the next step we're going to do here is create the views B y for our app, um, endpoints. And with views be why? And that is gonna be quite similar to the other stuff that we've been doing. We're gonna, um, do a blueprint. So we import the blueprint from flask, and we're gonna import those two classes from the a p i dot b y we create our blueprint, which gonna be up, up. Then we set up a view using the ask you method for plausible views with the AP AP I and finally we're gonna add the rules. So the 1st 1 is gonna be the post for creating an app. And remember, a nap. It's like a client, like a user name and password. And then we're gonna have access view, which is Thea Other Ah, a p I. Which is gonna be the token generation. So we're gonna add the rule and we're going to call that the APS slash access token. And you've been opposed to that when you want to create a new token. Perfect. So that's that, Um, now we need to add this blueprint to our application fee Why? So we're gonna import, um, from views import up up, and then we're gonna register that with up up here. Okay. With this, we can start at least creating and, um, generating tokens. Although we're not checking, we need to do some work on the decorators to check that the token is is valid. So let's go ahead and ah, and work on that. So let's go to decorators B y. And we're gonna were any day time here for checking the validity off the tokens. And we're also going to need the up models to retrieve the AP and the on the excess tokens . So I'm gonna delete this, and I want to say up I d is Theo the X up I d. And everything else in here is gonna be a new stuff, new things. So we're gonna get the APP token, which is gonna be on the headers. And that's when we pass ass ex app token. And I would check if Thea pi d it's none or the up token is none will return a four or three. The next thing we're gonna check if the app um I d exists. And if we don't find one, then we're going to return a 43 as well. And finally, we're gonna grab the token, and then we're going to say If there's no token that we've found, then return the floor three. Then we're gonna do the, uh, the access token. It's not the same as the app token that we found. Then we return it for three a swell. And finally we check if the token is expired. So the way to do that is we check if it's lower than the daytime you to see now. And if that's the case, then we're not going to return an empty string. But we're not actually returned an error message with a 43 Okay, perfect. So let's go ahead and test this on the on the APP 18. Install bcrypt and Test Tokens: Okay, The last lesson. We set up our views and the decorator to be able to register the the apse and also be able to check, generate and check the tokens for the axis. So now let's go ahead and install the pie be crit, which we used to include the passwords and then set up our A postman, uh, test to see that everything is working correctly. So let's go and do that. Okay, let's go to a requirements txt. And we're gonna add a new, um, library here called pie be crypt, and that's gonna be scribbling for, um and save that. So how do you install, um, libraries after the docker container is eyes set up? Well, you just you just need to, um, called peep install requirements from the outside. So it against here the container start because he didn't find big crypt on that, a p I p y lying three, which would be right here in Port Secret. So, um, we just need toe to do that to install that that library. So what you need to do is you actually just call the doctor composed build and what this is going to do it. It's gonna rebuild the, um all the containers. But the database one is not gonna change your data is actually gonna be kept without any modifications. And the, um, the application container is the one that's gonna be installing the new stop, but you'll see that it goes very fast because it's it's not generating originating the whole thing. Let me clear the screen so you guys can see this better, so Doctor can pull, spilled and see it almost keeps everything. He just goes straight to install requirements. And in there you go, Uh, it's done. So we have pike pie be crypt installed. Now, we can go ahead and run, be the container again. So let's go ahead and and do the postman endpoints. So we're going to create a new folder here called, uh, app and those are you going to be the end points? And, um, when a close, this don't save. Okay, so the first thing we're gonna do is we're gonna pose to the local host and it's gonna be up and ah, let's check what the value should be. So with post, we're gonna say we're gonna need up i d and have secret as the Jason Payload. So we're gonna have body, uh, raw. I said I'll be Jason. And when I have i d So let's say this is the mobile app that's gonna be accessing. And you can think of the abscess different. You know, different types off devices or if you're a P I spotlight thing. Actually, people are gonna be a putting. They're kind of like their user name and password. Um, So, for example, in the safe, your, um a, uh, e commerce, because it's a better. Maybe I an e commerce store. That's a it's Petco. So the up i d would be Petko here, and they would have to choose their their own secret. Um, and the other I think that they're gonna chooses thea up secret. So let's pass one here, and we're going to call this, uh, test told me No, that to log in or generate a token, we're gonna have the mobile and test. So let's save that. And this is gonna be, um, remember the way that we were. It's get okay. I just wanted to check the format. So we're going to save this ass post, create new up, and then we're gonna save it in the pets ap i app folder. Okay, so let's check here. It's running fine, and we're gonna post, and it says he didn't find the I see. No, I think it's APS. So they sicken views its apse. Right. So I me spell this, perhaps save that and then send again. Awesome. So we have about 200 okay? And the result is okay, which I think is what happens if everything went well, which is right here. So we generated that Ah ah ah hash past board. And Ah, and we most f um, save that on the mongo db. So let's go and check if that is the case. So we're gonna go into mongo db. So in order for us to check that out, we're going to open a new tab here, and we're gonna basically do what, Dr. Except I t out first. Before that, we need to check. But the name of the container is now. You see how, um, here that the image is called Betsy FBI Web, but the container name, it's actually pets. AP I Web Ron 15. That's because we're running this with Web ports. Remember how we running this with the service sports web? We're not passing here. The name. So, um, Docker basically select a number for us, and I think it increments one by one. So you need to chuck the check the container name before you. You issued this command. Um, you can also do it with a container, I d. But you know, it's up to you. So we're gonna do, doctor, Except I t and the container name. And then we're gonna put here whatever command we want to use in this case, we're gonna do mongo with the host mongo db. So this is how you would connect to mongo db from the application server. So if I type that in there Ah, it looks like I misspelled. So maybe it's not age its host. Let me check that. Right. It's host. So let me clear the skin and its host like this. There you go. So now we're connected to our among go db instance, you can show that the bees and you have pets. Ap I there. So we use that's a P I. And then we show collections and you see how we have app now. So that's our up collection that we created from the from the end point that we just did. So if I do, they'll be up. Find There you go. So you see how we have an i d. That was generated. That's among would be i. D. This is the application i d s mobile and the secret. As you can see here, it's encoded by B crypt. So that's perfect, because we know that it's it's test, right? It's, um it's that the obsequies test, but on the database, it's not stored a status stories, acerbic wit. And this is a good practice to always. If you're dealing with passwords and or things like that, you should definitely not store this things on plain text, but use big crypt library. Awesome. So, um, let's go ahead and generate a token, and I'm gonna leave that window there in case we need to check something else. Um, so a new endpoint here, So we're gonna just, um, duplicate this and it's gonna be, um I remember the endpoint waas. Let's see in views. Okay. APS access toking. So APS acts of stoking Perfect. And what did you need to, uh, post. I believe it was the to say here it was the uppity and secret. So it's basically the same. We can pass this as we have it there, but let's save that, um, save. And we're going to rename this to post create new up talking update. Awesome. So let's do that post and see what we get. Awesome. So we have 200 okay? And we have expires 2017 generate 26 which is a month from now. And then the token is this you you i d. And again if we go to our munger to be and now we do show collections, we'll see that we have now access in there. And if I do db access find there. I have the i. D. The object i d. Oh, which is the the access? No, the app foreign key. Correct. And this object I d belongs or correlates with this one here. And the token is tissue. I d and expires and see how it's It's store STIs on an I o u I s o date. Because Munger to be is able to handle that that form it so awesome. We have our token generation. And so now what we want to do is that for every, um, for every single request, we're gonna need to pass the, um this talking here. So let's leave that that top open. And let's just try doing a now get old pets and point. But now we're gonna need to use the, um, on the headers. We're gonna need to use this, You know, this token and the up i d But let's go ahead and copy this and they get a get all pets in point. We're gonna have a key called X Up I d. And that's gonna be mobile. And then the X up token is gonna be the token that we just copied and pasted. Um, let's just check for one moment without passing this and see what happened. So if I own click that those headers are not gonna be sent and we can check what happens there and see I get now. Ah, 43 forbidden. And that means that this is, um, heading into the decorators. It's not getting the up ideal token. Now, let's see what happens if I passed the up i d. I still get a four or three, and then let's see if I do the wrong token. So instead of e. At the end here, I'm just going to say f Okay, send. Same thing. I get a forbidden. That means that, um, you know, this is being checking the in the app, and then it checks that the, um the token is not the same, um, as they talking that we have here. So that's a 43 as well. Now, finally, it's fast. The right token. Then send and see. I get a 200. Okay? And now I see the list off petting here, as expected. So perfect. We have our authentication, um, layer built in. And, uh, now we're gonna start building some tests for these. For this piece of the of the A P I 19. Building the App's Tests: So now that we have our APS token system no authorisation system, let's go ahead and build tests because we haven't built any test so far. And it's gonna be a good introduction toe how we put or create tests for AP, eyes in general and specifically for flats. FBI's So let's get started. Okay, so we're going ahead and create the tests. Ah, here the file tests B y, and I'm going to copy and paste, cause this is something that you've seen in other courses off less courses that have done, and it's pretty much the same. So we set up, um, an application factory here. We set up the Mongol engine, get the B import unit, tests, importation and some other files. And I'm also importing from up models happen axis, and I'm getting the longer to be host from the settings. Then I create my APP test. Ah, unit test case, which ah typically has a create up method that allows me to quickly set up the application itself. Then I do a set up which, um, just uses that method and creates a new app. And then I have a tear down Ah, which gets the current TV that I've just created and drops that that epics Because, as you know, we want to start from from scratch on every test. So this, um, set up and tear down are gonna be called from every every single test. Finally have created an app dictionary with a you know, dummy back line and that secret that we're gonna be passing to the to the different ah, test cases. And as you can see, I return a Jason dumps. This is a, um, a function off Jason library that allows you to create a Jason object from a ah, either a string or a, um or in this case, a dictionary that that I'm creating using the python dicked uhm ki ward or function. So that's the beginning of it on. And then I'm gonna begin with the actual first test, which is the creator up test. Okay, so our first test is gonna be the create app test, so let's go ahead and do that. So I create a basic registration which is gonna use the app dictionary that we created on, um on the, um on the class itself. So we just post that to the apse and point with the data off the dictionary. And this is a very important we have to pass the content type in this request. And that's gonna be the application, Jason. So the assert here is gonna be that the status code is 200 that means that the application waas created properly Okay, let's now simulate that we have a missing app secret and check that returns a the error message. Um, so we're gonna have the we're going to recreate the from the app, um, dictionary, but we're gonna be missing the up secret part of it. And now we're gonna post to the apse and point, and we're passing the up dictionary That doesn't have the the secret. And finally, we assert that it's missing the up i d or secret, and that's the air message that's being passed from the A P I p. Y Perfect. Okay. And the last one we're gonna do is if we are, um, repeating the registration. So we're gonna say the same. Send the same up dictionary. So we set up the dictionary here, put the content type obligation, Jason, and we should get up. I d already exists. Okay, so let's go ahead and test this or run the stats and see how this is done. So first I'm gonna save this, and I should close some off this taps, and I'm gonna create a A top level tests be why? That's gonna be the runner. And you've seen this s I'm gonna go quickly through it. Um, we said the path first. Then we are going to import unit test and then import from up test the test that we just created and then run unit tests. The main. So how do we run the test? Well, we're gonna have to find out what the name of the docker, Uh, container is. So let's check that out. So it spends a p i Web, Ron 15. And I'm going to do the following Dr ex sec I t pets ap I Web run 15 which is the name of the container here. And I just type python three tests B y. So that should run. That s so they'd see how that goes. Perfect. So we have some deprecation. Warning. Jason separated. Get Jason instead. That's from within the, um the flask, um, package itself from work, so and will so get one from Mongo Engine, which is again a deprecation warning. But we see that we have a little dot here and it has ran one tests into a second. So that's working perfectly fun. So great we have our first test running and now let's go on and continue working on the on the abscessed. 20. Token Tests: So let's go ahead and continue working on the on the test. So now we're going to do the some token test. So we start doing that. The 1st 1 we're gonna do is we're gonna test the talking generation. So we're gonna post Tuapse using the AB dictionary and just great are up our initial app. And the next thing we're gonna do is we're gonna create a an actual token, and we're doing that through the access token and point, and then we're gonna grab the token from the, um from the return, Jason. But see, in this case, we're loading the the data that's being returned on the returned value on the response value. We're recording it with duty if eight. And then we're getting the token. Um ah. Took in property or the token, uh, piece off the Jason. That's free in return. Um, and the test in here is gonna be that they're talking. It's not. Not so. If that token is, it's not, Then that means that the Tess has failed. The next to test we're gonna do is we're going to test that the if we're missing the up secret, then that we're going to check that the token doesn't doesn't work. And we're also gonna check if the up secret is incorrect. And so we're passing the wrong, you know, up secret and up i d. Or in the case in this case, the 1st 1 is the It's the we're missing the up secret. And in the second case, we're missing the or report passing A incorrect. Absolutely. So this 1st 1 it's been a return missing up i d. Europe secret, and the next one is going to say incorrect credentials. The next thing we're gonna test is see that the token works, bypassing the right token. And we should get out 200 there. And we're also gonna test if we passed the wrong token. We're trying to get the pets in point with an incorrect token, So we should get a four or three from that request. The last test is gonna be a expire token. So we're gonna, um, try to do a 31 days from now access and we're going to now try with the with the existing token, and that's gonna be already expired. So we should get talking. Expired in the in the data. So that's it. That's that's all the tests that they were going to be building for the APP. Let's go ahead and run the tests. So let's go ahead and go to the terminal when a clear the screen here and remember that your, uh, docker containers should be running both e um, the Munger to be on the application. So we're gonna hurt. Go ahead, Doctor. Exactly. I t pets AP I. Weber on 15 which is the name of the running container Bison. Three Tests P. Y. Perfect. Again. We get some deprecation warnings, but nothing to worry about. Ah, but it says that it ran two tests in four seconds and everything went OK, so that's that. That's for that's it for the apse. And we should now start working on the stores and point for the FBI soul. Let's let's start working on that 21. Starting the Store End Point: we have just finished working on the apse and point. And now we're going to start working on the store's endpoint, which is going to describe the physical stores where we are gonna have our beds available and eventually we're gonna have pet assigned or associated with this with this stores. So let's start working on the stores A p I. And of course, we'll start with the blueprints for four stores. So let's see how we do that. Okay? First thing we're going to to a is we're going to create a new folder here called Pets. I mean, store sorry, store, and we're going to create an NDP. Why? So that we can import This s a by phone module, and the next thing we're gonna do is gonna have a views, B. Why? And we're gonna do something similar to what we've been doing before. Which eyes to create the store a p i, um, file and then create a blueprint from it and then store the views for, um, the stores and point for the get and post for stores as well and as well as we're gonna enable get put and elite four story the This is the first time we're gonna be using put in the lead. So that's gonna be pretty exciting Port. It's gonna be used for updating the stores and the lead is gonna be for the lead in the stores. So let me say that so that that's the views. And let's go ahead and create the models B y and he's gonna be something pretty standard as well. So we're gonna have the store with an external I d gonna have a neighborhood, a street address, a city state and a sip code and the full number and we're gonna have on indexes on external like the now One thing to notice here is that, um, in the pets when we were we had the pets. Initially, of course, we're storing this from the database, but we had, like this I d, which was 123 Now here we could have X Tex turn like the be the manga to be I D. But it's really not a good security practice to expose your ah internalized the your like mongo db i d. Or even worse for my sequel, I d. So always use something like this like an external I d that you're gonna be generating. And again, we're gonna be using you. You ideas for that? But this is a very important, like security thing that you should always be mindful off is to always have extra like these when you want to, um, allow people to select those those objects. 22. The JSON Schema Library: Now, as we start working on the story p I One thing that was specifically challenging for me waas the validation piece. So now we have a very complex store, a model that has all these fields, you know, street and sit code and neighborhood and things like that. And I wanted to see how he could, um, validate these and one approach that I thought about doing Waas somehow hacking wt t forms , even though they're not technically forms that we're validating maybe looking toe their validation classes and hardwire that. But then I started, you know, thinking about another library, that it's pretty, It's pretty useful, and it would be a good fit for for this project. And I think it's It's really good in general, too, if you have, like, Jason objects and that libraries called, uh, Jason Schema, and we're gonna take a quick look at it. Um, one thing that you'll notice is that Jason Schema can be installed on a supply from library . And, um, if we look at the example here, it's it's perfect for for an A P I validation, Um um program, because we can, um, we have a very flexible kind of like schema definition, and we can define, you know, that things are strings, so they're like numbers and things are required, as you can see from this example. So there are a lot of examples here that that they go through. But I'm going to Korea. Quick example for us to look at and get you introduced to the Jason scheme. My library. Before we do anything, though, we need toe at that library toe a requirement 60. So we're gonna have Jason scheme, um, with that version there. And we need to install that owner on our daugher, um, container. So we're gonna build the the containers once again. So let me clear the screen, and it'll install the Jason scheme. My library. Great. So we can run the container again, and it's go ahead and create a quick file here that will. I wouldn't be storing it on the, um, on the repository, but just so you guys see it? So, um, this what I Jason schema would look like and let me put that a little bit more toe the left . Um, so we have to import from Jason scheming, poor validate. And then we can have a schema off an object that we want to validate against. So in this case, this is a type of object, and the properties are price, name and external, like the and required price and name. So from these fields from these properties, once I require our price and name asked there, described here and notice that we have a perfect, um, pattern for you idea. So we're expecting, you know, the they the input or or the Jason object to have that format and then the way that we you , um, you validated is he just called validate? You put the object. So this is our right here and you on you compare it against the schema and you'll get, um, either a, you know, a success or another message. So let's run that from quickly, so I'm going to se Oh, sorry, I have. There you go. I have a fight on three, and we're gonna say Valle test B Y. Uh, so I guess now has a different name, right? 16. Sorry. Oh, that's so it's 16 now. Okay, So I didn't get any response, which means that it validated. But for example, let's say that I don't pass eggs in here and save that and then I run it again. See, I get ah, um validating required in schema and, uh, and it says required price and name type optics. So basically, the, you know, the validation error that I can grab from there is that name is a required property. So you can see it's a very flexible little library, and we're gonna be using it for for a store in point and eso We're gonna define that schema for the store. So let's see how we do that. So let's go ahead and create our stores, Chema And let's put this back in here and I'm gonna call this file the schema p y. And here's the schema. So I have It's a type object, and then we have properties Neighborhood Street, address City State and see how I'm required that it's a two letter capital. This is a regular expression. I believe that we've seen a little bit off that in the in the past. We also have a sip core, which is supposed to be five numbers, and we also have a phone that has a kind of like the area code and then three digits and then four digits with dashes in between. So if something doesn't match those things that were going to get an an air and I'm saying that old of all the properties are required So that's, um, that's gonna be the schema that we're gonna be using. The other thing that I'm gonna be using here toe facilitate the A P I. Is the concept off a template? So again? Because it's it's such a complicated object. I don't wanna be like building the Jason objects every time. So what I'm going to do is I'm going to create a templates b y with two functions. One is going to be this store object that if you pass the store from the Mongol engine or mongo db object to it, it'll return. You know this nicely? Um, kind of like addressed or formatted, um, Jason object that has the i. D. The neighborhood city state, etcetera. And I can do any kind off like transformations there. And as you can see, I'm also already having a links section in there. So that means that every time I need to change any of the Jason format. I can do it here very easily. And also for the stores when I have the stores, Um, like a like a query list. I'm going to do the following and will never return A I'm gonna have an array cold stores, and I'm gonna return the stores back to the to the user. Now, one thing is that this is a temporary state. I'm gonna change this afterwards on. Well, see why that is when we start using imagination. But for now, we're gonna live this. Ah, kind of like a placeholder for us to get back to. Okay, so I think we're ready to start working on the on the A P I specifically. So let's do that. 23. The Store API File: Okay, now that we've seen Jason Schema on how it's gonna be very useful for us to validate the user or the client input on the A P I. Now let's go ahead and start working on the A p I for the stores. So let's get started. Okay, So let's go ahead and create the A P I file and we're going to, um, do some imports here. So we're gonna import flask, method view, And, um, some of the elaborates that we've seen from flags like the Sun. If I write request aboard render template also you I d and Jason and this last ones are new in terms off, like we've never used them. So one is called the Jason Schema draft for validator, and the other one is called Jason Schema dot exceptions import best match, So we'll see how we use them in a little bit. We'll also have thea decorators. Ah, the up required ah, import the models from the store and again, this last to one store scheme. My import scheme and store templates, import store object and stores object are kind of like new usage. But as you can tell, this is related to the store templates that we have here. Um, where we have the the different templates for both the individual stores object and the, you know, the plural stores object. And also we have the from the store scheme, and we will import the schema on. We're gonna compare the decline input to this to the schema. So let's see how we do that. So here, we're gonna store. We're gonna be in with the class store ap I with its decorator. And again, we're going to check if there's, um you know, there's no request, Jason. Then we aboard 400. If it's not a get request, then we're gonna go through the get, um, method. And if there's a story d being passed on the get method, then we know we're going to return the individual store object. So we'll just pass down the ah, the response as the store object from the template. Otherwise, we're going to get all the stores. So that's that else in there. And then we are just gonna, uh, return the stores from the from the query to the stores object. And as we said before, this is kind of like a working process, but we're just going to return those, um those results in a in a very linear fashion. But will will do a better job of that when we do the the pagination, which is something that we really need to be using on AP eyes. But any case we have if there's a store i d. We get that story d If we get the store, we return that Jason, if I response, which is the result is okay, and then the story itself is thes store object from the template which will be this this thing here and ah else we were stone a 44 meaning that we we don't with them find that that that that story t otherwise, we if they give it to get and it's stores because it's not on a story The swing past, they were returned back all the stores. So now let's see what we do with the Post and the Post. We're gonna get the, um, the store Jason from the request, Jason. And here we're using this new method called the error. Ah, best match drop for about it validator. And this is just gonna, um Ah, it's gonna return back all the errors that we get from the comparison off that of that schema with the story Jason that's being that's impasse to us. And if there's an air, then will return a narrow message with the with the error message that that the schema validator it's passing with a 400. Otherwise, things are good. So we're gonna create a store object with the we're gonna create an external I D. Um, we're gonna just store the neighborhood's real address city, state, zip and phone that's been passed on the request. Then we saved that. And then we throw back to response with the store object, which, which again, is the template and the store, Um, that we just saved on the mongo DB and returned a two a one, which, as you might remember, means that the Post was successful and were returning content back to the to the user. So, uh, this thing here, of course, being the new thing. Ah, it's you know, you can investigate a little bit more about what? This, um, what this whole kind of like am involved. But it's pretty much we use it the same every time. So you can just use this copy and paste this and you just fast the, um the input from the client, the Jason object within this illiterate errors um, method that, um that's going to go through the errors if the, um if the, you know the Jason Schema template didn't match the one that they use various passing. So that's that. And we're gonna create just dummy entries for the put and the elite, which will implement later on. So that's the A P I. B y. Pretty, pretty simple stuff. Not too complicated. And so let's go ahead and try these this out. 24. Trying out the Store's End Point: Okay, so let's go ahead and test this out. We are going to create a new folder here, cold, uh, store. And I'm going to Let's clone the one of the post here, the post pets and point and put it here in the store. Let's rename this, and it's gonna be posed store, or rather, boast, create store. Okay. And in this we have we have the headers. Um, we need to add the application in the on the, um, yeah, I have that in here. Should have copied this. Maybe, but we have the X step up I d. So let's create that mix up. I be and it's mobile. And then the X up secret. Oh, no, it's talking, right token. And I believe we still have the same token. But if not, world will generate a new one. They put that in here. Where will this? There you go. Okay. And it's gonna be content type publication. Jason. And here I need to put the neighborhood phone all this field, so I'm gonna maybe copy and paste this. And, uh, this is a little bit to the so neighborhood. I'm going to say, um, college point in the street address. It's going to be 1234 Main Street and the city. It's going to be, um, Bronx. The state is gonna be New York and the city code once here, 33 and the phone 718453 to 3 to 32 OK, so there's gonna be posted to store. And so you have Jason. That looks good after headers and everything. So let's see if we can have this running here. It's running. We have our mongo db to test that out. Okay, so let's go ahead and put Let me save this great and send, uh, because you're a was not found on the server. So let's see have the views in here. Oh, it's stores. Uh, there you go safe and then sent still Oh, God. Put stored. Okay, safe And third time is a charm. No extra. Be local host stores. It's getting a 440 I know. I think I missed one step here, which is adding the blueprints Correcto. So let's see the blueprints here. It's gonna be from oops. So from store views, import store up and up register below print store app. Very good. Saved this. We started the server, yet it started. And let's give it another try. Oh, I have a right. I'm putting an extra coma here. It says, expecting property, naming, enclosing double quotes, Line eight. That's what kind of like pointing me to the so that air so send. And there you go. We have our first store. I have a 21 created. I have the result. Okay, Store city, Bronx. Here's the idea that was generated. And, uh, everything looks really good. Awesome. So let's do another one. And this one, we're gonna do a get. So let's duplicate this. You were gonna call it, get individual store and update. Ah, let's see. So it's a get stores. I have the Hatters there. So they should work when we say that and then send, uh, I'm not getting any stores, I think because it's maybe I'm not, um Now this is get all the stores right, So this would be get stated that get all stores. I think it's because we have We haven't really, um, enabled that were just returning, you know, an empty string. But let's try out a specific store which is that when we just created um and I think I lost the I d there. But we can check it on the on the database. So show the bees use bets, a p I show collections. So I'm gonna do Devi store find, and I have the token there. Uh huh. So I'm going to get the individual store. So let's duplicate this, edit it, get individual store update, and then I'm gonna do stores and the specific i d. I don't have to pass a a trailing slash there because this is kind of like individual one. It's not like a folder, so to speak. So let's save that and send perfect. So I got the You know, the starters today I d There's the h Air h ref for the self, and that's looking good. So perfect. This Assad is working fine. Now let's work on the put in the lead quickly, and then let's implement for real sees this one. The Guettel stores 25. Implementing PUT and DELETE: okay for this video, we're going to implement the put and elite for the store endpoint before we do that on. As I've said many, many times, we don't delete things anymore. In the general practice when we have, it's a flag that we said us, Um ah, some bullion that's either in a life or, um you can say published or whatever the case might be. But we don't delete records because these days storage is so cheap he doesn't make a lot of sense toe, you know, the lead things, and you always have a historical kind of like version off off what has happened. You don't lose any data. So the way I'm going to implement the delete function here is I'm gonna add a field called Live and that feels gonna be a bullion and the D V Field is gonna be l. And the fault equals true. So when we created by default, it's true And we're gonna have the We're gonna add life to the index that we have here because we're gonna be searching for things that are you know, this public I d or externally the end that the life flag is is is true. So with that change, we can now go ahead and do a little bit off modifications to the ah story P. I, um so one we're gonna here, we need to now check if the request is get, uh, it's not get or it's not the elite because both those methods are not gonna have a a payload, um, or Jason, Um, data there. So we're going to say if, um, records method is not get and we could request method is not the elite elite. And, uh, and did not request Jason in about 400. That means that delete doesn't We're not expecting any requests or Jason in there. The other thing is, now we're gonna look for external like the equal story d onda. We are gonna have life equals True, because that way were, you know, just getting If if the stores are alive and the same thing with the stores objects, all we're going to now say store objects filter life equals true awesome. So that leaves us to now create the put and the elite methods right here. So still that so the put method is gonna be very similar to the post, because remember, put is about, um, updating the record. And so we're gonna go and fit all the, um, all the fields that are being passenger request Jason. And remember that put is expecting all the fields beat being passed where we cannot pass. Just sit in your neighborhood or something like that. So we're gonna pass a store, i d. And the first thing is gonna check ive that store exists. If it doesn't exist, then we do a for a four. Then we're gonna do the same thing with the, um you know, Jason validator and get that to be validated. And if not, then we return a 400 error, and then here we're just gonna have a list of all the fields and save that. So in this case, it's not a safe. It's really an update. But that's, you know, among the to be, you know, we're gonna do safe, which is the same mass as the, um asked the ah, as the saving us a new one. Okay, that's the put pretty, pretty straightforward stuff and has tried to the lead now, So the elite is gonna be the following. We get the store I D And check that the store exists. And if not, then we return a 44 Well, the wise we just set the store life to false save it. And in return, a two or four response, which means that we were not returning any any information back. But, um, we're confirming that the operation indeed went through. So let's try doing those those things on the postman side of things. Okay? The 1st 1 we're gonna do is we're gonna do a put, which is gonna be very similar to their posts. So let's go ahead and duplicate that, and we're gonna edit this to be put update store. Okay. And so here we're gonna have a put function. We're gonna pass the same, except I d in token and in the body. We can change anything we want. So let's say that so let's see. Let's change. Um, let's say the neighborhood so instead off. Oh, wait. And you need to pass the actual store. I d. That you're that you're going, Toby. Modifying? No, Save that. Okay, so let's say the neighborhood now is, um it's a Bronx feel. Okay, So received server is running here Perfect. Looks good. And let's send that request and I get a 44 Now, the reason to get up for a four is because us you remember we added a new field called Life here and we also added at this to the indexes and the existing records don't have that life field. So it ah, when when This, um this record the store ideas being looked for in the FBI and it has thes um, this has this, like pickles through first. It's basically falling to the 44 because it's not finding a store that has the life equals true, because that record right now doesn't have that that life field. So the easiest way way to do this is to drop since we're on a development environment, just dropped the collection and then create a new store. From that point on, if you, you know, end up in the situation where you have existing, uh uh that are basis and you want to do a migration with new fields, you need to write some sort of script that reads all the fields. And that's that that the new field and then index, that stuff so it a bit more complicated. But since we're not really storing anything of value here, we're just going ahead and drop the collection. So to do that, we're gonna go to the database and we're gonna say, you know, use uh, bets. Eight b I. And if we see the collections, we're going to see the B store drop. And now we shouldn't have that collection anymore. So now when? When the new record is created, it will have the life field and be indexes properly. So let's do a post again here with specific, uh, we have the same store that we have before. Let's send that and we get a new I D. And now we're going to try to, uh, update that that store with the Bronx feel on, Let me tried doing the get into big store. We'll use thes I d. Here and I get the store perfectly fine there. And now let's update that ascendancy. We have college point here. Go to Bronx, feel now, So let's save place and then send. And now I get the correct updated here with 200. Um, and it's the, um I supposed to say that I get, I'm getting at 200. Um, and finally, I'm gonna try the delete function. So I'm going to just clone this one and at it, the elite individual store, and we're gonna do the leads here, and it's the same I d here, 65 a a Right. So let's save that. And we're gonna do send and I get to afford no content, which means that the operation went through. If I now try to get that store, I get a for all for not found. But in the database, you should still see that, um, that record there, but we have life equals falls. 26. Implementing Pagination on GET all Stores: So in this lesson, we're gonna implement pagination for the store, get endpoint, and you should always return paginated results. When you're getting when you're going to get that will involve a list off of items or objects. Um, it's just, you know, the the best practice for are getting a list of objects is to expansion eight. And it's always better for me, no servers, scalability, and and for the client to be able to the side which page off that set off that query said he's going to be getting so let's see how implement this. Okay, so in order for us to implement pagination we're gonna need, we're gonna use the pagination method or functionally start mongo engine provides. And so we're gonna define a constant here, and we're gonna call it stores per page. And when I said that to 10 So I'm gonna say, for every hit to the get, we're going to get 10 stores and then, you know, well, paginated through that, then I'm gonna have, um, on the get for all the stores I'm gonna then get this, um, these are store objects, filter life equals true. And, um, we're gonna be passing a page parameter on the euro that we're going to get and then Pagine eight using that that page and the stores for page. So let's do that. So this is the request that we're gonna pass and then stores equals stores. That paginated page equals the base that we're getting past. And as you can see here, if you if you don't get any, then we'll defaulted toe one and then per page is gonna be that constant that we had in in the top they think we're gonna do is we're gonna insert a self HR eight ref link to, you know, support, hate owes. And we're going to say that this this is a page a specific page. So we're going to say, um, links, and we're gonna have the HF h ref store space equals page percent s. And these will, um this will, uh, match the page that were on that's being passed on the on the request here. Um, so that way we can say this set is is belonging toa this specific page and I think that we're gonna do to also make it hate owes. Complaint is we're going to say How do we get to the previous page? And how do we get to the next page? So the client knows how toe Pagine eight. So that we were gonna do that is the following we're gonna have If stores has previous and , as you know, has previously saying, kind of like a functionary that pagination on the Mongol engine has and we're gonna pain toe the response links section Ah, the previous page. And also, if stores has next, then we gonna upend the next stores. Um, which again is it's a function off the ah off mongo engine has pre brief number and next number as the as part of their of the pagination our system so cool. So we're gonna have a Not only we're going to see what the current page is, but we're going to say to the client, Hey, and if you want to get the next set or the previous set, then you can hit this right here. So let's save this file and the last thing we're gonna do it's gonna modify the templates. And as I've bean telling you, this was kind of like a placeholder. We're going toe replace this with the following, we're gonna have a stores object, and then we're gonna bludgeon it through the store items. And I should know store items. Is the pagination kind of like query set or the page with the 10 results or whatever stores per page we have? Um, um kind of like identified. And then we're gonna upend the store object. And as you can see, it's this is referring, referring Sing this. So where we have a very scalable way off reusing this, asked the individual result for each object and finally will return the store subject, which is gonna be this this list off objects that are store optics. So that's pretty much it, um Let's see how we can get the stores. And ah, just so you know, I kind of, like, implemented or inserted a bunch of records. So if you hit Devi store fine. Now I have to put you specs. A B I I have this, you know, a bunch off records so that we can see the pagination better. So, actually, have I believe 20 something stores dummy stores that that I've created. So let's go toe postman and and see if the pagination works. So, um, the service running looks like everything is good thing. So we're gonna go ahead and get older stores here, and so I'm gonna do send, and here you go. So we have a 200. Okay. And as we can see, you have links. I have a self, which is page one. So this will be ph. One off the set. And then I have a next trap, which is spates, too. Then it says results. Okay. And then I see the stores here, Um, and if you, you know, count there should be 10 in stores in there, so that looks good. So how do we go to the next door? Well, we should we should a page to here. Um, and I can just put it here. Page equals two. Send and see. Now I get a self, which is page two. I get a previous, which is Space one and the next, which is page three. And again, again. You know, the next 10 stores. Um, notice How do you know the four money is ISA stores object that we have on our template, which has the self and and all the stuff in there. So I have to say, Looks pretty cool. And then finally, Page three. This only has previously doesn't have next because we only have 23 stores. So here we see only, Ah, I think it's the restores. 12 Yeah, three stores. So awesome. That looks really nice. It's a very professional results set and pagination, as I said, should be the method or you use when you have, you know, any any list off object that you're going to return back to the client. So that's that. Let's continue on, um, because we need some some testing for this for the store's app, so let's start doing that. 27. Store Tests: in this lesson. We're going to implement the tests for the stores and point, and we're going to start using something completely new that we haven't used in any of the court has so far, which is fixtures. So features are think of them as data that you can store on your own, your actual repository that contains stormy data that then you can dynamically load into your tests so that you can test things like, for example, we're going to use it for the pagination. So instead, off you creating like code toe pretty use, like you know, 23 stories like the one they that I have now you actually create these files called fixtures and then when? When the tests, I'm running those pictures, get loaded toe the dummy database, and then you can do operations on them. So let's see how we do this. So I have already loaded the tests from the repository, and you can, of course, see the they call yourself on the on the link that I'm providing. But, um, I just need to one eyed like go and type all this stuff from scratch because it's gonna be things that you've already seen. So let's just go quickly through them. Um, we have a store test test case where we create a nap. We set it up as a social and tear down. We have another up director dictionary that's gonna be pet line, pet secret. And this is kind of new. We're doing a stored dictionary where we have kind of like a sample at, ah store object that we're gonna used over and over again. And, um, we're also gonna be created something. Um, a method that I think I used a lot which is create the a p i app. So I just kind of like post to the apse with the with the app, the actually the app dictionary that we have in here on the top and as well as generate an access token which we kind of like need as well. So I kind off just supposed to the access token with the object up dictionary and then store that Assad s a property for the classic old self token that then I can reuse. And finally, one thing that we haven't seen in the past is having a headers method. Onda again, this is to make things easier for for the for the access off each request because it requires that we passed the bet lined and the token. So those are like helper functions that we're gonna be using. So ah, the first, um, store test stores. Um, kind off test battery is gonna be Ah, pretty. Also pretty simple. So we created a P I app using that method that we describe above and generate an access token. Now, in this, at this point, we have the self talking available, and then we're gonna create a store. So, um, notice how we have, um the Heathers equals self headers, which is this myth it that we have here in the top. And now you can see why I made it. Ah, a function because we're going to use this over and over again. So here we create a store. We passed the sore dictionary and we check that we have a a 21 that's created, and we also fetching the store I d from the Jason. That's return so that we can re use it afterwards. So then we can test getting a store using that store I D and which you get a 200 we also can edit the store. And here I passed, like a different kind of like store object. And then I put the as you can see here, I have amusing put. Um, so the stores and point and then I checked that the new phone that I passed here is being stored on the on that object. And finally, I am testing the leading. So, you know, I just go ahead and delete that store I served that I get a to a four, and then I also get, um, do aquarium mongo db to see if the if the count off stores that are life becomes false is equal to one. So all that is kind off. Not too surprising. And I think, you know, again, you can see it in detail when you when you don't know the code from the from the repository . Now, here's where things get interesting. I'm going to have a, um a a message that I'm gonna be ableto, um access from from the steps, and I'm going to place it on the application. Be Why? Because it's kind of related to the application. Um, so here at the end. I'm gonna do the following. I'm going to define a fixtures, um, method and what it does, It leverages manga import with, um, which is a command that Mongol TV provides. And it basically you can define Ah, host, which is stash h. You find the database, which is that Dash d Um, you passed the dash C, which is the, ah, collection that that that's going to be Where you going to import that file to? And then we have a fixture, which is a Jason file, that we're gonna pasto this to dysfunction. And then we used the call command, which is a a python like low level, um, kind of like a method that allows you to run, you know, shell commands within a python script. Now, for that, I need to add a library here called So process. So when I say it's from some process import cool. And, um, I also need I believe the os, um Let's see, Not only there, Wes, I need among go to be host us. I'm gonna import that from setting. So from savings import Mongol O d B host host. Okay, I don't think I need anything else in here. Um, So let's save that, then the other thing we're gonna do is we're gonna create a, um they ah, fixtures in the ah, in the stores. Um, in the store. Slight directory. But so I typically and you as a professional developer, you'll see this. You typically create a folder within your app called fixtures. And then inside that you're gonna have a new file, and then, you know, this is gonna be stores, not Jason. So here, we're gonna put the all the Jason objects. And here, you see, there's 23 stores in. They're gonna save that. And then the next thing is is going toe the test itself and adding this functionality. So we're gonna go to the test, and then we're going to say, um from application import, uh, fixtures. Okay, so let's see how we use Thea the pictures on this on this test that we're going to do for the pagination to let's create that method and it's gonna be called test, um, store pagination. And so we're gonna do the created A p I up and generate access token and see how we're now doing the features from the application. So we're they're finding that DVs a self DB name which is here, all the way on the top, and we're gonna have the collection is a store, and then the fixture is and you can just ah, uh, put the path from the from the top level store fixture store. Jason. So from this point on, after we run this command, the all that's all those stores are going to be available for us to tests on, so to run tests on. So it's a it's a big time saver. And it's, you know, release it to create Now test that are gonna be testing the pagination. So let's let's write those. So first I'm gonna do I get old stores so I don't get with headers on content type, and then I'm gonna assert that the half next in the RV data Why do I know that I makes is gonna It has to be there because I have more than one page and so that there would be a good you know, I'm testing properly the, um, the pagination there, so the next tests would be get the second page, so I'm gonna pass page equals two past the headers and the content type. And then I should have previous in the is the RV data as well. It's next because I'm in the middle off that off that pagination. So, um, spread That's pretty much it. I mean, you can come up with other tests. I think this is This is pretty good. So let's say that. And then finally, we need to add our new test here on test. So we're gonna say from from store tests, Import store test. Okay, finally, we need to run the test, so make sure that you have your, um, your containers fronting. I'm gonna do it right here on the manga db window. So I'm gonna say docker exact dash i t I didn't look at the docker ps o What? That um docker ps So it's pets ap I Web Ron 18 and then I'm going to say by phone three tests p y perfect. So that run well, noticed that we have a connected to mongo DB and then it says, imported 23 objects. That's from the Mongol import, Um ah, command. But as you can see, you know, we run all the tests and everything looks OK. So that's set for stores. And the next piece we're gonna we're working on is the actual pets endpoint. 28. Pet Endpoint Initial CRUD: Okay, now that we have our stores endpoint, we're not going to go back to the pets and point. And as you can remember, it was a test very like in memory. Kind of, Ah, list that we had in there, and we're going to not make it a proper kind of like bets endpoint with the database model and tests and all that. So let's start working on that. Okay? So you can see here we have the pets, FBI as it stands today, and, you know, it's a list off objects and get in the post. We're kind of like manipulating that that list. And of course, we wouldn't want to do that before we get there, though. Um, there. So you know this views B y is actually gonna work fine. The only thing that I'm gonna change here is instead of being an end here, remember that we're gonna have an external I D. Um, as the stores. Um externality. So we're gonna do this? Um, no resident, but I see just a simple parameter that's gonna be just like a like a strength. So that's the only changed that we're gonna do in in the views. Um, And before I work on the A p, I let's actually do, um, set up the models that we're gonna be using here. So we're gonna use the following model so important db from the application. We're gonna use the store models here because we have a foreign key, but the bed model's gonna ever have on external, like d a name s species. Um, a breed and age the store that that pet is located at, we're gonna have a price. Unless you can tell there it's a decimal field. We're gonna have a sold bullion, which means that if it's true that it was sold already, we're gonna have a received date, which is the date that the bet came into the store. We'll have a sold date, which is the date that the pet was sold and they're gonna have a life bullion, which is as kind of like we've been seeing. That's kind of our delete operation is gonna affect that, but we're actually not gonna erase any any pets. The other thing is on the indexes. I have more in the six indexes here because I'm gonna do some searches that are gonna be more a little bit more complex. The 1st 1 is gonna have external idea in life that's gonna be applicable. When I'm looking for a specific pet, then I'm gonna have a species and life, which is we're gonna use when we look Search for a ah specific species. Onda. Actually, now that I think of it, we're also gonna need breed here in this index because I'm gonna be searching for ah, you know, species. It's like dog or cat and breed is kind of like what type of dog, like, it's a multi Zohra Sheets who, um and I were going to do, like, searches across the entire pet that I base Ah, using those two fields. And finally we're gonna have a store because we're going to search for Give me the pets that this store has. So that's her models, and that looks good. So let's start working on the A p I. So there's, ah, some leverage that we're gonna use here. Um, we're gonna have Jason Schema for the scheme of validation. Um, we're gonna use you. I d for the Xterra. Lady on. We're gonna use Jason s well as daytime. We're also gonna use, um, the bet scheme other we're gonna build and a pet templates in this and this a p i and we're also gonna use the store models when we return the pet details. We're gonna basically, um, you know, print out the store. Um, so that's that. Let's start working on the actual, um, let's see here on the actual Perry p I class, and the first thing we're gonna define is an innit method. So we're gonna have, um, the pets per page, just like the pagination that we had on the stores and wheels going to check if the request method it's not equal to get. And the request Jason is, um, it's not set. Then we're gonna be aboard without 400. And I actually wanna added that because, um, if if if the lead is being passed, we don't pass a request, Jason, either. So and I think we saw that as well. So we're gonna actually do the following a request method. It's not get and request method is not delete. And we don't have to request Jason than a poor 400. Okay, so let's work on the pet, um, on the get here. So we're gonna do the following. So I'm gonna take this out, and I'm going to say if a light is being passed, then pet equals bet objects that filter external paid I d equals bad idea and life pickles . True. Returned the first object. If there's a hit, then return the response, which is gonna be a result, okay. And then the object which we're gonna define on this template that we're gonna work on in a bit, um then finally returned that responsible 200 otherwise returned a 400. Ok, um, let me also just put passing here so that we know that we're gonna work on this one's afterwards. And let's start working on the on those templates. So the first thing we're gonna work on is thesis key. Might be why, for the pets and this is what it looks like. Um, it's gonna be a type object name is gonna be string suspicious, string breeder. String age is a number, and then store is a string prices a string. And why prices string another number because it has decimals and Jason's handling off decimals. It's ah, it's a little bit complicated because I think that the closest thing we would be using would be float. But float has, you know, it's not just two decimals. It's a bunch of them, so it can get complicated. So I decided to use Price as a string. So remember that when you're passing or posting toe that endpoint, finally I'm gonna have a received date, and that's gonna have a pattern off the soul date that we had used in the past. Ah, which is, you know, the year, month, day, and then the time, which is hour, minute, second, and then the Z, which is UTC. Um, and finally I I'm gonna make all the fields required. So that's the schema for the templates. I'm going to use the following gonna have, um this is template B y templates be why, and this is where we're gonna do there. We're gonna have the, uh we're not important store object because you'll see that we're gonna use the store in here in the we're going to return the store as part of the template. So the better off just going to return the i. D. The name, the species, the breed, the age, the store as a story object. And this is a very cool thing. We're actually leveraging the store optic that we have in here. So, you know, we're not repeating all of this, and we want to When? When we're returning a pet. We want to. Ah, return. What store? Doc? Bet is in. Um, I don't have the received date, which we're we're gonna do. I s O format of it. Um, without the seconds. And then the links section, which will have the self and finally, the pets object is gonna be the the arrayed that's being passed when we do the get not the individual pet, but the, uh, all pets for that for that store. Um, well, not for that store for that for that end point. 29. Finishing Pet GET, POST and Postman Tests: Okay, let's continue working on the A P. I hear. And, uh, So I'm gonna do now the not the individual pet, but the if you're getting all the pets. So we haven't else, um, we're gonna get older pets that are live, and we're in return the pagination using a page. Um, And then we finally have the result. Okay, with the links toe the specific page, and we're gonna pass the bets. Object if the pets pagination has previous than we append that link toe the h air h, ref. Um, And if it has a next, then we append. That s well, so nothing that we haven't seen before. This is very similar to the stores and point. Um and that's it. So now let's Ah, let's work on the post. Totally not replace starting here. And so we're gonna have, uh, bets. Jason is the request, Jason. Then we're gonna check if the validator past the, um, the schema. If there's any errors than you return our message, then we fetch the store. We're gonna pass the external like the on the pet opposed to see if I mean to get that back into a specific store. If this story is not found, then we return, stored, not found. Then we're gonna test that the received eight. It's actually a good date. And we do that using a try, except if that, um, that method called string. Um, P time, which is spotter in time, Uh, doesn't Doesn't, you know, error out? Then it's fine. But if it doesn't, that's an invalid date. Finally, we create the pet object, and here we're gonna have the external i d the that we're going to create. Ah, that moment would have the name species breed age store price and received eight. And we're gonna save that that object and finally will return back the pet object. Um, with a 21 which means that the the object was created properly. Um, no, I put this twice, so we get rid of that. Um, cool. So I think we can go ahead and do a couple of tests here before we do the put and elite. So here we have our postman and, um, you know, before we kind off, like, play with the with the post and point for the pets, Let's go ahead and check that it's open running and it's running. And I have this one I, like, put a pet in this first store. So I know. I note the I d ah, here. And then I'm gonna gloat up the post. They start the start of the old kindof test that we did at the beginning of the course, right? So they're not Ah, they're not kind of like working properly. But let's see if we can make this. So have the post endpoint. It's gonna be local host pets. I thing we don't have the header, so we need to get the headers, and the body is definitely not not right. So I just made up a an object that where you can go ahead and test with. So it just is my actual dog, Mac. He says she to, um the H is actually 11. Ah, he's this store. This is a price that I just made up. But to me, of course, he's his much more valuable than that. Ah, So, um, I need to Let's save that for now. I need to get the token here for this. So we're gonna have X up. I d X Uh uh, The small bile and then x token is that value there. So let's go ahead and save that. So we have their body, we have the headers, so everything looks good. Um, and let's go ahead and do a post on. Let's see if this is running here. Yeah, it's running. So post Ah, we got an error. Penn is not defined. Um, see if I can check the the package or the file that's throwing that out. Okay, so I think I don't have I mean import from pet models. Import pet, Uh, today Strange. Oh, because it was God. It was here before, and I think I just overrode it from pet models. Import import Bet. Okay, let's try that again. Perfect. So we got our pet created. You can see the details here. So we have. It's a sped H breed. I d. The links is the individual pet name. Mac Price received date. The date came in perfectly fine. And ah, see how we're passing. This s a dating there, but this is very this is a tricky thing because we're actually passing this. This is a string and what we're doing on the a P. I is that we're, um, using this. Ah, a string, um, daytime daytime string pattern time which converts a known pattern for a specific, um, string into a daytime object. And that's what we're saving on the database. And then when he gets on its way back, we're converting that to, ah, string using the ice. So format. So it's it looks very simple, but it's actually a pretty cool set up. And you can you can use that for your for your AP eyes Now for the get um, actually, ah, I mean, we could get the i d. Here. We're gonna have to, like, also copy and paste the up. So that's for this big Let's let's do they get all endpoint. So see if that works. So get all pets and point Uh, we have the token, but I might not be the the latest one Coffee and face that just in case. Oh, it was It was a good, very good one. So if we said send, here you go, we get all the pets. And of course, there's not many of them, but it's ST Pat's base equals one, and it's returning Mac as the as the only object there. So that's all working. Fine. Now let's get one pet and point. This definitely needs a lot of work. So I think I copied the the Max I d. And let's get the the headers. So we need X. Uh, be mobile X toke and no up talking. Um, and let's copy that. Wait, that's the That's the token. And the idea I might maybe getting wrong. Where is Max? I'd be this one here, okay? Based Starting here and save this Send. Perfect. So we got max object here and there you go. Um, notice that we're, you know, we're getting the store details here, which is a very good This is how it the AP ice should work like you shouldn't be. You're saying store and the the I. D. Um, you should just, you know, help out the climb with with all the information. If it's a big object like the store has a lot off objects in there, then definitely you could potentially just pass idea, maybe some key details, and then have the decline get all the details for the store, but because it's not a big object, I think it's good that you embed other objects within the the return Jason that you're giving back to the client. Perfect. So now we need to work on foot and the late so let's go ahead and and work on that. 30. Pets PUT and DELETE: Okay, We're gonna work now on the put and elite, and this is very similar to what we've done in the stores, and it actually similar to the post. So I'm just going ahead and pace that from the repo. So we have a, um we're gonna look up the pet based on the pet I d. And we if we don't find the bed, we're gonna return the 44 Then we called Pat, Jason, Toby the request, Jason. And we're going to go through the validator for for that for that Jason object. And if there's any errors, will return to 400. Um, then we look up the store based on the on the store string, and if we don't find the store, then we return a 400. And finally we try the date on DSI that it's ah, it's a validate. If all the those things go, well, then we just set the the different properties. Main species breed age store price and receive date, toe the toe the pet and then save the object. Finally, where we returned back, a result off. Okay. And then the bed object is the passed with the bet that the leader is gonna be something similar. So we get the pet from the external like the Andi. If the bed is not founding, would return for four. If it does, if it's found. And we said their bed life, toe false, save that and return a tool for So those are the put in the lead. So let's try those out on the enforcement. Okay, So we're gonna test these things now on postmen, and we have a a put here, but I'm gonna are probably just, um Yeah, let's let's get the object from the from the post endpoint on its year body Go. And so what we're gonna do here is we're going to, uh, update Max talk to Max H 2 12 So he's a year older, and we need to update that, um, the pet I d. We need to get from the Guettel bets and point here. And oops, I copied the whole thing. The i d. There you go. And it saved that for now. And finally, we need to add the headers. So let's see the token here and x up. I d. It's more vile and accept token. Is this Okay. Looks like everything looks good there. So let's save that. And awesome. We get out. 200. Okay, let's see the age. He's 12 now. Uh, where's H O. H. Is the 1st 1 So the record was updated properly. We got a 200. Okay, so that looks good. And if we get the specific end point, you see the age there says 11%. Now you see, the age is 12. Awesome. So now let's do the elite. Um, we're gonna copy the I'd be here, and we're going to get the headers X up. I d is mobile X up token. And it's good that from here. Awesome. So that's all that we should need. Let's save that. So we have it and send perfect. We got a tool four. Which means that the server deleted that. That bet if we try to get Mac Now, here we get a four Ford not found, which is their behavior. We wanna we wanna have. Awesome. So we're done with the crowd. We've create, read, update and delete. And now let's go ahead and write some some tests for the bed 31. Pets Tests: So we're done with the pets Krug endpoints. And now we're gonna do the pets, um, tests for for that For that part of the A P I system. I'm gonna go very quickly through it because it's most of the stuff that we saw on the store's FBI. However, there's a couple of things that I'm going to show you. One is, um we're gonna have ah fixtures for the pets and the stores mixing one test. Um, and I actually added ideas to the fixture. So make sure to check the repo for the for the stores fixtures fixtures because now they have an idea at the beginning. And that way I can. Then the pets fixtures can address or ah, do a reference field. Two stores that are on that Jason, um, stores fixtures file. So let's get started. Okay, so let's add the tests file here, and I'm going to go quickly through this, like I said, because it's very similar to the store test. So we're gonna have the different libraries included. Um, that's where that's the settings the models that we need and eso here. We get the pet test class. We're gonna create an app with this based settings. And ah, we're also gonna have the set up with the application factory and a tear down which is gonna have the that are based being dropped. I'm also gonna set up a an ab dictionary, which is gonna be cold whenever we want to create a new app a stored dictionary, which is a kind of like a dummy store that we're creating here. And, uh, finally, we're gonna have a ah pet dictionary, which we're gonna have, um, with some some boilerplate kind of like, uh, pet object. Ah, And again, as we can see, I have the, uh, my dog Mac, in there. Um, then we're gonna have thea a method, um, helper mythical. Create a p i app, which will Ah, basically post too great an app with with the apse endpoint. And then we're also gonna have a generate access token. Ah, helper. That wheel generated access talking and said it asked the self token for the for the class from that point on, um, I also have the headers, and finally, we can start doing some tests. So the first things that we need to do here, he's to grieve the A p i app and then generate the access token. Ah, generate our first store. And then finally, let's test the create a, uh, a pet. This is the actual first test that we're doing here. So we're gonna post to the pets endpoint with headers, the back dictionary that we have and the pet I d is gonna be stored in this viable and we'll assert that we got a tool one. So lots of stuff there. One thing that is a little bit different here that I don't know if you noticed is that on the bed dictionary? I'm actually referencing self story t So you would think, like, why does it Why does that work? We haven't even, like, set up story D by that point. Well, the things that when we set up or we define the helper method, we're not actually calling it. We're just defining it. So this is kind of like a viable that's gonna be set later. And actually, when we call it, we have already created a store and I'm storing that in that self story. Be so that when I called the Self Back Dictionary that, um that viable is exists and and and it can go well, So that's a little trick that you guys can can use. And, uh um, you know, we're gonna be using that in this case, eso No, let's go through the the older tests, which is get and edit and delete. So for the get up it we're gonna do, ah, we're gonna hit the endpoint for pets. Plus paid I d with the headers and we should get out. Ah, status code off 200 for edit. I'm going to, um, create a new object that it's a completely different bet. And I'm going to basically hit the put endpoint with that pet i d. And I'm going to check that the status Cody's 200 and that, uh, the the pet species has been updated to be cat. And finally, I'm going to get the elite a pet which is hitting that same endpoint with delete and that had I d. And I'm asserting that the status code is to a four and that the count for pets that have the life equals false flag is said to one. So that's a pretty comprehensive set off, you know, test for the crowd. Part of it. Uhm I'm going to now go ahead and ah, at the test on the test B Y. So I'm gonna go here and I'm going to say from BET tests import pet test, and that's gonna then include that in there. Um, that's, uh that's a good start. We're gonna test the pagination with the with the with the fixtures, but I think we can We can run this test now and see what what happens. So to run the test, we're gonna make sure that our continuities up and running and we check what the docker container name is. Ah, it looks like it's pets ap. I went one. So I'm going to say docker except Dash I t, uh, pets a p i Web one and then by phone. Three tests be Why? Okay, so let's go ahead and run that perfect. So here I see that the fixtures for the stores with was run. That's why we get that imported 23 objects. But the tests are running fine. So that's that's a good start. So let's go ahead now and and try setting up the fixtures to test pagination 32. Pets Pagination Tests: so the forehead and create the fixtures here on the bet. So we're going to create a new folder called Fixtures. And inside that folder, we're gonna have a file called Pets that Jason and Ah, see. So I'm going to copy that from the from the repository in Here you go. So we have Ah, we have 15 pats, and a lot of them are Ah, you can see here that they have a, um and I d already being set as well as an external like the and, ah, a lot of them belonged to the same store. So you see, here is the B eight c at the end, with the exception of the last three. And that's because I want to test pagination on stores as well. When we get to the point where we're pagination vaccinating through pets that are in a specific store so you can grab that up. It's the Jason from the from the get report, people that that's linked in the, um in the course. So that's that. So now we're gonna do the second part of the test, which is going to be the pagination piece, So let's get started on that. So let's go ahead and test the pagination function there. So we're going to say test pagination. Uh, first we get the up up and running, and we're gonna import the two fixtures, the stores and the pet, and we're gonna now get the older pets. And we just need to get the, um, the at the pets endpoint and check that next facing there. And then we also get the second page of pets and we're going to check that the previous page is in there as well. So that's that's pretty much it. That's all the pagination tests that I have. And I think it's ah, it's a pretty good text test coverage there. So let's go ahead and try to run that. And so let's clear the screen here and run Python three tests. Perfect. So everything run run perfectly notice here that we have now the 15 pets being imported and the 23 stores on, um on the second fixture that on that second test that we're running. So that's it. Um, we have our pets, but fully tested, so Ah, we're pretty much almost Ah, the end. Um but we have Ah, a couple of lessons now. We want to go through 33. Get all Pets in a Store Endpoint: Okay, so the next two lessons it's gonna be about search functionality for R A P I. The 1st 1 we're gonna do is get all the pets in a store. And the 2nd 1 which is gonna be the next lesson, is to look across, um, the older pets using filters for, like, the breed and the species. So let's see how we do that. So we want to get a an endpoint called store story D pets to get all the pets in that store . So to do that, we're gonna have a new endpoint, and we're gonna call that the the following code. If a store up on your l store story, the pets and we're gonna get that using a get method, Um, from the from the FBI. So cool. So far, so good. So we're going to, um, next we're gonna work on the A P i itself. So let's save that. And we're going to add a couple off libraries here when I say from fat models import pet and from pet templates import pets up. Um, I also gonna have a kind of like the same, uh, constant here. I'm going to say self pets per page is gonna be 10. So what we're gonna do is we're gonna have pagination on the, um, on the actual endpoint. Um, and, uh, we're going to, um, half. If there's more than than 10 pets on that specific store, we're gonna have the, you know, previous next, uh, kind of like endpoints. So the next thing we're gonna do is we're gonna modify the pet, um, en pointe, and we're gonna have a the following code. Do and say, if pets is in the request, your URL, then we're going to get the objects off the pets that are in that store and then set the page viable and get the pagination of it. And then the response is gonna be a result. Okay? With the links off the ah, that pets page and the, um, the actual store object embedded in there. Um, if we have previews and this is kind of like you've seen this before, then we're gonna penned a previous page toe the the end point, and we're gonna also check if it has next. Then we're gonna have the, uh the link upended us. Well, okay, so that's That's if the pets is in the request that your URL then we're going to say otherwise. Um, if that's it's not on the on the end point. Then we're gonna have just the response for the for the store object. And, uh and then we just returned the object back to the to the end point. So that's the modification for the story, P I Now we also need to do some some changes to the pet templates. Um and so the idea here, this is a new thing that we're inserting here is now we're gonna pass a flat called No store equals true. What's the idea? The idea that I had waas If no story was true, then we're not gonna have on the pet templates. Uh, right here. We're not gonna have the store link, uh, sent in there because it's gonna be It doesn't make a lot of sensitive. Ah, if we're looking for the pets in a specific store to have all the pets in there with with the store repeated over and over again. So what we're going to do is we're gonna have that store piece to be optional, and it's gonna be only displayed if they know, Store flag A said too true. So let's see how we do that. So we're gonna have, um the flag notes store equals falls here, and that's a default. And remember, on python functions when you, um when you pass a perimeter with a default value, that means that you can either pass it or you don't have to pass it. Um, so that's kind of like a a na optional a notional parameter. And what I'm going to do here is I'm gonna take this out and I'm going to say, instead of return days, I'm going to say bet object equals to this. Okay, um, and then I'm going to say, if not know store. Then I'm going to say pet object off a bit. Object. Oh, store is goingto be store object off pat dot store. Okay. And finally, I'm gonna return the pet object, and I need to also have the no store flag here because remember, dysfunction can be called, um, from the for the individual kind of like template, but also it could be called from the If I get a list off pets, I want to be able to do that as well. So here I'm gonna say pets object. A pen pit object, Bad Kama, no store. And the way I passed that flag down to the to the pet object Um, the function. So that's that. And I think that's all we need to do for the But we need to do a small change on the on the store templates as well. So it's the store templates. So what I'm going to do here isn't going to, um, at a the pets endpoint the new endpoint toe the the length so that we can ah, you know, observe. Hey, does and ah exposed the possible links that we have. So I'm going to call these pets Rehl. So? So we need to get the pets. And then I'm gonna say slash stores slash percent ask which is going to be a string slash pets and then percentage. Ah, store that external. I be okay. So now we're gonna have to links one. It's gonna be this self and there one is gonna be the pets rail, which is telling the client, or by the way, if you want to get the pits on on this store, you just need to do this slash pets on the individual. Ah, store cool. So let's try that out and see how it works. 34. Test the Get all Pets in a Store Endpoint: Okay, so now I want to try out getting the pets on a specific store. And for that I want to blow it up the fixtures using this fixture Ah, function that I have on the application p y and load up older stores as well as a pet. So this this ah, fixtures you confined on the under repository that I that I'm pointing on every lesson. And the good thing is that the fixtures have for simple the stores have an i d. On the bet. I have the external link to the stores using the idea founding here. So you have ah, pretty good set off data to to play with. So you don't have to, like, build that from French. So the way we're gonna do that is we're going to open, and you make sure that your docker containers are running and open a new a new tab. And on that top, we're gonna try to get the, um, see the by phone, manage me. Why shell and import that that fixtures function here that we have for that for the test and use it to load our or data. So I'm gonna say docker ex SEC. I t, uh pets ap I Web one by phone three Managed B y shell. So I'm calling the manage Me. Why? Using python three within the container, But I'm actually interacting with it from the from the shell from my other odor shell. So see, you have those three little arrows there. That means that we're on the shell and we're ready to go. The first thing I'm going to do is I'm going to delete the existing data that we have so that we we have, you know, everything clean from from scratch. So I'm gonna say from store models import, uh, store. And I'm gonna say from that models import pet and they want to say store store optics. Oh, the elite. And I want a safe pet objects, all the elite, and they won't say from application import fixtures. Is that fixtures or fixed her fixtures? Okay. And then I'm going to say, um, fixtures. We have to pass the database Earp. It's a p I. We have to pass the collection, which is store, and then the relative, um so the the the picture filed relative to the to the petopia. So it would be in this case for the for the store would be store fixtures, stores, Jason, store fixtures, stores, Jason, um, and that imported the 23 objects there. Um, let me clear this screen, and then I'm gonna say fixtures fits a p I, uh, pet. And then two pats fixtures. Facts that Jason. Oh, is it bad? Bet? Yes, their pet up. Correct. Awesome. So now we imported those 15 objects and the stores as well. And let's go and check if we have the stores set up so correctly, so I'm going to get all the stores and perfect, I have you know, page one eyes this one page too, which means, you know, it loaded more than, um 10 which is a belief tennis, the number of source. And, um, and let me get all the pets to see if that works as well. And yet we have We have a bunch of bats in there with a different stores. So now I'm gonna test the what we just did. Now, which is get the pets in the in an individual store. Um, I preloaded here. I have ah store I d. That's the 1st 1 that has more than 10 pets I wanted toe. Also check on the pagination so still sent. And as you can see here, is working perfectly fine. I get all the pets that are in that store and ah, looks really good. And we have a page tool. So if we pass here question mark page equals two. We get the second page. So perfect. Now you see how that is working. And, um, you know, it's it's ah, it's a very good approach to getting objects that are within a another object in a related fashion. 35. Search Pets with Filters: when coming functionality that we are now we find in AP eyes is the ability toe filter across objects using some sort off like parameter on the commander on the your eye where you came, for example, in our in our case that say we have the Guettel bets endpoint. Um, instead of seeing all the pets across all the stores, maybe I want to see only the dogs, right. That would be a very common use case. Right? So, um, what I would like to do is I want to say something like a question mark and then put, um, species equals dark, for example, and have the ability to filter through through all the all the pets and point, um, but only showing that the dogs and the same thing. If I wanted to further filter out, I could do something like and breed equals. Ah, Sheets would, let's say right so I would be They would be getting all the older sheets who dogs across all the all the pet stores because, you know, if a common for Charlie would be Oh, I want to get a sheet to and I want to see what stores they sell that that type of dog in. So that's what we're gonna do now, and it's not very complicated. Actually, it's a very scalable solution that we're gonna use. So let's go ahead and modify the pet A PR endpoint. So let me closely stops here. And so the one thing that we're gonna have we're gonna need that we don't have right now is you see how we have all these pets like the H ref and the has previews. That's next. We need to modify that because we're gonna have filter. So were you would be kind of, like, strange to be doing If the I want filter parameter is species, then send this link and if not and so that would make a lot of sense. So what we're gonna do is we're gonna have a some sort off template that we're going to insert here, which is gonna be pet h r H ref. And then we're gonna say pets page and then percent s, which is gonna be a basically that the pace that the person is saying, but we're gonna be ableto then dynamically add to that H ref based on the under filters that the user is eyes requesting. So here we're going to do the following. So in in beneath the the actual filter here, we're going to do there following it's gonna have if species, in request arguments, we're gonna filter by the species and at the pain that h ref that request argument on the same thing. If we have breed in the request arguments, then you can filter that using the, um, the request argument and add that to the parrot rifle. Now, one cool thing about using queries in in or EMS is that you can further filter. So, for example, if we had species and then breed minorities that we're modifying the pets query twice and that's fine. What that's what What that is going to do is we're gonna have pets initially is gonna be filter by species, right? So, for example, we have a dog or dogs. Um, then when? If we have a breed also in there, this pets is referencing this pets already filtered by by dog. So you're like doing actually a second filter, which is perfect, is exactly what we want to do. But if by some you know, if the user is passing only brave, for example, so breed equals shit. So without passing the species, that works out as well. Because these pets then would be referencing all the pets like the, um the older pet objects that we have we have in here, right? The life equals true. And now we would be just, like, filtering with with great, which doesn't make a lot of sense. If you were looking for she too. I would say that you would also pass species, but we're not limiting that. And filters in nature should be like that dynamic. So I'm just like, posting that it will be the case here. Okay, so the next thing we're gonna do is we're gonna update these h ref. Um, viable is to say, the following It's gonna be now bad h ref and then percent page. And that way we're gonna have it's gonna be using the the new template for the for the your eyes that we're finding here. So same thing here. And finally the one on here. Awesome. So that's that. So let's say that and let's try it out. So right now, if I do pets next, check that that's working. So that looks good. And the you see that the template ing or they're a treff viable is working fine in there. Um, but now let's go ahead and search for dogs only. So we're gonna do ah, species equals dog and notice that I'm doing ah, higher case or upper case on the D because that's the way that it's store on the, um, on the data objects we could dough that, you know, with a lower case. But we would need to save all the objects to have that, um, nor cases. Well, let's write that out. And perfect. Now I see that the A treacherous bets Ph one and species equal stuck, which is the the current a drift. And now you see that I only get, um, docks in here, which is pretty cool. Um, and that seems to be working Fine. And then we're gonna ah, check for the the other filter, which is the the breed. Right? So we're going to do and breed equals Ah, shit. Sue and then send. Okay. Perfect. So they trip now reflects that it's a space physical starting breeding equal sheet. So and now I only get one dog, which is my my dog, Mac. Um, so perfect. So that's that's it. That's ah, how we can do filters. And you can think about setting off filters for, like, the stores, for example. You want to get the stores on a specific neighborhood or sit code. You know, the sky's the limit. So awesome work. 36. Conclusion: Okay, so that's it. We've come to the conclusion off the course. I hope you learned a bit about rest ful FBI fundamentals What it means to be a rest ful, a p I and how toe used the flask global views to make very simple and very scalable AP I platforms. Now, of course, that's the next step. I will recommend you to take a look at some of the A P I libraries out there. I think the most popular one is is a flask rest ful. And, ah, you know, I could potentially maybe do, ah, YouTube video. Make sure to check out my YouTube video channel with maybe assured, like, tutorial on it. But I think it's better this way to learn how toe build the on a P I platform from, like scratch without using any of these libraries, because then you get to appreciate what what goes behind the scenes and exactly why the libraries are doing the things that they're doing. So thank you so much for completing the course, and we'll see in the next one