Skip to main content

LayoutML - a library for creating HTML pages using Python

Project description

LayoutML

LayoutML (Layout Markup Library) is a library that allows you to describe the structure of web pages directly in code, turning Python into a markup language for web interfaces.

Package version Supported Python versions

Key Features

  • Create HTML elements using Python classes
  • Define CSS styles programmatically
  • Component-based approach (reusable layout blocks)
  • Clean and declarative syntax
  • Generate pure HTML/CSS without unnecessary code
  • Easy integration with FastAPI, Flask, Django
  • Lightweight with no external dependencies

Who is it for

  • Python developers who don’t want to write HTML manually
  • Backend developers (FastAPI / Django / Flask)
  • Educational projects
  • Generating HTML reports and interfaces
  • Building custom web frameworks on top of LayoutML

Contents

Core Classes

Base Elements

Semantic Elements

  • Header - Semantic <header> element
  • Main - Semantic <main> element
  • Footer - Semantic <footer> element
  • Nav - Semantic <nav> element
  • Section - Semantic <section> element
  • Article - Semantic <article> element
  • Aside - Semantic <aside> element

Text Elements

Media Elements

Form Elements

Layout

Document Structure

Routing

Application

Quick Start

Installation

pip install layoutml

Example Usage

This section provides examples of building web applications using LayoutML. You will learn how to create pages, add elements, and run the server.

Basic Run

The simplest way to run a LayoutML application:

from layoutml import LayoutML, Page
from layoutml.elements import Header, Paragraph, Button

class BasePage(Page):
    def __init__(self, doctype="html", title="LayoutML", lang="en", object_name=None, **kwargs):
        super().__init__(doctype, title, lang, object_name, **kwargs)
        self.head.set_icon("ico/logo.ico")


# Create the application
app = LayoutML()

# Define a route
@app._router.route("/")
def home():
    page = BasePage(title="Home")

    # Create elements
    header = Header()
    header.get_html(content="<h1>Welcome!</h1>")

    paragraph = Paragraph(text="This is an example of using LayoutML")

    button = Button(text="Click me", onclick="alert('Hello!')")

    # Add elements to the page
    page.body.add_element(header)
    page.body.add_element(paragraph)
    page.body.add_element(button)

    return page

# Run the application
if __name__ == "__main__":
    app.start(host="localhost", port=3700)

Running via Uvicorn from the Command Line

You can run the application using Uvicorn from the terminal:

uvicorn test:app --host localhost --port 3700 --reload

Where test is the name of your Python file, and app is the name of your LayoutML application instance.

Running via Uvicorn from Python Code

You can also run Uvicorn directly from a Python script:

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

Creating Multiple Routes

Example of an application with multiple pages:

from layoutml import LayoutML, Page
from layoutml.elements import Header, Paragraph, Button, Anchor

app = LayoutML()

@app.route("/")
def home():
    page = Page(title="Home")

    header = Header()
    header.get_html(content="<h1>Home Page</h1>")

    paragraph = Paragraph(text="Welcome to our website!")

    link = Anchor(href="/about", text="About Us")

    page.body.add_element(header)
    page.body.add_element(paragraph)
    page.body.add_element(link)

    return page

@app.route("/about")
def about():
    page = Page(title="About")

    header = Header()
    header.get_html(content="<h1>About Our Company</h1>")

    paragraph = Paragraph(text="We build web applications using LayoutML")

    back_link = Anchor(href="/", text="Back to Home")

    page.body.add_element(header)
    page.body.add_element(paragraph)
    page.body.add_element(back_link)

    return page

if __name__ == "__main__":
    app.start()

Using Route Parameters

You can create dynamic pages with parameters in the URL:

from layoutml import LayoutML, Page
from layoutml.elements import Header, Paragraph

app = LayoutML()

@app._router.route("/user/<username>")
def user_profile(username: str):
    page = Page(title=f"Profile {username}")

    header = Header()
    header.get_html(content=f"<h1>User Profile: {username}</h1>")

    paragraph = Paragraph(text=f"Welcome, {username}!")

    page.body.add_element(header)
    page.body.add_element(paragraph)

    return page

if __name__ == "__main__":
    app.start()

Adding CSS Styles

Example of a page with custom styles:

from layoutml import LayoutML, Page
from layoutml.elements import Header, Paragraph, Button

app = LayoutML()

@app.route("/")
def styled_page():
    page = Page(title="Styled Page")

    # Create an element with CSS classes
    header = Header(class_="main-header")
    header.get_html(content="<h1>Styled Page</h1>")

    paragraph = Paragraph(
        text="This text is styled using CSS",
        class_="highlight-text"
    )

    button = Button(
        text="Styled Button",
        class_="custom-button",
        style="padding: 10px 20px; background: #007bff; color: white; border: none; border-radius: 5px;"
    )

    # Add CSS styles via the head object
    page.head.selectors_styles.add_selector(".main-header")\
        .set_background_color("#f8f9fa")\
        .set_padding("20px")\
        .set_text_align("center")

    page.head.selectors_styles.add_selector(".highlight-text")\
        .set_color("#007bff")\
        .set_font_size("18px")\
        .set_font_weight("bold")

    page.head.selectors_styles.add_selector(".custom-button:hover")\
        .set_background_color("#0056b3")\
        .set_transform("scale(1.05)")

    page.body.add_element(header)
    page.body.add_element(paragraph)
    page.body.add_element(button)

    return page

