Creating a web application¶
Creating an application is not difficult in pyEchoNext. Thanks to its modularity and versatility, you can configure many settings and use different methods for creating web application routes.
The required module to import can be indicated in parentheses, i.e. where this abstraction is stored. ex. EchoNext (pyechonext.app): from echonext.app import EchoNext
The main one is the EchoNext class (pyechonext.app):
echonext = Echonext(app_name: str,
settings: Settings,
middlewaries: List[BaseMiddleware]
urls: Optional[List[URL]],
application_type: Optional[ApplicationType])
Settings¶
This argument is an instance of the Settings dataclass (pyechonext.config).
@dataclass
class Settings:
"""
This class describes settings.
"""
BASE_DIR: str
TEMPLATES_DIR: str
SECRET_KEY: str
VERSION: str = '1.0.0'
DESCRIPTION: str = 'Echonext webapp'
LOCALE: str = "DEFAULT"
LOCALE_DIR: str = None
Create an instance:
settings = Settings(
BASE_DIR=os.path.dirname(os.path.abspath(__file__)), TEMPLATES_DIR="templates",
SECRET_KEY='your-secret-key'
)
BASE_DIR - base directory of the application file, TEMPLATES_DIR - directory of html templates (for the built-in template engine or Jinja2).
Also, from version 0.4.3 you can use a special settings loader. At the moment, it allows you to load settings from three types of files:
env file (environment variables)
ini file
pymodule (python module)
To use it, import:
from pyechonext.config import SettingsLoader, SettingsConfigType
SettingsLoader is the loader, and SettingsConfigType is an enum class with types of config files.
SettingsLoader accepts the following arguments:
config_type: SettingsConfigType, filename: str
. To get settings you
need to call the get_settings()
method. It returns an object of the
Settings data class, which can be immediately passed to the EchoNext
application.
SettingsConfigType contains the following values:
class SettingsConfigType(Enum):
"""
This class describes a settings configuration type.
"""
THIS = 'this'
DOTENV = 'dotenv'
PYMODULE = 'pymodule'
Examples of config loading:
DOTENV¶
config_loader = SettingsLoader(SettingsConfigType.DOTENV, 'example_env')
settings = config_loader.get_settings()
example_env file:
PEN_BASE_DIR=.
PEN_TEMPLATES_DIR=templates
PEN_SECRET_KEY=secret-key
PEN_LOCALE=RU_RU
PEN_LOCALE_DIR=local
PEN_VERSION=1.0.0
PEN_DESCRIPTION=Example
THIS¶
config_loader = SettingsLoader(SettingsConfigType.INI, 'example_ini.ini')
settings = config_loader.get_settings()
File example_ini.ini:
[Settings]
BASE_DIR=.
TEMPLATES_DIR=templates
SECRET_KEY=secret-key
LOCALE=DEFAULT
VERSION=1.0.0
DESCRIPTION=Example
PyModule¶
config_loader = SettingsLoader(SettingsConfigType.PYMODULE, 'example_module.py')
settings = config_loader.get_settings()
Example_module.py file:
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
TEMPLATES_DIR = 'templates'
SECRET_KEY = 'secret-key'
VERSION = '1.0.0'
DESCRIPTION = 'Echonext webapp'
LOCALE = 'DEFAULT'
LOCALE_DIR = None
Middlewares¶
Middlewares - “middleware”. The BaseMiddleware class looks like this:
class BaseMiddleware(ABC):
"""
This abstract class describes a base middleware.
"""
@abstractmethod
def to_request(self, request: Request):
"""
To request method
:param request: The request
:type request: Request
"""
raise NotImplementedError
@abstractmethod
def to_response(self, response: Response):
"""
To response method
:param response: The response
:type response: Response
"""
raise NotImplementedError
To create your own Middleware, you need to create a new class based on this class and be sure to implement the to_request and to_response methods. pyEchoNext has a basic Middleware for creating sessions:
class SessionMiddleware(BaseMiddleware):
"""
This class describes a session (cookie) middleware.
"""
def to_request(self, request: Request):
"""
Set to request
:param request: The request
:type request: Request
"""
cookie = request.environ.get('HTTP_COOKIE', None)
if not cookie:
return
session_id = parse_qs(cookie)['session_id'][0]
request.extra['session_id'] = session_id
def to_response(self, response: Response):
"""
Set to response
:param response: The response
:type response: Response
"""
if not response.request.session_id:
response.add_headers([
("Set-Cookie", f'session_id={uuid4()}'),
])
There is also a basic list of middlewares
in pyechonext.middleware
to pass as arguments to EchoNext:
middlewares = [
SessionMiddleware
]
This way you can import it and use or add to it.
URLS¶
By default, urls
is an empty list. urls contains instances of the
URL dataclass (pyechonext.urls):
@dataclass
class URL:
path: str
controller: Type[PageController]
summary: Optional[str] = None
Controller is an abstraction of the site route (django-like). It must have two
methods: get
and post
(to respond to get and post requests).
These methods should return:
Data, page content. This can be a dictionary or a string.
OR:
Response class object (pyechonext.response)
You can combine these two methods. There are the following recommendations for their use:
If the method only returns already prepared data, then you should not return Response, return data.
If the method works with the response passed to it, then return the data or the response itself passed in the arguments.
In other cases, you can create a Response and return it, not data.
In the get and post methods, you should use only one method, you should not mix them. But if you cannot do without it, then this recommendation can be violated.
These recommendations may be violated at the request of the developer.
You can also throw WebError exceptions instead of returning a result: URLNotFound and MethodNotAllow. In this case, the application will not stop working, but will display an error on the web page side. If another exception occurs, the application will stop working.
We use MVC (Model-View-Controller) model. To understand this, read MVC Docs.
There is also a base list in pyechonext.urls to pass as arguments to EchoNext:
url_patterns = [URL(url="/", controller=MyController, summary="Page")]
application_type¶
application_type - application type. The argument takes an ApplicationType enum class:
class ApplicationType(Enum):
"""
This enum class describes an application type.
"""
JSON = "application/json"
HTML = "text/html"
PLAINTEXT = "text/plain"
Currently supported: ApplicationType.JSON, ApplicationType.HTML, ApplicationType.PLAINTEXT.
Defaults to ApplicationType.JSON.