📝 first push of docs
This commit is contained in:
parent
3ab9e05442
commit
42552e2dbc
44
docs/README.md
Normal file
44
docs/README.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# spiderweb
|
||||||
|
|
||||||
|
As a professional web developer focusing on arcane uses of Django for arcane purposes, it occurred to me a little while ago that I didn't actually know how a web framework _worked_.
|
||||||
|
|
||||||
|
> So I built one.
|
||||||
|
|
||||||
|
This is `spiderweb`, a web framework that's just big enough to hold a spider. When building it, my goals were simple:
|
||||||
|
|
||||||
|
- Learn a lot
|
||||||
|
- Create an unholy blend of Django and Flask
|
||||||
|
- Not look at any existing code. Go off of vibes alone and try to solve all the problems I could think of in my own way
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> This is a learning project. It should not be used for production without heavy auditing. It's not secure. It's not fast. It's not well-tested. It's not well-documented. It's not well-anything. It's a learning project.
|
||||||
|
>
|
||||||
|
> That being said, it's fun and it works, so I'm counting that as a win.
|
||||||
|
|
||||||
|
|
||||||
|
Here's a non-exhaustive list of things this can do:
|
||||||
|
|
||||||
|
* Function-based views
|
||||||
|
* Optional Flask-style URL routing
|
||||||
|
* Optional Django-style URL routing
|
||||||
|
* URLs with variables in them a lá Django
|
||||||
|
* Full middleware implementation
|
||||||
|
* Limit routes by HTTP verbs
|
||||||
|
* (Only GET and POST are implemented right now)
|
||||||
|
* Custom error routes
|
||||||
|
* Built-in dev server
|
||||||
|
* Gunicorn support
|
||||||
|
* HTML templates with Jinja2
|
||||||
|
* Static files support
|
||||||
|
* Cookies (reading and setting)
|
||||||
|
* Optional append_slash (with automatic redirects!)
|
||||||
|
* ~~CSRF middleware implementation~~ (it's there, but it's crappy and unsafe. This might be beyond my skillset.)
|
||||||
|
* Optional POST data validation middleware with Pydantic
|
||||||
|
* Database support (using Peewee, but the end user can use whatever they want as long as there's a Peewee driver for it)
|
||||||
|
* Session middleware with built-in session store
|
||||||
|
* Tests (currently a little over 80% coverage)
|
||||||
|
|
||||||
|
The TODO list:
|
||||||
|
|
||||||
|
* Fix CSRF middleware
|
||||||
|
* Add more HTTP verbs
|
1
docs/_media/DMSans-Bold.ttf
Normal file
1
docs/_media/DMSans-Bold.ttf
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://www.hubspot.com/hubfs/brand-kit-generator/prototype/fonts/DMSans-Bold.ttf
|
BIN
docs/_media/DMSans-Medium.ttf
Normal file
BIN
docs/_media/DMSans-Medium.ttf
Normal file
Binary file not shown.
BIN
docs/_media/Favicon-32x32.png
Normal file
BIN
docs/_media/Favicon-32x32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
docs/_media/favicon.png
Normal file
BIN
docs/_media/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
docs/_media/spiderweb_logo.png
Normal file
BIN
docs/_media/spiderweb_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
6
docs/_sidebar.md
Normal file
6
docs/_sidebar.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
- [home](README.md)
|
||||||
|
- [quickstart](quickstart.md)
|
||||||
|
- [responses](responses.md)
|
||||||
|
- Middleware
|
||||||
|
- [middleware](middleware/test.md)
|
||||||
|
- [middleware2](middleware/test2.md)
|
12
docs/example.md
Normal file
12
docs/example.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
> [!ATTENTION]
|
||||||
|
> An alert of type 'attention' using global style 'callout'.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> An alert of type 'tip' using global style 'callout'.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> An alert of type 'warning' using global style 'callout'.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> An alert of type 'note' using global style 'callout'.
|
44
docs/index.html
Normal file
44
docs/index.html
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Document</title>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||||
|
<meta name="description" content="Description">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/_media/Favicon-32x32.png">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
|
||||||
|
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: "DMSans";
|
||||||
|
src: url('_media/DMSans-Medium.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: "DMSans", sans-serif;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script>
|
||||||
|
window.$docsify = {
|
||||||
|
name: 'Spiderweb',
|
||||||
|
loadSidebar: true,
|
||||||
|
repo: 'https://github.com/itsthejoker/spiderweb',
|
||||||
|
maxLevel: 3,
|
||||||
|
coverpage: true,
|
||||||
|
'flexible-alerts': {
|
||||||
|
style: 'callout' // or 'flat'
|
||||||
|
},
|
||||||
|
auto2top: true,
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<!-- Docsify v4 -->
|
||||||
|
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
|
||||||
|
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-python.min.js"></script>
|
||||||
|
<!-- admonitions -->
|
||||||
|
<script src="https://unpkg.com/docsify-plugin-flexible-alerts"></script>
|
||||||
|
<script src="//unpkg.com/docsify-pagination/dist/docsify-pagination.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/docsify-tabs@1"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
1
docs/middleware/test.md
Normal file
1
docs/middleware/test.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
asdf
|
1
docs/middleware/test2.md
Normal file
1
docs/middleware/test2.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
asdfawaasdf
|
93
docs/quickstart.md
Normal file
93
docs/quickstart.md
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# quickstart
|
||||||
|
|
||||||
|
Start by installing the package with your favorite package manager:
|
||||||
|
|
||||||
|
<!-- tabs:start -->
|
||||||
|
|
||||||
|
<!-- tab:poetry -->
|
||||||
|
|
||||||
|
```shell
|
||||||
|
poetry add spiderweb-framework
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- tab:pip -->
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pip install spiderweb-framework
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- tab:pipenv -->
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pipenv install spiderweb-framework
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- tabs:end -->
|
||||||
|
|
||||||
|
Then, create a new file and drop this in it:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from spiderweb import SpiderwebRouter
|
||||||
|
from spiderweb.response import HttpResponse
|
||||||
|
|
||||||
|
app = SpiderwebRouter()
|
||||||
|
|
||||||
|
@app.route("/")
|
||||||
|
def index(request):
|
||||||
|
return HttpResponse("HELLO, WORLD!")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.start()
|
||||||
|
```
|
||||||
|
|
||||||
|
Start the dev server by running `python {yourfile.py}` and navigating to `http://localhost:8000/` in your browser. You should see `HELLO, WORLD!` displayed on the page. Press `Ctrl+C` to stop the server.
|
||||||
|
|
||||||
|
That's it! You've got a working web app. Let's take a look at what these few lines of code are doing:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from spiderweb import SpiderwebRouter
|
||||||
|
```
|
||||||
|
|
||||||
|
The `SpiderwebRouter` class is the main object that everything stems from in `spiderweb`. It's where you'll set your options, your routes, and more.
|
||||||
|
|
||||||
|
```python
|
||||||
|
from spiderweb.response import HttpResponse
|
||||||
|
```
|
||||||
|
|
||||||
|
Rather than trying to infer what you want, spiderweb wants you to be specific about what you want it to do. Part of that is the One Response Rule:
|
||||||
|
|
||||||
|
> Every view must return a Response, and each Response must be a specific type.
|
||||||
|
|
||||||
|
There are four different types of responses; if you want to skip ahead, hop over to [the responses page](responses.md) to learn more. For this example, we'll focus on `HttpResponse`, which is the base response.
|
||||||
|
|
||||||
|
```python
|
||||||
|
app = SpiderwebRouter()
|
||||||
|
```
|
||||||
|
|
||||||
|
This line creates a new instance of the `SpiderwebRouter` class and assigns it to the variable `app`. This is the object that will handle all of your requests and responses. If you need to pass any options into spiderweb, you'll do that here.
|
||||||
|
|
||||||
|
```python
|
||||||
|
@app.route("/")
|
||||||
|
def index(request):
|
||||||
|
return HttpResponse("HELLO, WORLD!")
|
||||||
|
```
|
||||||
|
|
||||||
|
This is an example view. There are a few things to note here:
|
||||||
|
|
||||||
|
- The `@app.route("/")` decorator tells spiderweb that this view should be called when the user navigates to the root of the site.
|
||||||
|
- The `def index(request):` function is the view itself. It takes a single argument, `request`, which is a `Request` object that contains all the information about the incoming request.
|
||||||
|
- The `return HttpResponse("HELLO, WORLD!")` line is the response. In this case, it's a simple `HttpResponse` object that contains the string `HELLO, WORLD!`. This will be sent back to the user's browser.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> Every view must accept a `request` object as its first argument. This object contains all the information about the incoming request, including headers, cookies, and more.
|
||||||
|
>
|
||||||
|
> There's more that we can pass in, but for now, we'll keep it simple.
|
||||||
|
|
||||||
|
```python
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.start()
|
||||||
|
```
|
||||||
|
|
||||||
|
Once you finish setting up your app, it's time to start it! You can start the dev server by just calling `app.start()` (and its counterpart `app.stop()` to stop it). This will start a simple server on `localhost:8000` that you can access in your browser. It's not a secure server; don't even think about using it in production. It's just good enough for development.
|
||||||
|
|
||||||
|
Now that your app is done, you can also run it with Gunicorn by running `gunicorn --workers=2 {yourfile}:app` in your terminal. This will start a Gunicorn server on `localhost:8000` that you can access in your browser and is a little more robust than the dev server.
|
3
docs/responses.md
Normal file
3
docs/responses.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# responses
|
||||||
|
|
||||||
|
...
|
40
test.py
Normal file
40
test.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
from peewee import *
|
||||||
|
from playhouse.migrate import SqliteMigrator, migrate
|
||||||
|
|
||||||
|
from spiderweb.db import SpiderwebModel
|
||||||
|
|
||||||
|
db = SqliteDatabase("people.db")
|
||||||
|
migrator = SqliteMigrator(db)
|
||||||
|
|
||||||
|
|
||||||
|
class Person(SpiderwebModel):
|
||||||
|
name = CharField()
|
||||||
|
birthday = DateField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
database = db # This model uses the "people.db" database.
|
||||||
|
|
||||||
|
|
||||||
|
class Pet(SpiderwebModel):
|
||||||
|
owner = ForeignKeyField(Person, backref="pets")
|
||||||
|
name = CharField(max_length=40)
|
||||||
|
animal_type = CharField()
|
||||||
|
age = IntegerField(null=True)
|
||||||
|
favorite_color = CharField(null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
database = db # this model uses the "people.db" database
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
db.connect()
|
||||||
|
Pet.check_for_needed_migration()
|
||||||
|
# try:
|
||||||
|
# Pet.check_for_needed_migration()
|
||||||
|
# except:
|
||||||
|
# migrate(
|
||||||
|
# migrator.add_column(
|
||||||
|
# Pet._meta.table_name, 'favorite_color', CharField(null=True)
|
||||||
|
# ),
|
||||||
|
# )
|
||||||
|
db.create_tables([Person, Pet])
|
Loading…
Reference in New Issue
Block a user