if __name__ == "__main__":
    app.start()

Using Layouts

Creating a page using horizontal and vertical layouts:

from layoutml import LayoutML, Page
from layoutml.elements import Header, Paragraph, Button
from layoutml.layout import HorizontalLayout, VerticalLayout

app = LayoutML()

@app.route("/")
def layout_example():
    page = Page(title="Layout Example")

    # Vertical layout for the entire page
    main_layout = VerticalLayout(object_name="mainLayout")
    main_layout.object_styles.set_gap("20px").set_padding("20px")

    # Horizontal layout for navigation
    nav_layout = HorizontalLayout(object_name="navLayout")
    nav_layout.object_styles.set_justify_content("space-between")

    nav_layout.add_element(Button(text="Home"))
    nav_layout.add_element(Button(text="About"))
    nav_layout.add_element(Button(text="Contacts"))

    # Horizontal layout for cards
    cards_layout = HorizontalLayout(object_name="cardsLayout")
    cards_layout.object_styles.set_gap("20px").set_justify_content("center")

    for i in range(3):
        card = VerticalLayout(object_name=f"card{i}")
        card.object_styles.set_border("1px solid #ddd")\
                          .set_padding("15px")\
                          .set_border_radius("8px")\
                          .set_width("200px")

        card.add_element(Paragraph(text=f"Card {i+1}"))
        card.add_element(Button(text="Learn More"))
        cards_layout.add_element(card)

    main_layout.add_elements(nav_layout, cards_layout)
    page.body.add_element(main_layout)

    return page

if __name__ == "__main__":
    app.start()

Handling Forms

Example of creating a page with a form and handling data:

from layoutml import LayoutML, Page
from layoutml.elements import Input, Button, Label, Paragraph

app = LayoutML()

@app.route("/contact", methods=["GET", "POST"])
def contact_page():
    page = Page(title="Contacts")

    page.body.add_element(Paragraph(text="Get in touch with us"))

    # Create a form
    form = BaseElement(tag="form", method="post", action="/submit")

    # Name field
    form.add_element(Label(for_id="name", text="Name:"))
    form.add_element(Input(id="name", name="name", required=True))

    # Email field
    form.add_element(Label(for_id="email", text="Email:"))
    form.add_element(Input(type="email", id="email", name="email", required=True))

    # Submit button
    form.add_element(Button(text="Submit", type="submit"))

    page.body.add_element(form)

    return page

if __name__ == "__main__":
    app.start()

Development Tips

  1. Development mode: Use the --reload flag when running via Uvicorn for automatic server reload on code changes.

  2. Debugging: You can print route information using the print_routes() method:

app.print_routes()
  1. Code organization: For larger applications, it is recommended to split routes into modules:
# routes.py
from layoutml import LayoutML

app = LayoutML()

# Import routes from other modules
from .home_routes import home_router
from .api_routes import api_router

app.include_router(home_router)
app.include_router(api_router, prefix="/api")
  1. Asynchronous handlers: LayoutML supports async functions for route handling:
@app.route("/async-data")
async def async_data():
    data = await fetch_data_from_db()
    page = Page(title="Data")
    page.body.add_element(Paragraph(text=str(data)))
    return page

))())()()() After запуск the server will be available at http://localhost:3700

Project Status

LayoutML is under active development.

📄 License

MIT License

Feedback

I am always happy to receive your feedback and suggestions for improving LayoutML. Please leave your comments.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

layoutml-1.0.1.tar.gz (40.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

layoutml-1.0.1-py3-none-any.whl (49.6 kB view details)

Uploaded Python 3

File details

Details for the file layoutml-1.0.1.tar.gz.

File metadata

  • Download URL: layoutml-1.0.1.tar.gz
  • Upload date:
  • Size: 40.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.2

File hashes

Hashes for layoutml-1.0.1.tar.gz
Algorithm Hash digest
SHA256 ccced50173a7e5acf5be223eda0fa4474526debfe40c6688322b0d3f4aa74fe2
MD5 dad07b465bea3d3ade85f8ef141d5ced
BLAKE2b-256 44d2dd1ceb81ca392915840abf8328f1473fa3b0ec7dda08faeb8b114a9a9f60

See more details on using hashes here.

File details

Details for the file layoutml-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: layoutml-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 49.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.2

File hashes

Hashes for layoutml-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b94f0c95fad14f3725264346725c9261608d5fe2a8249b960d83205c628ef8d4
MD5 970e632cbd86f248cc7d9b0cf095e519
BLAKE2b-256 4fd17922c35e359c9c764e729f9c7763c7a3841055021a31a759b236cb8b353f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page