Commit 5f41bf8b authored by Давид Ли's avatar Давид Ли

completed 39 lesson

parent 38ccb863
......@@ -4,5 +4,6 @@
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.11 (http_framework)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="bootstrap" level="application" />
</component>
</module>
\ No newline at end of file
from request import Request
from response import Response
from src.request import Request
from src.response import Response
class BaseController:
......
from .base import BaseController
from controllers.base import BaseController
class PagesController(BaseController):
......
import utils
from controllers.base import BaseController
def id_generator():
count = 0
while True:
count += 1
yield count
id_gen = id_generator()
from db.database import Database
from template_engine.jinja import env
from utils import id_gen
class PostsController(BaseController):
posts_db = [
{'id': next(id_gen), 'title': 'This is 1 post'},
{'id': next(id_gen), 'title': 'This is 2 post'},
{'id': next(id_gen), 'title': 'This is 3 post'},
]
def get_list(self):
body = (
'<h1>This is posts page</h1>'
'<br><form action="/posts" method="POST">'
'<label>'
'<input type="text" name="title">'
'</label>'
'<input type="submit">'
'</form><br>'
)
tmp = env.get_template('posts/list.html')
body = tmp.render(posts=Database.all())
self.response.add_header('Content-Type', 'text/html')
self.response.set_body(body)
for post in self.posts_db:
body += f'<h3>{post["id"]} - {post["title"]}'
def new(self):
tmp = env.get_template('posts/create.html')
body = tmp.render(id=next(utils.id_gen))
self.response.add_header('Content-Type', 'text/html')
self.response.set_body(body)
def create(self):
id_ = next(id_gen)
self.posts_db.append(
Database.add(
{
'id': id_,
'title': f'This is {id_} post'
'title': self.request.body['title']
}
)
self.response.add_header('Content-Type', 'text/html')
self.response.set_status(301)
self.response.add_header('Location', '/posts')
self.response.set_body('<a href="/posts"">Back to posts list</a>')
from utils import id_gen
class Database:
posts = [
{'id': next(id_gen), 'title': 'This is 1 post'},
{'id': next(id_gen), 'title': 'This is 2 post'},
{'id': next(id_gen), 'title': 'This is 3 post'},
]
@classmethod
def all(cls):
return cls.posts
@classmethod
def add(cls, post: dict[str]):
cls.posts.append(post)
from controllers.pages import PagesController
from controllers.posts import PostsController
from src.router import Router
from src.server import runserver
config = {
'host': 'localhost',
'port': 1025,
'static': 'static'
}
router = Router()
router.get('/', PagesController, 'home')
router.get('/about-us', PagesController, 'about_us')
router.get('/posts', PostsController, 'get_list')
router.post('/posts', PostsController, 'create')
router.get('/posts/new', PostsController, 'new')
runserver(router, config)
Jinja2==3.1.2
MarkupSafe==2.1.2
import socketserver
from controllers.pages import PagesController
from controllers.posts import PostsController
from request import Request
from response import Response
from router import Router
from static_responder import StaticResponder
import errors
HOST, PORT = '127.0.0.1', 1025
# CRUDL - Create, Read, Update, Delete, List
# /posts
# GET - /posts
# GET - /posts/{id}
# POST - /posts
# PUT/PATCH - /posts/{id}
# DELETE - /posts/{id}
router = Router()
router.get('/', PagesController, 'home')
router.get('/about-us', PagesController, 'about_us')
router.get('/posts', PostsController, 'get_list')
router.post('/posts', PostsController, 'create')
class MyTCPHandler(socketserver.StreamRequestHandler):
def handle(self) -> None:
request = Request(file=self.rfile)
response = Response(file=self.wfile)
static_responder = StaticResponder(request, response, 'static')
router.run(request, response)
print(
f'Method: {request.method}\n'
f'URI: {request.uri}\n'
f'Protocol: {request.protocol}\n'
)
response.send()
socketserver.TCPServer.allow_reuse_address = True
with socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler) as server:
server.serve_forever()
from request import Request
from response import Response
from src.request import Request
from src.response import Response
def not_found(request: Request, response: Response):
......
......@@ -45,4 +45,4 @@ class Request:
self.body = parsed
else:
self.body = self.file.read(content_length)
self.body = body
......@@ -8,12 +8,14 @@ class Response:
HTTP_BAD_REQUEST = 400
HTTP_NOT_FOUND = 404
HTTP_INTERNAL_SERVER_ERROR = 500
HTTP_MOVED_PERMANENTLY = 301
MESSAGES = {
HTTP_OK: 'OK',
HTTP_BAD_REQUEST: 'Bad Request',
HTTP_NOT_FOUND: 'Not Found',
HTTP_INTERNAL_SERVER_ERROR: 'Internal Server Error'
HTTP_INTERNAL_SERVER_ERROR: 'Internal Server Error',
HTTP_MOVED_PERMANENTLY: 'Moved Permanently'
}
PROTOCOL = 'HTTP/1.1'
......@@ -30,7 +32,7 @@ class Response:
def set_body(self, body: str) -> None:
self.body = body.encode()
self.add_header('Content-Type', str(len(self.body)))
self.add_header('Content-Length', str(len(self.body)))
def set_file_body(self, file: BinaryIO) -> None:
self.file_body = file
......@@ -41,7 +43,11 @@ class Response:
self.__headers.append({name: value})
def __get_status_line(self) -> str:
if self.__status in self.MESSAGES:
message = self.MESSAGES[self.__status]
else:
message = ''
return f'{self.PROTOCOL} {self.__status} {message}'
def __get_response_head(self) -> bytes:
......
import errors
from src import errors
from controllers.base import BaseController
from request import Request
from response import Response
from src.request import Request
from src.response import Response
class Router:
......
import socketserver
from src.request import Request
from src.response import Response
from src.router import Router
from src.static_responder import StaticResponder
def runserver(router: Router, config: dict[str]) -> None:
class MyTCPHandler(socketserver.StreamRequestHandler):
def handle(self) -> None:
request = Request(file=self.rfile)
response = Response(file=self.wfile)
static_responder = StaticResponder(request, response, config['static'])
if static_responder.file:
static_responder.prepare_response()
else:
router.run(request, response)
print(
f'Method: {request.method}\n'
f'URI: {request.uri}\n'
f'Protocol: {request.protocol}\n'
)
response.send()
socketserver.TCPServer.allow_reuse_address = True
with socketserver.ThreadingTCPServer((config['host'], config['port']), MyTCPHandler) as server:
server.serve_forever()
......@@ -2,8 +2,8 @@ from glob import glob
import os
from request import Request
from response import Response
from src.request import Request
from src.response import Response
class StaticResponder:
......
......@@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="../static/styles.css">
<link rel="stylesheet" href="../../static/styles.css">
<title>Title</title>
</head>
<body>
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.1/css/bootstrap.min.css"
integrity="sha512-Ez0cGzNzHR1tYAv56860NLspgUGuQw16GiOOp/I2LuTmpSK9xDXlgJz3XN4cnpXWDmkNBKXR/VDMTCnAaEooxA=="
crossorigin="anonymous" referrerpolicy="no-referrer"/>
<link rel="stylesheet" href="styles.css">
<title>Title</title>
</head>
<body>
<div class="container container-2">
{% block content %}
{% endblock %}
</div>
</body>
</html>
\ No newline at end of file
{% extends 'posts/base.html' %}
{% block content %}
<form action="/posts" method="post">
<div class="mb-3 row">
<label for="staticEmail" class="col-sm-2 col-form-label">Id</label>
<div class="col-sm-10">
<input type="text" readonly class="form-control-plaintext" id="staticEmail" value="{{ id }}">
</div>
</div>
<div class="mb-3 row">
<label for="inputPassword" class="col-sm-2 col-form-label">Title</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="inputPassword" name="title">
</div>
</div>
<button class="btn btn-success">Submit</button>
</form>
{% endblock %}
\ No newline at end of file
{% extends 'posts/base.html' %}
{% block content %}
<h1>This is the posts page</h1>
<div class="row">
{% for post in posts %}
<div class="col-4">
<div class="card">
<div class="card-header">
{{ post.id }}
</div>
<div class="card-body">
<h5 class="card-title">{{ post.title }}</h5>
<p class="card-text">With supporting text below as a natural lead-in to additional content.</p>
<a href="#" class="btn btn-primary">Go somewhere</a>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
\ No newline at end of file
......@@ -6,7 +6,6 @@ h1 {
color: red
}
.container {
margin: 0 auto;
width: 80%;
.container-2 {
background-color: red;
}
from jinja2 import Environment, PackageLoader, select_autoescape
env = Environment(
loader=PackageLoader('src'),
autoescape=select_autoescape()
)
def id_generator():
count = 0
while True:
count += 1
yield count
id_gen = id_generator()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment