... | ... | @@ -34,35 +34,38 @@ Success ! |
|
|
|
|
|
## Since we care about maintainability, lets do a bit of housework
|
|
|
|
|
|
API's can grow large, containing many endpoints and resources and having them all in one file is silly.
|
|
|
A bit of refactoring can go a long way, but first we'll add a new dependency.
|
|
|
API's can grow large, containing many endpoints and resources and having them all in one file is silly. A bit of refactoring can go a long way, but first we'll add a new dependency.
|
|
|
|
|
|
Exit vim, by typing `:q`
|
|
|
|
|
|
Now in the shell, type `pip install fastapi-chameleon aiofiles`
|
|
|
Chameleon is a very nice templating framework, that strives to create templates that conform to xhtml specs.
|
|
|
And the _fastapi-chameleon_ package integrates it with FastAPI.
|
|
|
Now in the shell, type `pip install fastapi-chameleon aiofiles`\
|
|
|
Chameleon is a very nice templating framework, that strives to create templates that conform to xhtml specs.\
|
|
|
And the _fastapi-chameleon_ package integrates it with FastAPI.
|
|
|
|
|
|
Since we'll also be wanting to serve static content, such as images and css, we also installed _aiofiles_, or asynchronous-input-output-files, in short, it allows us to serve static content asynchronously, for added speed.
|
|
|
Since we'll also be wanting to serve static content, such as images and css, we also installed _aiofiles_,\
|
|
|
or asynchronous-input-output-files, in short, it allows us to serve static content asynchronously, for added speed.
|
|
|
|
|
|
And just a reminder, all these things we are installing and building on top of, are all opensource.
|
|
|
But their license therms can differ.
|
|
|
And just a reminder, all these things we are installing and building on top of, are all opensource.\
|
|
|
But their license therms can differ.
|
|
|
|
|
|
While where out here in the shell, lets create a couple of folders...
|
|
|
|
|
|
* `mkdir templates`
|
|
|
* `mkdir static`
|
|
|
|
|
|
And create some files to put in them
|
|
|
|
|
|
* `touch templates/index.html`
|
|
|
* `touch static/index.css`
|
|
|
* `touch api_router.py`
|
|
|
|
|
|
Go back into the editor, run `vim main.py`
|
|
|
|
|
|
We just changed the index function, to return HTML.
|
|
|
We just changed the index function, to return HTML.\
|
|
|
But no one wants to inline HTML into code, and since we just installed a templating engine, we should use it.
|
|
|
|
|
|
Now refactoring code using an unfamiliar editor is a daunting task, so depending on how long it takes, we might have to skip ahead after this.
|
|
|
Now refactoring code using an unfamiliar editor is a daunting task, so depending on how long it takes,\
|
|
|
we might have to skip ahead after this.\
|
|
|
Keep calm and don't panic, it'll be fine.
|
|
|
|
|
|
New vim commands which might be useful.
|
... | ... | @@ -71,32 +74,29 @@ In NORMAL-mode (not insert). |
|
|
|
|
|
* `gg` goes to top of file
|
|
|
* `GG` goes to bottom
|
|
|
* `/` searches a file, using regex. (<Enter> to search, `n` to next, `:noh` to clear search results)
|
|
|
* `/` searches a file, using regex. ( to search, `n` to next, `:noh` to clear search results)
|
|
|
* `yy` on a line, copies it
|
|
|
* `dd` on a line, cuts it
|
|
|
* `p` pastes below current line
|
|
|
* `p` pastes below current line
|
|
|
|
|
|
A lot of vim commands can be composed, so typing `10G` will move the cursor to line 10 in the file.
|
|
|
`d5d` will cut from current line, and 5 down, there are more, a lot more.
|
|
|
But this isn't actually workshop on vim, but remember this...
|
|
|
A lot of vim commands can be composed, so typing `10G` will move the cursor to line 10 in the file. \
|
|
|
`d5d` will cut from current line, and 5 down, there are more, a lot more.\
|
|
|
But this isn't actually workshop on vim, but remember this...
|
|
|
|
|
|
The designers of vim believe that people _edit_ files more than they _create_ them,
|
|
|
so vim is optimised towards modifying existing files, as appose to creating them.
|
|
|
The designers of vim believe that people _edit_ files more than they _create_ them, so vim is optimised towards modifying existing files, as appose to creating them.
|
|
|
|
|
|
Pressing `v` puts vim into VISUAL-mode, as appose to `i` for INSERT-mode.
|
|
|
In _visual-mode_ you can use the cursors to select in the buffer.
|
|
|
Pressing `v` puts vim into VISUAL-mode, as appose to `i` for INSERT-mode.\
|
|
|
In _visual-mode_ you can use the cursors to select in the buffer.
|
|
|
|
|
|
As an example, if we are on line 10, press `v` and pres the down key a couple of times,
|
|
|
and then press `d` - We'll cut those lines.
|
|
|
As an example, if we are on line 10, press `v` and press the down key a couple of times, and then press `d` - We'll cut those lines.
|
|
|
|
|
|
And that brings us to the most import key, the one to rule them all.
|
|
|
And that brings us to the most import key, the one to rule them all.
|
|
|
|
|
|
`u` will undo ;)
|
|
|
`u` will undo ;)
|
|
|
|
|
|
Last one before we start, in _visual-mode_ select a few lines, and press `>`
|
|
|
you just indented right.
|
|
|
Last one before we start, in _visual-mode_ select a few lines, and press `>` you just indented right.
|
|
|
|
|
|
Lets take a look at the final result for _main.py_
|
|
|
Lets take a look at the final result for _main.py_
|
|
|
|
|
|
```python
|
|
|
# Move all imports to top of file, and group+sort them for good measure
|
... | ... | @@ -141,48 +141,47 @@ async def index(): |
|
|
# And the items route has disappeared?
|
|
|
```
|
|
|
|
|
|
Basically, we've added and removed imports depending on their use.
|
|
|
We've introduced to new features, namely support for _templates_ and _static files_.
|
|
|
The index function has gotten a new annotation, that "links" it to a template file.
|
|
|
And we've removed the items route.
|
|
|
Basically, we've added and removed imports depending on their use.\
|
|
|
We've introduced to new features, namely support for _templates_ and _static files_.\
|
|
|
The index function has gotten a new annotation, that "links" it to a template file.\
|
|
|
And we've removed the items route.
|
|
|
|
|
|
As always, press `Esc` to exit insert-mode, and :w to save.
|
|
|
As always, press `Esc` to exit _insert-mode_, and `:w` to save.
|
|
|
|
|
|
Now come the hard part, the need to work with multiple files.
|
|
|
Now come the hard part, the need to work with multiple files.
|
|
|
|
|
|
The easy way, is to simply exit vim, and start vim on a new file,
|
|
|
that could be `:q` and `vim api_router.py`
|
|
|
The easy way, is to simply exit vim, and start vim on a new file,\
|
|
|
that could be `:q` and `vim api_router.py`
|
|
|
|
|
|
But for the brave, working with multiple files or buffers as vim calls them is a powerful skill.
|
|
|
But for the brave, working with multiple files or buffers as vim calls them is a powerful skill.
|
|
|
|
|
|
Here are the most useful commands...
|
|
|
Here are the most useful commands...
|
|
|
|
|
|
- To open a file (buffer) type `:e {filepath}` you can use tab-completion.
|
|
|
- To list open buffers type `:ls`, note the number (n) to the left of each.
|
|
|
- To switch buffers type `:b<n>`
|
|
|
- To go to next buffer type `:bn`, and `:bp` for previous
|
|
|
- To delete a buffer (~close it), type `:bd`
|
|
|
(this does not delete the file)
|
|
|
* To open a file (buffer) type `:e {filepath/folder}` you can use tab-completion.
|
|
|
* To list open buffers type `:ls`, note the number (n) to the left of each.
|
|
|
* To switch buffers type `:b<n>`
|
|
|
* To go to next buffer type `:bn`, and `:bp` for previous
|
|
|
* To delete a buffer (\~close it), type `:bd` (this does not delete the file)
|
|
|
|
|
|
It is also possible to go to an open buffer, by knowing its name, or part of it.
|
|
|
Typing `:b <filename>` jumps to the buffer with that file, and of course, tab-completion is your friend.
|
|
|
It is also possible to go to an open buffer, by knowing its name, or part of it.\
|
|
|
Typing `:b <filename>` jumps to the buffer with that file, and of course, tab-completion is your friend.
|
|
|
|
|
|
And finally, typing `:e .` will allow you to navigate the file system to open a file! ( _Now he tells me!_ )
|
|
|
And finally, typing `:e .` will allow you to navigate the file system to open a file! ( _Now he tells me!_ )
|
|
|
|
|
|
So, lets try...
|
|
|
So, lets try...
|
|
|
|
|
|
Navigate to the bottom of main.py, down to where the `@router.get("/items/{item_id}")` line is.
|
|
|
Press `v` and arrow down to until the whole code block is selected.
|
|
|
Press `d` to cut it, and `:w` to save the change.
|
|
|
Navigate to the bottom of main.py, down to where the `@router.get("/items/{item_id}")` line is.\
|
|
|
Press `v` and arrow down to until the whole code block is selected.\
|
|
|
Press `d` to cut it, and `:w` to save the change.
|
|
|
|
|
|
Type `:e api+<tab>` or `:e .` and navigate to open the api_router.py file we created earlier.
|
|
|
Since this file is empty, simply press `p`to paste the cut-content from before.
|
|
|
Type `:e api+<tab>` or `:e .` and navigate to open the api_router.py file we created earlier.\
|
|
|
Since this file is empty, simply press `p`to paste the cut-content from before.
|
|
|
|
|
|
Press `gg` or arrow back up to the top of the file, and type in the remaining bits.
|
|
|
Press `gg` or arrow back up to the top of the file, and type in the remaining bits.
|
|
|
|
|
|
Press `i` to enter _insert-mode_, and change the `@app` part to `@router`
|
|
|
Press `i` to enter _insert-mode_, and change the `@app` part to `@router`
|
|
|
|
|
|
When the file looks like this, the free coffee is on me.
|
|
|
When the file looks like this, the free coffee is on me.
|
|
|
|
|
|
```python
|
|
|
from fastapi import APIRouter
|
... | ... | @@ -193,11 +192,10 @@ router = APIRouter() |
|
|
@router.get("/items/{item_id}")
|
|
|
def read_item(item_id: int, q: Optional[str] = None):
|
|
|
return {"item_id": item_id, "q": q}
|
|
|
|
|
|
```
|
|
|
|
|
|
`Esc`to return to _normal-mode_ and type `:w`to save, and delete that buffer `:bd`
|
|
|
`Esc`to return to _normal-mode_ and type `:w`to save, and delete that buffer `:bd`
|
|
|
|
|
|
You are back in main.py, well done!! - I'll take it from here!
|
|
|
You are back in main.py, well done!! - I'll take it from here!
|
|
|
|
|
|
Proceed to Part 3. |
|
|
\ No newline at end of file |