Compare commits

...

26 commits

Author SHA1 Message Date
0049419578
better image on about servala
All checks were successful
Build and Deploy / build (push) Successful in 1m6s
Build and Deploy / deploy (push) Successful in 6s
2025-05-06 16:09:26 +02:00
44263ffca5
upgrade django 2025-05-06 16:06:40 +02:00
c1f776e7eb
update docs 2025-05-06 16:05:35 +02:00
8b594846ad
include proxied plausible script 2025-04-09 15:42:33 +02:00
9d16fc0da9
reverse proxy plausible script 2025-04-09 15:37:48 +02:00
f5677414e6
only load contact_tags once 2025-04-07 16:36:33 +02:00
12fdf7ed87
only show plans when available 2025-04-07 16:33:49 +02:00
63ac43a045
use h1 on all pages instead of h2 for SEO reasons 2025-03-28 15:46:43 +01:00
e6adfe7499
fix missing img alt 2025-03-28 15:32:46 +01:00
4fdc2e0115
output correct javascript tag 2025-03-28 11:17:47 +01:00
b35ce84792
fix 404 handling in json ld 2025-03-28 11:14:24 +01:00
4f1bbdd147
resize sir vala mascot image size 2025-03-28 11:02:33 +01:00
05742d9f1c
configure reverse proxy header for proper TLS 2025-03-28 10:50:07 +01:00
ddd1cd70ad
plausible event for newsletter signup 2025-03-28 10:33:20 +01:00
388b596f3f
include organization data on homepage 2025-03-27 16:00:26 +01:00
d69b540fcc
basic implementation of json-ld 2025-03-27 15:49:59 +01:00
3e1b6d95b6
fix url in robots.txt 2025-03-27 15:02:25 +01:00
1fed0f63d0
support favicon.ico on root 2025-03-27 14:54:47 +01:00
92a8b0951e
add newsletter subscription functionality 2025-03-27 10:33:27 +01:00
0dd73bedde
fix card logo size on homepage 2025-03-26 14:00:40 +01:00
9988c9fcbd
improved alt and title for sir vala - seo 2025-03-26 10:03:30 +01:00
6fda0a4b7a
revised flyer 2025-03-24 15:22:36 +01:00
1ad5c0c38c
improve the cta offering buttons on the service detail page 2025-03-20 16:28:38 +01:00
478ac76210
fix see all button in mobile view 2025-03-18 09:34:37 +01:00
1cfd5a57d7
add links to products vshn to about page 2025-03-17 12:11:44 +01:00
39236b45eb
offerings with plans first on list 2025-03-17 09:32:46 +01:00
38 changed files with 395 additions and 166 deletions

16
.env.example Normal file
View file

@ -0,0 +1,16 @@
DEBUG=True
ODOO_URL=https://test.central.vshn.ch
ODOO_DB=VSHNTest
ODOO_USERNAME=CHANGEME
ODOO_PASSWORD=CHANGEME
BROKER_USERNAME=broker
BROKER_PASSWORD=CHANGEME
ALLOWED_HOSTS=localhost,127.0.0.1
SECRET_KEY="django-insecure-CHANGEME"
ODOO_LEAD_CAMPAIGN_ID=6
ODOO_LEAD_SOURCE_ID=28
ODOO_LEAD_MEDIUM_ID=1
ODOO_LEAD_TAG_ID=6
ODOO_MAILING_LIST_ID=14
EMAIL_HOST_USER=CHANGEME
EMAIL_HOST_PASSWORD=CHANGEME

View file

@ -42,7 +42,7 @@ jobs:
container: catthehacker/ubuntu:act-latest
environment:
name: prod
url: https://serva.la/
url: https://servala.com/
steps:
- name: Checkout repository

View file

@ -35,6 +35,6 @@ deploy:
- oc -n ${NAMESPACE} rollout restart deployment/servala
environment:
name: prod
url: https://poc.serva.la/
url: https://servala.com/
only:
- main

View file

@ -1,8 +1,12 @@
# Servala Frontend
# Servala Website
This is a PoC for a Servala Frontend with the aim to collect leads and measure market interest.
This is the Django source-code of the website powering https://servala.com.
* List services
* Show CSPs
* Collect leads with a form
* Expose some OSB API mocks to collect leads
## Running locally
```
cp .env.example .env
source .env
uv run --extra dev manage.py migrate
uv run --extra dev manage.py runserver
```

View file

@ -42,7 +42,18 @@
# Proxy all other requests to Gunicorn
handle {
reverse_proxy unix//app/run/gunicorn.sock
reverse_proxy unix//app/run/gunicorn.sock {
header_up X-Forwarded-Proto https
header_up X-Forwarded-Host {host}
}
}
@plausible path /js/script.js /api/event
handle @plausible {
rewrite /js/script.js /js/script.file-downloads.hash.outbound-links.tagged-events.js
reverse_proxy https://plausible.io {
header_up Host {http.reverse_proxy.upstream.hostport}
}
}
# Basic compression for better performance

View file

@ -97,3 +97,70 @@ class OdooAPI:
logger.error(f"Unexpected error creating lead: {str(e)}")
logger.debug("Full error details:", exc_info=True)
raise
def add_to_mailing_list(self, email, mailing_list_id=46):
"""Add an email to a mailing list in Odoo"""
try:
logger.info(
f"Attempting to add {email} to mailing list ID {mailing_list_id}"
)
# Ensure we have a valid connection
if not self.odoo:
logger.warning("No active Odoo connection, attempting to reconnect")
self._connect()
# Add contact to mailing list
MailingContact = self.odoo.env["mailing.contact"]
existing_mailing_contacts = MailingContact.search([("email", "=", email)])
if existing_mailing_contacts:
mailing_contact_id = existing_mailing_contacts[0]
# Check if already in this list
MailingContactList = self.odoo.env["mailing.contact.subscription"]
existing_subscriptions = MailingContactList.search(
[
("contact_id", "=", mailing_contact_id),
("list_id", "=", mailing_list_id),
]
)
if not existing_subscriptions:
# Add to this specific list
MailingContactList.create(
{
"contact_id": mailing_contact_id,
"list_id": mailing_list_id,
"opt_out": False,
}
)
else:
# Create new mailing contact and subscription
mailing_contact_id = MailingContact.create(
{
"name": email.split("@")[0],
"email": email,
}
)
MailingContactList = self.odoo.env["mailing.contact.subscription"]
MailingContactList.create(
{
"contact_id": mailing_contact_id,
"list_id": mailing_list_id,
"opt_out": False,
}
)
logger.info(f"Successfully added {email} to mailing list")
return True
except odoorpc.error.RPCError as e:
logger.error(f"RPC Error adding to mailing list: {str(e)}")
logger.debug("Full RPC error details:", exc_info=True)
return False
except Exception as e:
logger.error(f"Unexpected error adding to mailing list: {str(e)}")
logger.debug("Full error details:", exc_info=True)
return False

View file

@ -12083,7 +12083,6 @@ a.btn:focus {
}
.card__image__wide {
width: 150px;
height: 80px;
margin-bottom: 16px
}
@ -12109,6 +12108,15 @@ a.btn:focus {
margin-bottom: 0
}
.card-logo {
max-height: 80px;
max-width: 100%;
width: auto;
object-fit: contain;
display: block;
margin: 0 auto;
}
@media (min-width: 992px) {
.section-hero__header {
width: 56%

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 114 KiB

Before After
Before After

1
hub/services/static/js/htmx204.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,7 @@
{% load static %}
{% load canonical_tags %}
{% load social_meta_tags %}
{% load json_ld_tags %}
<!DOCTYPE html>
<html lang="en">
<head>
@ -12,12 +13,14 @@
<link rel="icon" type="image/x-icon" href="{% static "img/favicon.ico" %}">
<link rel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">
{% social_meta_tags %}
{% json_ld_structured_data %}
<link rel="stylesheet" href='{% static "css/bootstrap-icons.min.css" %}'>
<link rel="stylesheet" type="text/css" href='{% static "css/servala-main.css" %}'>
{% block extra_css %}{% endblock %}
<script defer data-domain="servala.com" src="https://plausible.io/js/script.file-downloads.hash.outbound-links.tagged-events.js"></script>
<script defer data-api="/api/event" data-domain="servala.com" src="/js/script.js"></script>
<script defer src="{% static "js/htmx204.min.js" %}"></script>
<script defer src="{% static "js/alpine-collapse.min.js" %}"></script>
<script defer src="{% static "js/servala-main.js" %}"></script>
{% block extra_js %}{% endblock %}
@ -100,11 +103,18 @@
<h2 class="section-h1 fs-40 fs-lg-60 d-inline-block mb-24">Ready to Get Started?</h2>
</div>
<div class="text-gray-300 w-lg-37 mx-auto mb-24">
<p class="mb-0">Explore all available Services on Servala, with new ones added regularly.</p>
<p class="mb-0">Subscribe to our newsletter to stay informed.</p>
</div>
<div>
<a class="btn btn-primary btn-lg mr-md-17 mb-17 mb-md-0 w-100 w-md-auto" href="{% url 'services:homepage' %}" role="button">Discover
Services</a>
<div class="mt-4">
<form hx-post="{% url 'services:subscribe' %}" hx-target="#signup-form-container" hx-swap="outerHTML">
{% csrf_token %}
<div id="signup-form-container" class="d-flex justify-content-center">
<div class="input-group" style="max-width: 500px;">
<input type="email" name="email" class="form-control" id="email-input" placeholder="Your email address" required>
<button type="submit" class="btn btn-primary plausible-event-name=Newsletter+Sign-Up">Subscribe to updates</button>
</div>
</div>
</form>
</div>
</header>
</div>

View file

@ -8,7 +8,7 @@
<section class="section bg-primary-subtle">
<div class="container mx-auto px-20 px-lg-0 pt-40 pb-60">
<header class="section-primary__header text-center">
<h2 class="section-h1 fs-40 fs-lg-64 mb-24">About Servala</h2>
<h1 class="section-h1 fs-40 fs-lg-64 mb-24">About Servala</h1>
<div class="text-gray-300 w-lg-37 mx-auto">
<p class="mb-0">Open Cloud Native Service Hub. Unlock the Power of Cloud Native Applications.</p>
</div>
@ -33,12 +33,12 @@
</div>
<div class="page-action">
<a class="btn btn-primary btn-lg mr-md-17 mb-17 mb-md-0px mb-lg-17 mb-xl-0 w-100 w-md-auto" href="{% static "servala-flyer.pdf" %}" role="button">Download Flyer</a>
<a class="btn btn-outline btn-lg w-100 w-md-auto" href="{% url 'services:service_list' %}" role="button">Discover Services</a>
<a class="btn btn-outline btn-lg w-100 w-md-auto" href="https://products.vshn.ch/servala/index.html" target="_blank" role="button">Learn More</a>
</div>
</div>
<div class="w-lg-30">
<div class="page-header__image-wrapper">
<img class="page-header__image" src="{% static "img/about-image.png" %}" alt="About Servala">
<img class="page-header__image" src="{% static "img/servala-people.png" %}" alt="About Servala">
</div>
</div>
</div>
@ -47,31 +47,43 @@
<h2 class="fs-32 fw-semibold mt-3">Who benefits from using Servala?</h2>
<div class="text-gray-500 fs-19 lh-1-7">
<p>Servala is designed for Software Vendors, Cloud Providers and Enterprises and their users, enabling them to offer, integrate, and consume cloud-native services and applications and DevOps tools with ease.</p>
<p>For <strong>Software Vendors</strong>, Servala provides a powerful channel to distribute, monetize, and operate their software as managed services. <strong>Cloud Providers</strong> can extend their core infrastructure offerings with value-added services. <strong>Enterprise Private Clouds</strong> gain seamless access to trusted services and applications while maintaining full control over security and compliance - all within an open and agnostic ecosystem.</p>
<p>For <a href="https://products.vshn.ch/servala/isv.html" target="_blank"><strong>Software Vendors</strong></a>, Servala provides a powerful channel to distribute, monetize, and operate their software as managed services.
<a href="https://products.vshn.ch/servala/csp.html" target="_blank"><strong>Cloud Providers</strong></a> can extend their core infrastructure offerings with value-added services.
<a href="https://products.vshn.ch/servala/enterprise.html" target="_blank"><strong>Enterprise Private Clouds</strong></a> gain seamless access to trusted services and applications while maintaining full control over security and compliance - all within an open and agnostic ecosystem.
</p>
</div>
<article class="pt-20">
<article class="pt-5">
<h3 class="fs-24 fw-semibold">Software Vendors</h3>
<ul class="list-disc pl-8 text-gray-500 fs-19">
<li>Transform software into SaaS offerings.</li>
<li>Reach new markets and ecosystems through our existing partner network.</li>
<li>Streamline operations and monetization.</li>
</ul>
<div class="page-action">
<a class="btn btn-primary mr-md-17 mb-17 mb-md-0px mb-lg-17 mb-xl-17 w-100 w-md-auto" href="https://products.vshn.ch/servala/isv.html" target="_blank" role="button">Learn More</a>
</div>
</article>
<article class="pt-20">
<article class="pt-5">
<h3 class="fs-24 fw-semibold">Cloud Providers</h3>
<ul class="list-disc pl-8 text-gray-500 fs-19">
<li>Offer value-added services and applications to customers.</li>
<li>Enhance operational efficiency and market reach.</li>
<li>Keep pace with fast-changing industry demands.</li>
</ul>
<div class="page-action">
<a class="btn btn-primary mr-md-17 mb-17 mb-md-0px mb-lg-17 mb-xl-17 w-100 w-md-auto" href="https://products.vshn.ch/servala/csp.html" target="_blank" role="button">Learn More</a>
</div>
</article>
<article class="pt-20">
<article class="pt-5">
<h3 class="fs-24 fw-semibold">Enterprise Private Clouds</h3>
<ul class="list-disc pl-8 text-gray-500 fs-19">
<li>Access scalable, secure, and cost-efficient services.</li>
<li>Enable self-service installation of trusted applications without managing infrastructure.</li>
<li>Ensure compliance, boost developer productivity, and simplify operations.</li>
</ul>
<div class="page-action">
<a class="btn btn-primary mr-md-17 mb-17 mb-md-0px mb-lg-17 mb-xl-17 w-100 w-md-auto" href="https://products.vshn.ch/servala/enterprise.html" target="_blank" role="button">Learn More</a>
</div>
</article>
</div>
@ -197,7 +209,7 @@
</div>
<div class="w-lg-30">
<div class="page-header__image-wrapper">
<img class="page-header__image" src="{% static "img/sir-vala-text.png" %}" alt="Servala Mascot Sir Vala">
<img class="page-header__image" src="{% static "img/sir-vala-text.png" %}" alt="Cartoon serval cat named Sir Vala with blue eyes and a happy expression. It's the mascot of Servala - Open Cloud Native Service Hub" title="Sir Vala - Mascot of Servala">
</div>
</div>
</div>

View file

@ -43,7 +43,7 @@
<div class="col-12 col-md-6 col-lg-3 mb-20 mb-lg-0">
<div class="card h-100 d-flex flex-column">
<div class="card__image">
<a href="{{ service.get_absolute_url }}"><img class="img-fluid" src="{{ service.logo.url }}" alt="{{ service.name }} logo" style="max-height: 80px; max-width: 250px; object-fit: contain;"></a>
<a href="{{ service.get_absolute_url }}"><img class="img-fluid card-logo" src="{{ service.logo.url }}" alt="{{ service.name }} logo"></a>
</div>
<div class="card__header">
<h3 class="card__title"><a href="{{ service.get_absolute_url }}" class="text-decoration-none">{{ service.name }}</a></h3>
@ -64,7 +64,7 @@
</div>
</div>
<div class="page-action d-lg-none">
<a class="btn btn-outline-primary btn-lg w-100" href="#" role="button">See All</a>
<a class="btn btn-outline-primary btn-lg w-100" href="{% url 'services:service_list' %}" role="button">See All</a>
</div>
</div>
</div>
@ -91,7 +91,7 @@
<div class="col-12 col-md-6 col-lg-3 mb-20 mb-lg-0">
<div class="card h-100 d-flex flex-column">
<div class="card__image__wide mb-4">
<a href="{{ provider.get_absolute_url }}"><img class="img-fluid" src="{{ provider.logo.url }}" alt="{{ provider.name }} logo" style="max-height: 80px; max-width: 250px; object-fit: contain;"></a>
<a href="{{ provider.get_absolute_url }}"><img class="img-fluid card-logo" src="{{ provider.logo.url }}" alt="{{ provider.name }} logo"></a>
</div>
<div class="card__header">
<h3 class="card__title"><a href="{{ provider.get_absolute_url }}" class="text-decoration-none">{{ provider.name }}</a></h3>
@ -111,7 +111,7 @@
</div>
</div>
<div class="page-action d-lg-none">
<a class="btn btn-outline-primary btn-lg w-100" href="#" role="button">See All</a>
<a class="btn btn-outline-primary btn-lg w-100" href="{% url 'services:provider_list' %}" role="button">See All</a>
</div>
</div>
</div>
@ -136,7 +136,7 @@
<div class="col-12 col-md-6 col-lg-3 mb-20 mb-lg-0">
<div class="card h-100 d-flex flex-column">
<div class="card__image__wide mb-4">
<a href="{{ partner.get_absolute_url }}"><img class="img-fluid" src="{{ partner.logo.url }}" alt="{{ partner.name }} logo" style="max-height: 80px; max-width: 250px; object-fit: contain;"></a>
<a href="{{ partner.get_absolute_url }}"><img class="img-fluid card-logo" src="{{ partner.logo.url }}" alt="{{ partner.name }} logo"></a>
</div>
<div class="card__header">
<h3 class="card__title"><a href="{{ partner.get_absolute_url }}" class="text-decoration-none">{{ partner.name }}</a></h3>
@ -154,7 +154,7 @@
</div>
</div>
<div class="page-action d-lg-none">
<a class="btn btn-outline-primary btn-lg w-100" href="#" role="button">See All</a>
<a class="btn btn-outline-primary btn-lg w-100" href="{% url 'services:partner_list' %}" role="button">See All</a>
</div>
</div>
</div>
@ -164,7 +164,7 @@
<div class="row">
<div class="col-12 col-lg-4 mb-30 mb-lg-0">
<div class="section-logo mx-auto">
<img class="img-fluid" src="{% static "img/section-logo.png" %}" alt="">
<img class="img-fluid" src="{% static "img/section-logo.png" %}" alt="Servala Icon Logo">
</div>
</div>
<div class="col-12 col-lg-8">

View file

@ -7,7 +7,7 @@
<section class="section bg-primary-subtle">
<div class="container mx-auto px-20 px-lg-0 pt-40 pb-60">
<header class="section-primary__header text-center">
<h2 class="section-h1 fs-40 fs-lg-64 mb-24">Contact Us</h2>
<h1 class="section-h1 fs-40 fs-lg-64 mb-24">Contact Us</h1>
<div class="text-gray-300 w-lg-37 mx-auto">
<p class="mb-0">We'd love to hear from you!</p>
</div>

View file

@ -10,7 +10,7 @@
<div class="flex-1 pr-lg-40 mb-40 mb-lg-0">
<div class="bg-gray-50 rounded-20 p-40">
<header>
<h2 class="fs-44 fw-semibold mb-40">Inquiry for {{ service.name }}</h2>
<h1 class="fs-44 fw-semibold mb-40">Inquiry for {{ service.name }}</h1>
</header>
<form method="post">
@ -78,7 +78,7 @@
<div class="d-flex align-items-center mb-24">
<div class="card__image mb-0">
{% if selected_offering.service.logo %}
<img class="img-fluid" src="{{ selected_offering.service.logo.url }}" alt="">
<img class="img-fluid" src="{{ selected_offering.service.logo.url }}" alt="Service Logo">
{% endif %}
</div>
<div class="card__header ps-16">

View file

@ -1,15 +1,16 @@
{% extends 'base.html' %}
{% load static %}
{% load contact_tags %}
{% block title %}{{ offering.service.name }} on {{ offering.cloud_provider.name }}{% endblock %}
{% block title %}Managed {{ offering.service.name }} on {{ offering.cloud_provider.name }}{% endblock %}
{% block content %}
<section class="section bg-primary-subtle">
<div class="container mx-auto px-20 px-lg-0 pt-40 pb-60">
<header class="section-primary__header text-center">
<h2 class="section-h1 fs-40 fs-lg-64 mb-24">Service Offering</h2>
<h1 class="section-h1 fs-40 fs-lg-64 mb-24">Managed {{ offering.service.name }} on {{ offering.cloud_provider.name }}</h1>
<div class="text-gray-300 w-lg-37 mx-auto">
<p class="mb-0">{{ offering.service.name }} managed by VSHN on {{ offering.cloud_provider.name }}</p>
<p class="mb-0">Details about {{ offering.service.name }} managed by VSHN on {{ offering.cloud_provider.name }}</p>
</div>
</header>
</div>
@ -142,6 +143,7 @@
{% endif %}
<!-- Plans -->
{% if offering.plans.all %}
<div class="pt-24" id="plans" style="scroll-margin-top: 30px;">
<h3 class="fs-24 fw-semibold lh-1 mb-12">Available Plans</h3>
<div class="row">
@ -173,19 +175,24 @@
<div class="alert alert-info">
<p>No plans available yet.</p>
<h4 class="mb-3">I'm interested in this offering</h4>
{% load contact_tags %}
{% embedded_contact_form source="Offering Interest" service=offering.service offering_id=offering.id %}
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="col-12" id="interest" style="scroll-margin-top: 30px;">
<h4 class="mb-3">I'm interested in this offering</h4>
{% load contact_tags %}
{% embedded_contact_form source="Offering Interest" service=offering.service offering_id=offering.id %}
</div>
{% endif %}
{% if offering.plans.exists %}
<div class="pt-40">
<h4 class="fs-22 fw-semibold lh-1 mb-12">I'm interested in a plan</h4>
<div class="row">
<div class="col-12">
{% load contact_tags %}
{% embedded_contact_form source="Plan Order" service=offering.service offering_id=offering.id choices=offering.plans.all choice_label="Select a Plan" %}
</div>
</div>

View file

@ -6,7 +6,7 @@
<section class="section bg-primary-subtle">
<div class="container mx-auto px-20 px-lg-0 pt-40 pb-60">
<header class="section-primary__header text-center">
<h2 class="section-h1 fs-40 fs-lg-64 mb-24">Service Offerings</h2>
<h1 class="section-h1 fs-40 fs-lg-64 mb-24">Service Offerings</h1>
<div class="text-gray-300 w-lg-37 mx-auto">
<p class="mb-0">Explore all available Offerings on Servala, with new ones added regularly. These ready-made packages bundle a Service on a Cloud Provider, making them ready for immediate use.</p>
</div>

View file

@ -7,7 +7,10 @@
<section class="section bg-primary-subtle">
<div class="container mx-auto px-20 px-lg-0 pt-40 pb-60">
<header class="section-primary__header text-center">
<h2 class="section-h1 fs-40 fs-lg-64 mb-24">Consulting Partner</h2>
<h1 class="section-h1 fs-40 fs-lg-64 mb-24">{{ partner.name }} on Servala</h1>
<div class="text-gray-300 w-lg-37 mx-auto">
<p class="mb-0">About the consulting partner {{ partner.name }} on Servala</p>
</div>
</header>
</div>
</section>

View file

@ -9,7 +9,7 @@
<section class="section bg-primary-subtle">
<div class="container mx-auto px-20 px-lg-0 pt-40 pb-60">
<header class="section-primary__header text-center">
<h2 class="section-h1 fs-40 fs-lg-64 mb-24">Consulting Partners</h2>
<h1 class="section-h1 fs-40 fs-lg-64 mb-24">Consulting Partners</h1>
<div class="text-gray-300 w-lg-37 mx-auto">
<p class="mb-0">Browse our network of expert Consulting Partners on Servala, with new partners added regularly. They'll help you get up to speed and make the most of specific services.</p>
</div>

View file

@ -1,13 +1,16 @@
{% extends 'base.html' %}
{% load contact_tags %}
{% block title %}Service Provider {{ provider.name }}{% endblock %}
{% block title %}Cloud Provider {{ provider.name }}{% endblock %}
{% block content %}
<section class="section bg-primary-subtle">
<div class="container mx-auto px-20 px-lg-0 pt-40 pb-60">
<header class="section-primary__header text-center">
<h2 class="section-h1 fs-40 fs-lg-64 mb-24">Service Provider</h2>
<h1 class="section-h1 fs-40 fs-lg-64 mb-24">{{ provider.name }} on Servala</h1>
<div class="text-gray-300 w-lg-37 mx-auto">
<p class="mb-0">About the cloud provider {{ provider.name }} on Servala</p>
</div>
</header>
</div>
</section>

View file

@ -2,14 +2,14 @@
{% load static %}
{% load contact_tags %}
{% block title %}Service Providers{% endblock %}
{% block title %}Cloud Providers{% endblock %}
{% block meta_description %}Discover cloud providers on Servala offering reliable infrastructure and innovative cloud computing solutions for businesses of all sizes.{% endblock %}
{% block content %}
<section class="section bg-primary-subtle">
<div class="container mx-auto px-20 px-lg-0 pt-40 pb-60">
<header class="section-primary__header text-center">
<h2 class="section-h1 fs-40 fs-lg-64 mb-24">Cloud Providers</h2>
<h1 class="section-h1 fs-40 fs-lg-64 mb-24">Cloud Providers</h1>
<div class="text-gray-300 w-lg-37 mx-auto">
<p class="mb-0">Explore all available Cloud Providers on Servala, with new ones added regularly.</p>
</div>

View file

@ -6,9 +6,9 @@
<section class="section bg-primary-subtle">
<div class="container mx-auto px-20 px-lg-0 pt-40 pb-60">
<header class="section-primary__header text-center">
<h2 class="section-h1 fs-40 fs-lg-64 mb-24">Service Details</h2>
<h1 class="section-h1 fs-40 fs-lg-64 mb-24">{{ service.name }} on Servala</h1>
<div class="text-gray-300 w-lg-37 mx-auto">
<p class="mb-0">{{ service.name }}</p>
<p class="mb-0">Details about the service {{ service.name }} on Servala</p>
</div>
</header>
</div>
@ -142,11 +142,15 @@
{% if service.offerings.exists %}
<h3 class="fs-24 fw-semibold lh-1 mb-12">Get it on</h3>
<p>Choose one of our trusted service providers</p>
{% for offering in service.offerings.all %}
<p><a class="btn btn-primary btn-lg mr-md-17 mb-17 mb-md-0px mb-lg-17 mb-xl-0 w-100 w-md-auto"
href="{% url 'services:offering_detail' offering.cloud_provider.slug offering.service.slug %}"
role="button">{{ offering.cloud_provider.name }}</a></p>
{% endfor %}
<div class="d-flex flex-wrap gap-3">
{% for offering in service.offerings.all %}
{% if not offering.cloud_provider.disable_listing %}
<a class="btn btn-primary btn-lg w-auto"
href="{% url 'services:offering_detail' offering.cloud_provider.slug offering.service.slug %}"
role="button">{{ offering.cloud_provider.name }}</a>
{% endif %}
{% endfor %}
</div>
{% else %}
<div class="pt-40">
<h3 class="fs-24 fw-semibold lh-1 mb-12">Contact Us About This Service</h3>

View file

@ -9,7 +9,7 @@
<section class="section bg-primary-subtle">
<div class="container mx-auto px-20 px-lg-0 pt-40 pb-60">
<header class="section-primary__header text-center">
<h2 class="section-h1 fs-40 fs-lg-64 mb-24">Services</h2>
<h1 class="section-h1 fs-40 fs-lg-64 mb-24">Services</h1>
<div class="text-gray-300 w-lg-37 mx-auto">
<p class="mb-0">Explore all available Services on Servala, with new ones added regularly.</p>
</div>

View file

@ -8,7 +8,7 @@
<div class="col-md-8 text-center">
<div class="card shadow-sm">
<div class="card-body p-5">
<h2 class="mb-4">Thank You!</h2>
<h1 class="mb-4">Thank You!</h1>
<p class="lead">Your message has been sent successfully.</p>
<p>We'll get back to you as soon as possible.</p>
<a href="{% url 'services:homepage' %}" class="btn btn-primary mt-3">Take me home</a>

View file

@ -0,0 +1,7 @@
<div id="signup-form-container" class="text-center py-3">
<div class="alert alert-danger" role="alert">
<h4 class="section-h1">Oops!</h4>
<p class="text-gray-300">Something went wrong. Please try again later.</p>
<button class="btn btn-primary mt-2" onclick="location.reload()">Try Again</button>
</div>
</div>

View file

@ -0,0 +1,6 @@
<div id="signup-form-container" class="text-center py-3">
<div role="alert">
<h4 class="section-h1">Thank you!</h4>
<p class="text-gray-300">You have been successfully subscribed to our mailing list.</p>
</div>
</div>

View file

@ -1,6 +1,6 @@
# hub/services/templatetags/json_ld_tags.py
from django import template
from django.urls import resolve
from django.urls import resolve, Resolver404
from django.utils.safestring import mark_safe
import json
@ -11,14 +11,14 @@ register = template.Library()
def json_ld_structured_data(context):
"""
Generates appropriate JSON-LD structured data based on the current page.
For schemas, see https://schema.org/
"""
request = context["request"]
current_url = request.path
resolved_view = resolve(current_url)
view_name = resolved_view.url_name
request = context.get("request")
if not request:
return ""
# Base URL for building absolute URLs
base_url = request.build_absolute_uri("/").rstrip("/")
current_url = request.path
base_url = f"{request.scheme}://{request.get_host()}"
# Default organization data (for Servala)
organization_data = {
@ -30,8 +30,8 @@ def json_ld_structured_data(context):
"contactPoint": {
"@type": "ContactPoint",
"telephone": "+41 44 545 53 00",
"email": "hi@serva.la",
"contactType": "Customer Support",
"email": "hi@servala.com",
"contactType": "Sales",
},
"address": {
"@type": "PostalAddress",
@ -42,27 +42,45 @@ def json_ld_structured_data(context):
},
}
# Handle different page types
if view_name == "homepage":
# Add try-except around the view resolution
try:
resolved_view = resolve(current_url)
view_name = resolved_view.url_name
except Resolver404:
# For 404 pages or other unresolvable URLs, return minimal data
data = {
"@context": "https://schema.org",
"@type": "WebSite",
"name": "Servala - Open Cloud Native Service Hub",
"url": base_url,
"description": "Servala connects businesses, developers, and cloud service providers on one unique hub with secure, scalable, and easy-to-use cloud-native services.",
"potentialAction": {
"@type": "SearchAction",
"target": f"{base_url}/services/?search={{search_term_string}}",
"query-input": "required name=search_term_string",
},
}
json_ld = json.dumps(data, indent=2)
return mark_safe(f'<script type="application/ld+json">{json_ld}</script>')
# Handle different page types
if view_name == "homepage":
data = [
{
"@context": "https://schema.org",
"@type": "WebSite",
"name": "Servala - Open Cloud Native Service Hub",
"url": base_url,
"description": "Servala connects businesses, developers, and cloud service providers on one unique hub with secure, scalable, and easy-to-use cloud-native services.",
"potentialAction": {
"@type": "SearchAction",
"target": f"{base_url}/service/?search={{search_term_string}}",
"query-input": "required name=search_term_string",
},
},
organization_data,
]
elif view_name == "service_list":
data = {
"@context": "https://schema.org",
"@type": "CollectionPage",
"name": "Cloud Services - Servala",
"url": f"{base_url}/services/",
"url": f"{base_url}/service/",
"description": "Explore all available cloud services on Servala, with new services added regularly.",
"isPartOf": {"@type": "WebSite", "name": "Servala", "url": base_url},
}

View file

@ -21,4 +21,5 @@ urlpatterns = [
path("contact/", views.leads.contact, name="contact"),
path("contact/thank-you/", views.thank_you, name="thank_you"),
path("contact-form/", views.contact_form, name="contact_form"),
path("subscribe/", views.subscribe, name="subscribe"),
]

View file

@ -4,3 +4,4 @@ from .partners import *
from .providers import *
from .services import *
from .pages import *
from .subscriptions import *

View file

@ -1,5 +1,6 @@
from django.shortcuts import render, get_object_or_404
from django.db.models import Q
from django.db.models import Count
from hub.services.models import (
Service,
ServiceOffering,
@ -47,14 +48,16 @@ def provider_detail(request, slug):
.prefetch_related("categories")
)
# Get the provider's offerings and sort them by service attributes
# Get the provider's offerings and sort them by service attributes and plan availability
# Exclude offerings with disabled services
ordered_offerings = (
ServiceOffering.objects.filter(
cloud_provider=provider, service__disable_listing=False
)
.select_related("service")
.annotate(has_plans=Count("plans"))
.order_by(
"-has_plans", # Offerings with plans first
"-service__is_featured", # Featured first (True before False)
"service__is_coming_soon", # Coming soon last (False before True)
"service__name", # Alphabetically within each group

View file

@ -0,0 +1,36 @@
import logging
from django.conf import settings
from django.shortcuts import render
from django.views.decorators.http import require_POST
from hub.services.odoo import OdooAPI
logger = logging.getLogger(__name__)
@require_POST
def subscribe(request):
"""Handle mailing list subscription requests"""
email = request.POST.get("email", "")
if not email:
return render(request, "subscriptions/error.html")
try:
# Get mailing list ID from settings
mailing_list_id = settings.ODOO_CONFIG.get("mailing_list_id", 46)
# Connect to Odoo
odoo = OdooAPI()
# Add subscriber to mailing list
result = odoo.add_to_mailing_list(email, mailing_list_id)
if result:
return render(request, "subscriptions/success.html")
else:
return render(request, "subscriptions/error.html")
except Exception as e:
logger.error(
f"Failed to add subscriber to mailing list: {str(e)}", exc_info=True
)
return render(request, "subscriptions/error.html")

View file

@ -55,6 +55,10 @@ CSRF_TRUSTED_ORIGINS = [f"https://{h}" for h in HTTPS_HOSTS] + [
# Primary website URL
WEBSITE_URL = env.str("WEBSITE_URL", default="https://servala.com")
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
USE_X_FORWARDED_HOST = True
USE_X_FORWARDED_PORT = True
# Application definition
INSTALLED_APPS = [
@ -204,6 +208,7 @@ ODOO_CONFIG = {
"source_id": env.str("ODOO_LEAD_SOURCE_ID", default="1"),
"medium_id": env.str("ODOO_LEAD_MEDIUM_ID", default="1"),
"tag_id": env.str("ODOO_LEAD_TAG_ID", default="1"),
"mailing_list_id": env.int("ODOO_MAILING_LIST_ID", default=46),
}
BROKER_USERNAME = env.str("BROKER_USERNAME", default="broker")

View file

@ -6,6 +6,7 @@ from django.shortcuts import render
from django.urls import path, include
from django.contrib.sitemaps.views import sitemap
from django.http import HttpResponse
from django.views.generic.base import RedirectView
from hub.services.views.errors import bad_request, page_not_found, server_error
@ -21,7 +22,7 @@ from .sitemaps import (
def robots_txt(request):
content = """User-agent: *
Allow: /
Sitemap: https://serva.la/sitemap.xml
Sitemap: https://servala.com/sitemap.xml
"""
return HttpResponse(content, content_type="text/plain")
@ -49,6 +50,11 @@ urlpatterns = [
name="django.contrib.sitemaps.views.sitemap",
),
path("robots.txt", robots_txt, name="robots_txt"),
path(
"favicon.ico",
RedirectView.as_view(url=settings.STATIC_URL + "img/favicon.ico"),
name="favicon",
),
]
if settings.DEBUG:
urlpatterns += [

View file

@ -5,7 +5,7 @@ description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"django>=5.1.5",
"django>=5.2",
"django-admin-sortable2>=2.2.4",
"django-jazzmin>=3.0.1",
"django-nested-admin>=4.1.1",

182
uv.lock generated
View file

@ -1,14 +1,14 @@
version = 1
revision = 1
revision = 2
requires-python = ">=3.13"
[[package]]
name = "asgiref"
version = "3.8.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/29/38/b3395cc9ad1b56d2ddac9970bc8f4141312dbaec28bc7c218b0dfafd0f42/asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590", size = 35186 }
sdist = { url = "https://files.pythonhosted.org/packages/29/38/b3395cc9ad1b56d2ddac9970bc8f4141312dbaec28bc7c218b0dfafd0f42/asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590", size = 35186, upload-time = "2024-03-22T14:39:36.863Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/39/e3/893e8757be2612e6c266d9bb58ad2e3651524b5b40cf56761e985a28b13e/asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", size = 23828 },
{ url = "https://files.pythonhosted.org/packages/39/e3/893e8757be2612e6c266d9bb58ad2e3651524b5b40cf56761e985a28b13e/asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", size = 23828, upload-time = "2024-03-22T14:39:34.521Z" },
]
[[package]]
@ -19,32 +19,32 @@ dependencies = [
{ name = "django" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/98/9f/fc9905758256af4f68a55da94ab78a13e7775074edfdcaddd757d4921686/dj_database_url-2.3.0.tar.gz", hash = "sha256:ae52e8e634186b57e5a45e445da5dc407a819c2ceed8a53d1fac004cc5288787", size = 10980 }
sdist = { url = "https://files.pythonhosted.org/packages/98/9f/fc9905758256af4f68a55da94ab78a13e7775074edfdcaddd757d4921686/dj_database_url-2.3.0.tar.gz", hash = "sha256:ae52e8e634186b57e5a45e445da5dc407a819c2ceed8a53d1fac004cc5288787", size = 10980, upload-time = "2024-10-23T10:05:19.953Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e5/91/641a4e5c8903ed59f6cbcce571003bba9c5d2f731759c31db0ba83bb0bdb/dj_database_url-2.3.0-py3-none-any.whl", hash = "sha256:bb0d414ba0ac5cd62773ec7f86f8cc378a9dbb00a80884c2fc08cc570452521e", size = 7793 },
{ url = "https://files.pythonhosted.org/packages/e5/91/641a4e5c8903ed59f6cbcce571003bba9c5d2f731759c31db0ba83bb0bdb/dj_database_url-2.3.0-py3-none-any.whl", hash = "sha256:bb0d414ba0ac5cd62773ec7f86f8cc378a9dbb00a80884c2fc08cc570452521e", size = 7793, upload-time = "2024-10-23T10:05:41.254Z" },
]
[[package]]
name = "dj-email-url"
version = "1.0.6"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/14/ef/8eb478accd9b0369d46a98d1b43027ee0c254096149265c78e6b2e2fa3b0/dj-email-url-1.0.6.tar.gz", hash = "sha256:55ffe3329e48f54f8a75aa36ece08f365e09d61f8a209773ef09a1d4760e699a", size = 15590 }
sdist = { url = "https://files.pythonhosted.org/packages/14/ef/8eb478accd9b0369d46a98d1b43027ee0c254096149265c78e6b2e2fa3b0/dj-email-url-1.0.6.tar.gz", hash = "sha256:55ffe3329e48f54f8a75aa36ece08f365e09d61f8a209773ef09a1d4760e699a", size = 15590, upload-time = "2022-09-24T11:04:50.281Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8a/f9/fcb9745099d821f9a26092d3d6f4df8f10049885045c3a93ff726d2e40a6/dj_email_url-1.0.6-py2.py3-none-any.whl", hash = "sha256:cbd08327fbb08b104eac160fb4703f375532e4c0243eb230f5b960daee7a96db", size = 6296 },
{ url = "https://files.pythonhosted.org/packages/8a/f9/fcb9745099d821f9a26092d3d6f4df8f10049885045c3a93ff726d2e40a6/dj_email_url-1.0.6-py2.py3-none-any.whl", hash = "sha256:cbd08327fbb08b104eac160fb4703f375532e4c0243eb230f5b960daee7a96db", size = 6296, upload-time = "2022-09-24T11:04:47.191Z" },
]
[[package]]
name = "django"
version = "5.1.5"
version = "5.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "asgiref" },
{ name = "sqlparse" },
{ name = "tzdata", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/e4/17/834e3e08d590dcc27d4cc3c5cd4e2fb757b7a92bab9de8ee402455732952/Django-5.1.5.tar.gz", hash = "sha256:19bbca786df50b9eca23cee79d495facf55c8f5c54c529d9bf1fe7b5ea086af3", size = 10700031 }
sdist = { url = "https://files.pythonhosted.org/packages/4c/1b/c6da718c65228eb3a7ff7ba6a32d8e80fa840ca9057490504e099e4dd1ef/Django-5.2.tar.gz", hash = "sha256:1a47f7a7a3d43ce64570d350e008d2949abe8c7e21737b351b6a1611277c6d89", size = 10824891, upload-time = "2025-04-02T13:08:06.874Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/11/e6/e92c8c788b83d109f34d933c5e817095d85722719cb4483472abc135f44e/Django-5.1.5-py3-none-any.whl", hash = "sha256:c46eb936111fffe6ec4bc9930035524a8be98ec2f74d8a0ff351226a3e52f459", size = 8276957 },
{ url = "https://files.pythonhosted.org/packages/63/e0/6a5b5ea350c5bd63fe94b05e4c146c18facb51229d9dee42aa39f9fc2214/Django-5.2-py3-none-any.whl", hash = "sha256:91ceed4e3a6db5aedced65e3c8f963118ea9ba753fc620831c77074e620e7d83", size = 8301361, upload-time = "2025-04-02T13:08:01.465Z" },
]
[[package]]
@ -54,9 +54,9 @@ source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ee/a1/0651ad69906f9ec9e73897353e933611550c6d31bfa9f721319c0ed99108/django_admin_sortable2-2.2.4.tar.gz", hash = "sha256:155e6114c7a931bceed9513af014f782ff1e643d99e81ddfef934f1daecd669d", size = 68207 }
sdist = { url = "https://files.pythonhosted.org/packages/ee/a1/0651ad69906f9ec9e73897353e933611550c6d31bfa9f721319c0ed99108/django_admin_sortable2-2.2.4.tar.gz", hash = "sha256:155e6114c7a931bceed9513af014f782ff1e643d99e81ddfef934f1daecd669d", size = 68207, upload-time = "2024-11-15T09:43:15.451Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/66/c3/e804b1f04546c1060e566f35177c346590820a95bfb981d1f6360b419437/django_admin_sortable2-2.2.4-py3-none-any.whl", hash = "sha256:406c5b6d6e84ad982cc6e53c3f34b5db5f0a3f34891126af90c9fb2c372f53d5", size = 90816 },
{ url = "https://files.pythonhosted.org/packages/66/c3/e804b1f04546c1060e566f35177c346590820a95bfb981d1f6360b419437/django_admin_sortable2-2.2.4-py3-none-any.whl", hash = "sha256:406c5b6d6e84ad982cc6e53c3f34b5db5f0a3f34891126af90c9fb2c372f53d5", size = 90816, upload-time = "2024-11-15T09:43:13.665Z" },
]
[[package]]
@ -67,18 +67,18 @@ dependencies = [
{ name = "asgiref" },
{ name = "django" },
]
sdist = { url = "https://files.pythonhosted.org/packages/9f/bc/3c67f7daca53b826ec51888576fe5e117d9442d2d0acb58f4264d48b9dba/django_browser_reload-1.17.0.tar.gz", hash = "sha256:3667939cde0eee1a6d698dbe3b78cf10b573dabc4e711fb7933f1ba91fb98da4", size = 14312 }
sdist = { url = "https://files.pythonhosted.org/packages/9f/bc/3c67f7daca53b826ec51888576fe5e117d9442d2d0acb58f4264d48b9dba/django_browser_reload-1.17.0.tar.gz", hash = "sha256:3667939cde0eee1a6d698dbe3b78cf10b573dabc4e711fb7933f1ba91fb98da4", size = 14312, upload-time = "2024-10-29T10:31:14.846Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/8f/62fc4fbf5c05c2210e6cb616f1c2a3da53871dfecbaa4c44b1f482ca3e8f/django_browser_reload-1.17.0-py3-none-any.whl", hash = "sha256:d372c12c1c5962c02279a53cac7e8a020c48f104592c637a06d0768b28d2d6be", size = 12228 },
{ url = "https://files.pythonhosted.org/packages/7f/8f/62fc4fbf5c05c2210e6cb616f1c2a3da53871dfecbaa4c44b1f482ca3e8f/django_browser_reload-1.17.0-py3-none-any.whl", hash = "sha256:d372c12c1c5962c02279a53cac7e8a020c48f104592c637a06d0768b28d2d6be", size = 12228, upload-time = "2024-10-29T10:31:13.332Z" },
]
[[package]]
name = "django-cache-url"
version = "3.4.5"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/20/28/d420aaa89028d2ec0cf17c1510d06ff6a8ed0bf1abfb7f33c999e1c5befa/django-cache-url-3.4.5.tar.gz", hash = "sha256:eb9fb194717524348c95cad9905b70b647452741c1d9e481fac6d2125f0ad917", size = 7230 }
sdist = { url = "https://files.pythonhosted.org/packages/20/28/d420aaa89028d2ec0cf17c1510d06ff6a8ed0bf1abfb7f33c999e1c5befa/django-cache-url-3.4.5.tar.gz", hash = "sha256:eb9fb194717524348c95cad9905b70b647452741c1d9e481fac6d2125f0ad917", size = 7230, upload-time = "2023-12-04T17:19:46.21Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/48/90/01755e4a42558b763f7021e9369aa6aa94c2ede7313deed56cb7483834ab/django_cache_url-3.4.5-py2.py3-none-any.whl", hash = "sha256:5f350759978483ab85dc0e3e17b3d53eed3394a28148f6bf0f53d11d0feb5b3c", size = 4760 },
{ url = "https://files.pythonhosted.org/packages/48/90/01755e4a42558b763f7021e9369aa6aa94c2ede7313deed56cb7483834ab/django_cache_url-3.4.5-py2.py3-none-any.whl", hash = "sha256:5f350759978483ab85dc0e3e17b3d53eed3394a28148f6bf0f53d11d0feb5b3c", size = 4760, upload-time = "2023-12-04T17:19:44.355Z" },
]
[[package]]
@ -88,9 +88,9 @@ source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django" },
]
sdist = { url = "https://files.pythonhosted.org/packages/84/96/21b6255e90d92a3eb4e93bea9376635d54258e0353ebb913a55e40ae9254/django_jazzmin-3.0.1.tar.gz", hash = "sha256:67ae148bade41267a09ca8e4352ddefa6121795ebbac238bb9a6564ff841eb1b", size = 2053550 }
sdist = { url = "https://files.pythonhosted.org/packages/84/96/21b6255e90d92a3eb4e93bea9376635d54258e0353ebb913a55e40ae9254/django_jazzmin-3.0.1.tar.gz", hash = "sha256:67ae148bade41267a09ca8e4352ddefa6121795ebbac238bb9a6564ff841eb1b", size = 2053550, upload-time = "2024-10-08T17:40:59.771Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ad/5b/2f8c4b168e6c41bf1e4b14d787deb23d80f618f0693db913bbe208a4a907/django_jazzmin-3.0.1-py3-none-any.whl", hash = "sha256:12a0a4c1d4fd09c2eef22acf6a1f03112b515ba695c59faa8ea80efc81c1f21b", size = 2125957 },
{ url = "https://files.pythonhosted.org/packages/ad/5b/2f8c4b168e6c41bf1e4b14d787deb23d80f618f0693db913bbe208a4a907/django_jazzmin-3.0.1-py3-none-any.whl", hash = "sha256:12a0a4c1d4fd09c2eef22acf6a1f03112b515ba695c59faa8ea80efc81c1f21b", size = 2125957, upload-time = "2024-10-08T17:40:57.359Z" },
]
[[package]]
@ -100,9 +100,9 @@ source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django" },
]
sdist = { url = "https://files.pythonhosted.org/packages/0a/02/5d3b57d2ad3c1819aaf921fa6b9d7fbc54ec5d81871a7fb6f4f0b146dd4e/django_js_asset-3.0.1.tar.gz", hash = "sha256:5ad51814edf38d28e6280e6ecad50ee40551363a2f6a6bfe93577dee793dc378", size = 7701 }
sdist = { url = "https://files.pythonhosted.org/packages/0a/02/5d3b57d2ad3c1819aaf921fa6b9d7fbc54ec5d81871a7fb6f4f0b146dd4e/django_js_asset-3.0.1.tar.gz", hash = "sha256:5ad51814edf38d28e6280e6ecad50ee40551363a2f6a6bfe93577dee793dc378", size = 7701, upload-time = "2024-12-17T17:16:33.559Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/61/d1/be003d14c880c100d8713b2ca0a286728e6e8b47e50d25e2fab31adc9632/django_js_asset-3.0.1-py3-none-any.whl", hash = "sha256:0b7ee73c45ca65cccbcc2f60cbe8fbc87ff133b543c282cb64fe6c13d7ca4c10", size = 4283 },
{ url = "https://files.pythonhosted.org/packages/61/d1/be003d14c880c100d8713b2ca0a286728e6e8b47e50d25e2fab31adc9632/django_js_asset-3.0.1-py3-none-any.whl", hash = "sha256:0b7ee73c45ca65cccbcc2f60cbe8fbc87ff133b543c282cb64fe6c13d7ca4c10", size = 4283, upload-time = "2024-12-17T17:16:34.818Z" },
]
[[package]]
@ -112,9 +112,9 @@ source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "python-monkey-business" },
]
sdist = { url = "https://files.pythonhosted.org/packages/1c/d1/bd500d354dcc3ccbf74507c97dabc5aee18bf0620d2df3deb3971b5c14ed/django-nested-admin-4.1.1.tar.gz", hash = "sha256:645d63b38d579b034a65e0983f1f8cbb8824c75b4232f8d62a1583fa7a9f568f", size = 421628 }
sdist = { url = "https://files.pythonhosted.org/packages/1c/d1/bd500d354dcc3ccbf74507c97dabc5aee18bf0620d2df3deb3971b5c14ed/django-nested-admin-4.1.1.tar.gz", hash = "sha256:645d63b38d579b034a65e0983f1f8cbb8824c75b4232f8d62a1583fa7a9f568f", size = 421628, upload-time = "2024-08-13T02:16:36.9Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/fe/e2/2a58c3c21c2e8c383f7e9de2874fa7b443705146e54d0364f1fe6fc31b7e/django_nested_admin-4.1.1-py3-none-any.whl", hash = "sha256:7e72ab7a8ae4c91074f6f709ce38fdf54f9c5f78d19e68772e0f05b83090ec9f", size = 465355 },
{ url = "https://files.pythonhosted.org/packages/fe/e2/2a58c3c21c2e8c383f7e9de2874fa7b443705146e54d0364f1fe6fc31b7e/django_nested_admin-4.1.1-py3-none-any.whl", hash = "sha256:7e72ab7a8ae4c91074f6f709ce38fdf54f9c5f78d19e68772e0f05b83090ec9f", size = 465355, upload-time = "2024-08-13T02:16:34.405Z" },
]
[[package]]
@ -125,9 +125,9 @@ dependencies = [
{ name = "django" },
{ name = "django-js-asset" },
]
sdist = { url = "https://files.pythonhosted.org/packages/d6/2d/28aeb5d89b96b0850f286f50d1bb51259d3425242035fb9f893073350b22/django_prose_editor-0.10.3.tar.gz", hash = "sha256:4ecef8cbd0286065ec54e18e15419495c80404a408860cad2189180724f93d49", size = 260180 }
sdist = { url = "https://files.pythonhosted.org/packages/d6/2d/28aeb5d89b96b0850f286f50d1bb51259d3425242035fb9f893073350b22/django_prose_editor-0.10.3.tar.gz", hash = "sha256:4ecef8cbd0286065ec54e18e15419495c80404a408860cad2189180724f93d49", size = 260180, upload-time = "2025-01-21T18:21:41.748Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f2/fd/922e6f3e9827c31a9bc00751ac02f0798c5beeae4994a97dbb978a1a55a2/django_prose_editor-0.10.3-py3-none-any.whl", hash = "sha256:776f0eb86791e72278f55abc98e426620f9bff5554a46c513069f8c089d80960", size = 261340 },
{ url = "https://files.pythonhosted.org/packages/f2/fd/922e6f3e9827c31a9bc00751ac02f0798c5beeae4994a97dbb978a1a55a2/django_prose_editor-0.10.3-py3-none-any.whl", hash = "sha256:776f0eb86791e72278f55abc98e426620f9bff5554a46c513069f8c089d80960", size = 261340, upload-time = "2025-01-21T18:21:45.122Z" },
]
[package.optional-dependencies]
@ -142,9 +142,9 @@ source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a2/11/ab9c6b0105d55b9a8197b9795d77fec72d1ec065c2cb479410c6ca1f7daf/django_schema_viewer-0.5.2.tar.gz", hash = "sha256:4c9316a3831e6015270b432404f1589b6b711b13ebc6d797b1fce82d1fa7281e", size = 486063 }
sdist = { url = "https://files.pythonhosted.org/packages/a2/11/ab9c6b0105d55b9a8197b9795d77fec72d1ec065c2cb479410c6ca1f7daf/django_schema_viewer-0.5.2.tar.gz", hash = "sha256:4c9316a3831e6015270b432404f1589b6b711b13ebc6d797b1fce82d1fa7281e", size = 486063, upload-time = "2025-01-11T23:55:38.135Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/aa/1a/f2dc4b54b18da7fd8dec7149c86f484581addd010f65f7a40bf16addbf39/django_schema_viewer-0.5.2-py3-none-any.whl", hash = "sha256:d799f52194cb906add990a1f178d92b0acfcb0a2e54c022843784e06fb12d75b", size = 492672 },
{ url = "https://files.pythonhosted.org/packages/aa/1a/f2dc4b54b18da7fd8dec7149c86f484581addd010f65f7a40bf16addbf39/django_schema_viewer-0.5.2-py3-none-any.whl", hash = "sha256:d799f52194cb906add990a1f178d92b0acfcb0a2e54c022843784e06fb12d75b", size = 492672, upload-time = "2025-01-11T23:55:40.496Z" },
]
[[package]]
@ -154,9 +154,9 @@ source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django" },
]
sdist = { url = "https://files.pythonhosted.org/packages/2c/ce/31482eb688bdb4e271027076199e1aa8d02507e530b6d272ab8b4481557c/djangorestframework-3.15.2.tar.gz", hash = "sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad", size = 1067420 }
sdist = { url = "https://files.pythonhosted.org/packages/2c/ce/31482eb688bdb4e271027076199e1aa8d02507e530b6d272ab8b4481557c/djangorestframework-3.15.2.tar.gz", hash = "sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad", size = 1067420, upload-time = "2024-06-19T07:59:32.891Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7c/b6/fa99d8f05eff3a9310286ae84c4059b08c301ae4ab33ae32e46e8ef76491/djangorestframework-3.15.2-py3-none-any.whl", hash = "sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20", size = 1071235 },
{ url = "https://files.pythonhosted.org/packages/7c/b6/fa99d8f05eff3a9310286ae84c4059b08c301ae4ab33ae32e46e8ef76491/djangorestframework-3.15.2-py3-none-any.whl", hash = "sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20", size = 1071235, upload-time = "2024-06-19T07:59:26.106Z" },
]
[[package]]
@ -167,9 +167,9 @@ dependencies = [
{ name = "marshmallow" },
{ name = "python-dotenv" },
]
sdist = { url = "https://files.pythonhosted.org/packages/3c/8f/952bd034eac79c8b68b6c770cb78c2bdcb3140d31ff224847f3520077d75/environs-14.1.0.tar.gz", hash = "sha256:a5f2afe9d5a21b468e74a3cceacf5d2371fd67dbb9a7e54fe62290c75a09cdfa", size = 30985 }
sdist = { url = "https://files.pythonhosted.org/packages/3c/8f/952bd034eac79c8b68b6c770cb78c2bdcb3140d31ff224847f3520077d75/environs-14.1.0.tar.gz", hash = "sha256:a5f2afe9d5a21b468e74a3cceacf5d2371fd67dbb9a7e54fe62290c75a09cdfa", size = 30985, upload-time = "2025-01-10T15:27:49.362Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d5/ad/57cfa3e8a006df88e723524127dbab2971a4877c97e7bad070257e15cb6c/environs-14.1.0-py3-none-any.whl", hash = "sha256:a7edda1668ddf1fbfcb7662bdc242dac25648eff2c7fdbaa5d959693afed7a3e", size = 15332 },
{ url = "https://files.pythonhosted.org/packages/d5/ad/57cfa3e8a006df88e723524127dbab2971a4877c97e7bad070257e15cb6c/environs-14.1.0-py3-none-any.whl", hash = "sha256:a7edda1668ddf1fbfcb7662bdc242dac25648eff2c7fdbaa5d959693afed7a3e", size = 15332, upload-time = "2025-01-10T15:27:42.865Z" },
]
[package.optional-dependencies]
@ -186,103 +186,103 @@ source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "packaging" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ed/3a/b392ca6582ce5c2e515a8ca365f89b6e631d864a80ecdc72e0bc1bf3aec6/marshmallow-3.26.0.tar.gz", hash = "sha256:eb36762a1cc76d7abf831e18a3a1b26d3d481bbc74581b8e532a3d3a8115e1cb", size = 221490 }
sdist = { url = "https://files.pythonhosted.org/packages/ed/3a/b392ca6582ce5c2e515a8ca365f89b6e631d864a80ecdc72e0bc1bf3aec6/marshmallow-3.26.0.tar.gz", hash = "sha256:eb36762a1cc76d7abf831e18a3a1b26d3d481bbc74581b8e532a3d3a8115e1cb", size = 221490, upload-time = "2025-01-23T03:20:11.904Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d6/0d/80d7071803df1957c304bc096a714334dda7eb41ecfdd28dcfb49b1cde0e/marshmallow-3.26.0-py3-none-any.whl", hash = "sha256:1287bca04e6a5f4094822ac153c03da5e214a0a60bcd557b140f3e66991b8ca1", size = 50846 },
{ url = "https://files.pythonhosted.org/packages/d6/0d/80d7071803df1957c304bc096a714334dda7eb41ecfdd28dcfb49b1cde0e/marshmallow-3.26.0-py3-none-any.whl", hash = "sha256:1287bca04e6a5f4094822ac153c03da5e214a0a60bcd557b140f3e66991b8ca1", size = 50846, upload-time = "2025-01-23T03:20:09.805Z" },
]
[[package]]
name = "nh3"
version = "0.2.20"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/46/f2/eb781d94c7855e9129cbbdd3ab09a470441e4176a82a396ae1df270a7333/nh3-0.2.20.tar.gz", hash = "sha256:9705c42d7ff88a0bea546c82d7fe5e59135e3d3f057e485394f491248a1f8ed5", size = 17489 }
sdist = { url = "https://files.pythonhosted.org/packages/46/f2/eb781d94c7855e9129cbbdd3ab09a470441e4176a82a396ae1df270a7333/nh3-0.2.20.tar.gz", hash = "sha256:9705c42d7ff88a0bea546c82d7fe5e59135e3d3f057e485394f491248a1f8ed5", size = 17489, upload-time = "2024-12-17T12:50:22.381Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/3c/65/d31d93b6d1e5fe80d0cc18f0b96eaa561edfa0a15a6ef6b0fce50202a931/nh3-0.2.20-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e1061a4ab6681f6bdf72b110eea0c4e1379d57c9de937db3be4202f7ad6043db", size = 1202187 },
{ url = "https://files.pythonhosted.org/packages/b4/ae/5b03bf198e06921454012e4b9a51e676d26fd37d9fdc1f29371a0b380487/nh3-0.2.20-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb4254b1dac4a1ee49919a5b3f1caf9803ea8dada1816d9e8289e63d3cd0dd9a", size = 737822 },
{ url = "https://files.pythonhosted.org/packages/0a/53/a12dffb6ee3772deba82eb5997667fc835afd2e813d1f4080d8738f29eec/nh3-0.2.20-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ae9cbd713524cdb81e64663d0d6aae26f678db9f2cd9db0bf162606f1f9f20c", size = 756643 },
{ url = "https://files.pythonhosted.org/packages/d0/0c/6cd2c5ac3e6e31f2a28721e8e2a924cb6b05ad054bf787bd1816ffd40b96/nh3-0.2.20-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e1f7370b4e14cc03f5ae141ef30a1caf81fa5787711f80be9081418dd9eb79d2", size = 923415 },
{ url = "https://files.pythonhosted.org/packages/64/f0/229a6c8b81b86ba22d8e7f27ade62cb2fcfb987e570f49944fdd8490a76a/nh3-0.2.20-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:ac4d27dc836a476efffc6eb661994426b8b805c951b29c9cf2ff36bc9ad58bc5", size = 994959 },
{ url = "https://files.pythonhosted.org/packages/75/e3/62ae3d3b658739ee15b129356fe6d4c4bc8ab235d7bf2e0d2794d64f7bc6/nh3-0.2.20-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4fd2e9248725ebcedac3997a8d3da0d90a12a28c9179c6ba51f1658938ac30d0", size = 915777 },
{ url = "https://files.pythonhosted.org/packages/45/bd/8405d03371e335f02eb72e09dcf73307f8fd3095e4165cec6836346fe3db/nh3-0.2.20-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f7d564871833ddbe54df3aa59053b1110729d3a800cb7628ae8f42adb3d75208", size = 908614 },
{ url = "https://files.pythonhosted.org/packages/ee/f8/5d977f09cf82c1f22a864375f471db111530fc79c88efdf0659fe6d3d6bc/nh3-0.2.20-cp313-cp313t-win32.whl", hash = "sha256:d2a176fd4306b6f0f178a3f67fac91bd97a3a8d8fafb771c9b9ef675ba5c8886", size = 540482 },
{ url = "https://files.pythonhosted.org/packages/c5/f4/e34afe5fd8bed1920eac2974c9c853f548b4b65c139444285ffd2a68495d/nh3-0.2.20-cp313-cp313t-win_amd64.whl", hash = "sha256:6ed834c68452a600f517dd3e1534dbfaff1f67f98899fecf139a055a25d99150", size = 541302 },
{ url = "https://files.pythonhosted.org/packages/92/08/5e3b61eed1bc0efeb330ddc5cf5194f28a0b7be7943aa20bd44cfe14650b/nh3-0.2.20-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:76e2f603b30c02ff6456b233a83fc377dedab6a50947b04e960a6b905637b776", size = 1202141 },
{ url = "https://files.pythonhosted.org/packages/29/d2/3377f8006c71e95e007b07b5bfcac22c9de4744ca3efb23b396d3deb9581/nh3-0.2.20-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:181063c581defe683bd4bb78188ac9936d208aebbc74c7f7c16b6a32ae2ebb38", size = 760699 },
{ url = "https://files.pythonhosted.org/packages/37/d7/7077f925d7d680d53dcb6e18a4af13d1a7da59761c06c193bfa249a7470a/nh3-0.2.20-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:231addb7643c952cd6d71f1c8702d703f8fe34afcb20becb3efb319a501a12d7", size = 747353 },
{ url = "https://files.pythonhosted.org/packages/cb/59/6b2f32af477aae81f1454a7f6ef490ebc3c22dd9e1370e73fcfe243dc07a/nh3-0.2.20-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1b9a8340a0aab991c68a5ca938d35ef4a8a3f4bf1b455da8855a40bee1fa0ace", size = 854125 },
{ url = "https://files.pythonhosted.org/packages/5b/f2/c3d2f7b801477b8b387b51fbefd16dc7ade888aeac547f18ba0558fd6f48/nh3-0.2.20-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10317cd96fe4bbd4eb6b95f3920b71c902157ad44fed103fdcde43e3b8ee8be6", size = 817453 },
{ url = "https://files.pythonhosted.org/packages/42/4d/f7e3a35506a0eba6eedafc21ad52773985511eb838812e9f96354831ad3c/nh3-0.2.20-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8698db4c04b140800d1a1cd3067fda399e36e1e2b8fc1fe04292a907350a3e9b", size = 891694 },
{ url = "https://files.pythonhosted.org/packages/e6/0e/c499453c296fb40366e3069cd68fde77a10f0a30a17b9d3b491eb3ebc5bf/nh3-0.2.20-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3eb04b9c3deb13c3a375ea39fd4a3c00d1f92e8fb2349f25f1e3e4506751774b", size = 744388 },
{ url = "https://files.pythonhosted.org/packages/18/67/c3de8022ba2719bdbbdd3704d1e32dbc7d3f8ac8646247711645fc90d051/nh3-0.2.20-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92f3f1c4f47a2c6f3ca7317b1d5ced05bd29556a75d3a4e2715652ae9d15c05d", size = 764831 },
{ url = "https://files.pythonhosted.org/packages/f0/14/a4ea40e2439717d11c3104fc2dc0ac412301b7aeb81d6a3d0e6505c77e7d/nh3-0.2.20-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ddefa9fd6794a87e37d05827d299d4b53a3ec6f23258101907b96029bfef138a", size = 923334 },
{ url = "https://files.pythonhosted.org/packages/ed/ae/e8ee8afaf67903dd304f390056d1ea620327524e2ad66127a331b14d5d98/nh3-0.2.20-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:ce3731c8f217685d33d9268362e5b4f770914e922bba94d368ab244a59a6c397", size = 994873 },
{ url = "https://files.pythonhosted.org/packages/20/b5/02122cfe3b36cf0ba0fcd73a04fd462e1f7a9d91b456f6e0b70e46df21c7/nh3-0.2.20-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:09f037c02fc2c43b211ff1523de32801dcfb0918648d8e651c36ef890f1731ec", size = 915707 },
{ url = "https://files.pythonhosted.org/packages/47/d3/5df43cc3570cdc9eb1dc79a39191f89fedf8bcefd8d30a161ff1dffb146c/nh3-0.2.20-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:813f1c8012dd64c990514b795508abb90789334f76a561fa0fd4ca32d2275330", size = 908539 },
{ url = "https://files.pythonhosted.org/packages/4f/fd/aa000f6c76a832c488eac26f20d2e8a221ba2b965efce692f14ebc4290bf/nh3-0.2.20-cp38-abi3-win32.whl", hash = "sha256:47b2946c0e13057855209daeffb45dc910bd0c55daf10190bb0b4b60e2999784", size = 540439 },
{ url = "https://files.pythonhosted.org/packages/19/31/d65594efd3b42b1de2335d576eb77525691fc320dbf8617948ee05c008e5/nh3-0.2.20-cp38-abi3-win_amd64.whl", hash = "sha256:da87573f03084edae8eb87cfe811ec338606288f81d333c07d2a9a0b9b976c0b", size = 541249 },
{ url = "https://files.pythonhosted.org/packages/3c/65/d31d93b6d1e5fe80d0cc18f0b96eaa561edfa0a15a6ef6b0fce50202a931/nh3-0.2.20-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e1061a4ab6681f6bdf72b110eea0c4e1379d57c9de937db3be4202f7ad6043db", size = 1202187, upload-time = "2024-12-17T12:49:28.903Z" },
{ url = "https://files.pythonhosted.org/packages/b4/ae/5b03bf198e06921454012e4b9a51e676d26fd37d9fdc1f29371a0b380487/nh3-0.2.20-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb4254b1dac4a1ee49919a5b3f1caf9803ea8dada1816d9e8289e63d3cd0dd9a", size = 737822, upload-time = "2024-12-17T12:49:30.42Z" },
{ url = "https://files.pythonhosted.org/packages/0a/53/a12dffb6ee3772deba82eb5997667fc835afd2e813d1f4080d8738f29eec/nh3-0.2.20-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ae9cbd713524cdb81e64663d0d6aae26f678db9f2cd9db0bf162606f1f9f20c", size = 756643, upload-time = "2024-12-17T12:49:31.767Z" },
{ url = "https://files.pythonhosted.org/packages/d0/0c/6cd2c5ac3e6e31f2a28721e8e2a924cb6b05ad054bf787bd1816ffd40b96/nh3-0.2.20-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e1f7370b4e14cc03f5ae141ef30a1caf81fa5787711f80be9081418dd9eb79d2", size = 923415, upload-time = "2024-12-17T12:49:34.434Z" },
{ url = "https://files.pythonhosted.org/packages/64/f0/229a6c8b81b86ba22d8e7f27ade62cb2fcfb987e570f49944fdd8490a76a/nh3-0.2.20-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:ac4d27dc836a476efffc6eb661994426b8b805c951b29c9cf2ff36bc9ad58bc5", size = 994959, upload-time = "2024-12-17T12:49:37.357Z" },
{ url = "https://files.pythonhosted.org/packages/75/e3/62ae3d3b658739ee15b129356fe6d4c4bc8ab235d7bf2e0d2794d64f7bc6/nh3-0.2.20-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4fd2e9248725ebcedac3997a8d3da0d90a12a28c9179c6ba51f1658938ac30d0", size = 915777, upload-time = "2024-12-17T12:49:40.012Z" },
{ url = "https://files.pythonhosted.org/packages/45/bd/8405d03371e335f02eb72e09dcf73307f8fd3095e4165cec6836346fe3db/nh3-0.2.20-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f7d564871833ddbe54df3aa59053b1110729d3a800cb7628ae8f42adb3d75208", size = 908614, upload-time = "2024-12-17T12:49:42.895Z" },
{ url = "https://files.pythonhosted.org/packages/ee/f8/5d977f09cf82c1f22a864375f471db111530fc79c88efdf0659fe6d3d6bc/nh3-0.2.20-cp313-cp313t-win32.whl", hash = "sha256:d2a176fd4306b6f0f178a3f67fac91bd97a3a8d8fafb771c9b9ef675ba5c8886", size = 540482, upload-time = "2024-12-17T12:49:45.42Z" },
{ url = "https://files.pythonhosted.org/packages/c5/f4/e34afe5fd8bed1920eac2974c9c853f548b4b65c139444285ffd2a68495d/nh3-0.2.20-cp313-cp313t-win_amd64.whl", hash = "sha256:6ed834c68452a600f517dd3e1534dbfaff1f67f98899fecf139a055a25d99150", size = 541302, upload-time = "2024-12-17T12:49:48.049Z" },
{ url = "https://files.pythonhosted.org/packages/92/08/5e3b61eed1bc0efeb330ddc5cf5194f28a0b7be7943aa20bd44cfe14650b/nh3-0.2.20-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:76e2f603b30c02ff6456b233a83fc377dedab6a50947b04e960a6b905637b776", size = 1202141, upload-time = "2024-12-17T12:49:50.601Z" },
{ url = "https://files.pythonhosted.org/packages/29/d2/3377f8006c71e95e007b07b5bfcac22c9de4744ca3efb23b396d3deb9581/nh3-0.2.20-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:181063c581defe683bd4bb78188ac9936d208aebbc74c7f7c16b6a32ae2ebb38", size = 760699, upload-time = "2024-12-17T12:49:52.833Z" },
{ url = "https://files.pythonhosted.org/packages/37/d7/7077f925d7d680d53dcb6e18a4af13d1a7da59761c06c193bfa249a7470a/nh3-0.2.20-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:231addb7643c952cd6d71f1c8702d703f8fe34afcb20becb3efb319a501a12d7", size = 747353, upload-time = "2024-12-17T12:49:54.23Z" },
{ url = "https://files.pythonhosted.org/packages/cb/59/6b2f32af477aae81f1454a7f6ef490ebc3c22dd9e1370e73fcfe243dc07a/nh3-0.2.20-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1b9a8340a0aab991c68a5ca938d35ef4a8a3f4bf1b455da8855a40bee1fa0ace", size = 854125, upload-time = "2024-12-17T12:49:55.481Z" },
{ url = "https://files.pythonhosted.org/packages/5b/f2/c3d2f7b801477b8b387b51fbefd16dc7ade888aeac547f18ba0558fd6f48/nh3-0.2.20-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10317cd96fe4bbd4eb6b95f3920b71c902157ad44fed103fdcde43e3b8ee8be6", size = 817453, upload-time = "2024-12-17T12:49:58.101Z" },
{ url = "https://files.pythonhosted.org/packages/42/4d/f7e3a35506a0eba6eedafc21ad52773985511eb838812e9f96354831ad3c/nh3-0.2.20-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8698db4c04b140800d1a1cd3067fda399e36e1e2b8fc1fe04292a907350a3e9b", size = 891694, upload-time = "2024-12-17T12:49:59.91Z" },
{ url = "https://files.pythonhosted.org/packages/e6/0e/c499453c296fb40366e3069cd68fde77a10f0a30a17b9d3b491eb3ebc5bf/nh3-0.2.20-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3eb04b9c3deb13c3a375ea39fd4a3c00d1f92e8fb2349f25f1e3e4506751774b", size = 744388, upload-time = "2024-12-17T12:50:02.656Z" },
{ url = "https://files.pythonhosted.org/packages/18/67/c3de8022ba2719bdbbdd3704d1e32dbc7d3f8ac8646247711645fc90d051/nh3-0.2.20-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92f3f1c4f47a2c6f3ca7317b1d5ced05bd29556a75d3a4e2715652ae9d15c05d", size = 764831, upload-time = "2024-12-17T12:50:05.09Z" },
{ url = "https://files.pythonhosted.org/packages/f0/14/a4ea40e2439717d11c3104fc2dc0ac412301b7aeb81d6a3d0e6505c77e7d/nh3-0.2.20-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ddefa9fd6794a87e37d05827d299d4b53a3ec6f23258101907b96029bfef138a", size = 923334, upload-time = "2024-12-17T12:50:06.666Z" },
{ url = "https://files.pythonhosted.org/packages/ed/ae/e8ee8afaf67903dd304f390056d1ea620327524e2ad66127a331b14d5d98/nh3-0.2.20-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:ce3731c8f217685d33d9268362e5b4f770914e922bba94d368ab244a59a6c397", size = 994873, upload-time = "2024-12-17T12:50:08.159Z" },
{ url = "https://files.pythonhosted.org/packages/20/b5/02122cfe3b36cf0ba0fcd73a04fd462e1f7a9d91b456f6e0b70e46df21c7/nh3-0.2.20-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:09f037c02fc2c43b211ff1523de32801dcfb0918648d8e651c36ef890f1731ec", size = 915707, upload-time = "2024-12-17T12:50:12.178Z" },
{ url = "https://files.pythonhosted.org/packages/47/d3/5df43cc3570cdc9eb1dc79a39191f89fedf8bcefd8d30a161ff1dffb146c/nh3-0.2.20-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:813f1c8012dd64c990514b795508abb90789334f76a561fa0fd4ca32d2275330", size = 908539, upload-time = "2024-12-17T12:50:16.172Z" },
{ url = "https://files.pythonhosted.org/packages/4f/fd/aa000f6c76a832c488eac26f20d2e8a221ba2b965efce692f14ebc4290bf/nh3-0.2.20-cp38-abi3-win32.whl", hash = "sha256:47b2946c0e13057855209daeffb45dc910bd0c55daf10190bb0b4b60e2999784", size = 540439, upload-time = "2024-12-17T12:50:18.694Z" },
{ url = "https://files.pythonhosted.org/packages/19/31/d65594efd3b42b1de2335d576eb77525691fc320dbf8617948ee05c008e5/nh3-0.2.20-cp38-abi3-win_amd64.whl", hash = "sha256:da87573f03084edae8eb87cfe811ec338606288f81d333c07d2a9a0b9b976c0b", size = 541249, upload-time = "2024-12-17T12:50:20.004Z" },
]
[[package]]
name = "odoorpc"
version = "0.10.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/cf/0a/9f907fbfefd2486bb4a3faab03f094f03b300b413004f348a3583ecc1898/OdooRPC-0.10.1.tar.gz", hash = "sha256:d0bc524c5b960781165575bad9c13d032d6f968c3c09276271045ddbbb483aa5", size = 58086 }
sdist = { url = "https://files.pythonhosted.org/packages/cf/0a/9f907fbfefd2486bb4a3faab03f094f03b300b413004f348a3583ecc1898/OdooRPC-0.10.1.tar.gz", hash = "sha256:d0bc524c5b960781165575bad9c13d032d6f968c3c09276271045ddbbb483aa5", size = 58086, upload-time = "2023-08-16T09:13:42.346Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/20/60/8c5ea2a63151d6c1215e127909eeee3c16e792bbae92ab596dd921d6669d/OdooRPC-0.10.1-py2.py3-none-any.whl", hash = "sha256:a0900bdd5c989c414b1ef40dafccd9363f179312d9166d9486cf70c7c2f0dd44", size = 38482 },
{ url = "https://files.pythonhosted.org/packages/20/60/8c5ea2a63151d6c1215e127909eeee3c16e792bbae92ab596dd921d6669d/OdooRPC-0.10.1-py2.py3-none-any.whl", hash = "sha256:a0900bdd5c989c414b1ef40dafccd9363f179312d9166d9486cf70c7c2f0dd44", size = 38482, upload-time = "2023-08-16T09:13:40.8Z" },
]
[[package]]
name = "packaging"
version = "24.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 }
sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950, upload-time = "2024-11-08T09:47:47.202Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 },
{ url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" },
]
[[package]]
name = "pillow"
version = "11.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f3/af/c097e544e7bd278333db77933e535098c259609c4eb3b85381109602fb5b/pillow-11.1.0.tar.gz", hash = "sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20", size = 46742715 }
sdist = { url = "https://files.pythonhosted.org/packages/f3/af/c097e544e7bd278333db77933e535098c259609c4eb3b85381109602fb5b/pillow-11.1.0.tar.gz", hash = "sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20", size = 46742715, upload-time = "2025-01-02T08:13:58.407Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b3/31/9ca79cafdce364fd5c980cd3416c20ce1bebd235b470d262f9d24d810184/pillow-11.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ae98e14432d458fc3de11a77ccb3ae65ddce70f730e7c76140653048c71bfcbc", size = 3226640 },
{ url = "https://files.pythonhosted.org/packages/ac/0f/ff07ad45a1f172a497aa393b13a9d81a32e1477ef0e869d030e3c1532521/pillow-11.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cc1331b6d5a6e144aeb5e626f4375f5b7ae9934ba620c0ac6b3e43d5e683a0f0", size = 3101437 },
{ url = "https://files.pythonhosted.org/packages/08/2f/9906fca87a68d29ec4530be1f893149e0cb64a86d1f9f70a7cfcdfe8ae44/pillow-11.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:758e9d4ef15d3560214cddbc97b8ef3ef86ce04d62ddac17ad39ba87e89bd3b1", size = 4326605 },
{ url = "https://files.pythonhosted.org/packages/b0/0f/f3547ee15b145bc5c8b336401b2d4c9d9da67da9dcb572d7c0d4103d2c69/pillow-11.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b523466b1a31d0dcef7c5be1f20b942919b62fd6e9a9be199d035509cbefc0ec", size = 4411173 },
{ url = "https://files.pythonhosted.org/packages/b1/df/bf8176aa5db515c5de584c5e00df9bab0713548fd780c82a86cba2c2fedb/pillow-11.1.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:9044b5e4f7083f209c4e35aa5dd54b1dd5b112b108648f5c902ad586d4f945c5", size = 4369145 },
{ url = "https://files.pythonhosted.org/packages/de/7c/7433122d1cfadc740f577cb55526fdc39129a648ac65ce64db2eb7209277/pillow-11.1.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:3764d53e09cdedd91bee65c2527815d315c6b90d7b8b79759cc48d7bf5d4f114", size = 4496340 },
{ url = "https://files.pythonhosted.org/packages/25/46/dd94b93ca6bd555588835f2504bd90c00d5438fe131cf01cfa0c5131a19d/pillow-11.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:31eba6bbdd27dde97b0174ddf0297d7a9c3a507a8a1480e1e60ef914fe23d352", size = 4296906 },
{ url = "https://files.pythonhosted.org/packages/a8/28/2f9d32014dfc7753e586db9add35b8a41b7a3b46540e965cb6d6bc607bd2/pillow-11.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b5d658fbd9f0d6eea113aea286b21d3cd4d3fd978157cbf2447a6035916506d3", size = 4431759 },
{ url = "https://files.pythonhosted.org/packages/33/48/19c2cbe7403870fbe8b7737d19eb013f46299cdfe4501573367f6396c775/pillow-11.1.0-cp313-cp313-win32.whl", hash = "sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9", size = 2291657 },
{ url = "https://files.pythonhosted.org/packages/3b/ad/285c556747d34c399f332ba7c1a595ba245796ef3e22eae190f5364bb62b/pillow-11.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:593c5fd6be85da83656b93ffcccc2312d2d149d251e98588b14fbc288fd8909c", size = 2626304 },
{ url = "https://files.pythonhosted.org/packages/e5/7b/ef35a71163bf36db06e9c8729608f78dedf032fc8313d19bd4be5c2588f3/pillow-11.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:11633d58b6ee5733bde153a8dafd25e505ea3d32e261accd388827ee987baf65", size = 2375117 },
{ url = "https://files.pythonhosted.org/packages/79/30/77f54228401e84d6791354888549b45824ab0ffde659bafa67956303a09f/pillow-11.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:70ca5ef3b3b1c4a0812b5c63c57c23b63e53bc38e758b37a951e5bc466449861", size = 3230060 },
{ url = "https://files.pythonhosted.org/packages/ce/b1/56723b74b07dd64c1010fee011951ea9c35a43d8020acd03111f14298225/pillow-11.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8000376f139d4d38d6851eb149b321a52bb8893a88dae8ee7d95840431977081", size = 3106192 },
{ url = "https://files.pythonhosted.org/packages/e1/cd/7bf7180e08f80a4dcc6b4c3a0aa9e0b0ae57168562726a05dc8aa8fa66b0/pillow-11.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ee85f0696a17dd28fbcfceb59f9510aa71934b483d1f5601d1030c3c8304f3c", size = 4446805 },
{ url = "https://files.pythonhosted.org/packages/97/42/87c856ea30c8ed97e8efbe672b58c8304dee0573f8c7cab62ae9e31db6ae/pillow-11.1.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:dd0e081319328928531df7a0e63621caf67652c8464303fd102141b785ef9547", size = 4530623 },
{ url = "https://files.pythonhosted.org/packages/ff/41/026879e90c84a88e33fb00cc6bd915ac2743c67e87a18f80270dfe3c2041/pillow-11.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e63e4e5081de46517099dc30abe418122f54531a6ae2ebc8680bcd7096860eab", size = 4465191 },
{ url = "https://files.pythonhosted.org/packages/e5/fb/a7960e838bc5df57a2ce23183bfd2290d97c33028b96bde332a9057834d3/pillow-11.1.0-cp313-cp313t-win32.whl", hash = "sha256:dda60aa465b861324e65a78c9f5cf0f4bc713e4309f83bc387be158b077963d9", size = 2295494 },
{ url = "https://files.pythonhosted.org/packages/d7/6c/6ec83ee2f6f0fda8d4cf89045c6be4b0373ebfc363ba8538f8c999f63fcd/pillow-11.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ad5db5781c774ab9a9b2c4302bbf0c1014960a0a7be63278d13ae6fdf88126fe", size = 2631595 },
{ url = "https://files.pythonhosted.org/packages/cf/6c/41c21c6c8af92b9fea313aa47c75de49e2f9a467964ee33eb0135d47eb64/pillow-11.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:67cd427c68926108778a9005f2a04adbd5e67c442ed21d95389fe1d595458756", size = 2377651 },
{ url = "https://files.pythonhosted.org/packages/b3/31/9ca79cafdce364fd5c980cd3416c20ce1bebd235b470d262f9d24d810184/pillow-11.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ae98e14432d458fc3de11a77ccb3ae65ddce70f730e7c76140653048c71bfcbc", size = 3226640, upload-time = "2025-01-02T08:11:58.329Z" },
{ url = "https://files.pythonhosted.org/packages/ac/0f/ff07ad45a1f172a497aa393b13a9d81a32e1477ef0e869d030e3c1532521/pillow-11.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cc1331b6d5a6e144aeb5e626f4375f5b7ae9934ba620c0ac6b3e43d5e683a0f0", size = 3101437, upload-time = "2025-01-02T08:12:01.797Z" },
{ url = "https://files.pythonhosted.org/packages/08/2f/9906fca87a68d29ec4530be1f893149e0cb64a86d1f9f70a7cfcdfe8ae44/pillow-11.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:758e9d4ef15d3560214cddbc97b8ef3ef86ce04d62ddac17ad39ba87e89bd3b1", size = 4326605, upload-time = "2025-01-02T08:12:05.224Z" },
{ url = "https://files.pythonhosted.org/packages/b0/0f/f3547ee15b145bc5c8b336401b2d4c9d9da67da9dcb572d7c0d4103d2c69/pillow-11.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b523466b1a31d0dcef7c5be1f20b942919b62fd6e9a9be199d035509cbefc0ec", size = 4411173, upload-time = "2025-01-02T08:12:08.281Z" },
{ url = "https://files.pythonhosted.org/packages/b1/df/bf8176aa5db515c5de584c5e00df9bab0713548fd780c82a86cba2c2fedb/pillow-11.1.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:9044b5e4f7083f209c4e35aa5dd54b1dd5b112b108648f5c902ad586d4f945c5", size = 4369145, upload-time = "2025-01-02T08:12:11.411Z" },
{ url = "https://files.pythonhosted.org/packages/de/7c/7433122d1cfadc740f577cb55526fdc39129a648ac65ce64db2eb7209277/pillow-11.1.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:3764d53e09cdedd91bee65c2527815d315c6b90d7b8b79759cc48d7bf5d4f114", size = 4496340, upload-time = "2025-01-02T08:12:15.29Z" },
{ url = "https://files.pythonhosted.org/packages/25/46/dd94b93ca6bd555588835f2504bd90c00d5438fe131cf01cfa0c5131a19d/pillow-11.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:31eba6bbdd27dde97b0174ddf0297d7a9c3a507a8a1480e1e60ef914fe23d352", size = 4296906, upload-time = "2025-01-02T08:12:17.485Z" },
{ url = "https://files.pythonhosted.org/packages/a8/28/2f9d32014dfc7753e586db9add35b8a41b7a3b46540e965cb6d6bc607bd2/pillow-11.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b5d658fbd9f0d6eea113aea286b21d3cd4d3fd978157cbf2447a6035916506d3", size = 4431759, upload-time = "2025-01-02T08:12:20.382Z" },
{ url = "https://files.pythonhosted.org/packages/33/48/19c2cbe7403870fbe8b7737d19eb013f46299cdfe4501573367f6396c775/pillow-11.1.0-cp313-cp313-win32.whl", hash = "sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9", size = 2291657, upload-time = "2025-01-02T08:12:23.922Z" },
{ url = "https://files.pythonhosted.org/packages/3b/ad/285c556747d34c399f332ba7c1a595ba245796ef3e22eae190f5364bb62b/pillow-11.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:593c5fd6be85da83656b93ffcccc2312d2d149d251e98588b14fbc288fd8909c", size = 2626304, upload-time = "2025-01-02T08:12:28.069Z" },
{ url = "https://files.pythonhosted.org/packages/e5/7b/ef35a71163bf36db06e9c8729608f78dedf032fc8313d19bd4be5c2588f3/pillow-11.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:11633d58b6ee5733bde153a8dafd25e505ea3d32e261accd388827ee987baf65", size = 2375117, upload-time = "2025-01-02T08:12:30.064Z" },
{ url = "https://files.pythonhosted.org/packages/79/30/77f54228401e84d6791354888549b45824ab0ffde659bafa67956303a09f/pillow-11.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:70ca5ef3b3b1c4a0812b5c63c57c23b63e53bc38e758b37a951e5bc466449861", size = 3230060, upload-time = "2025-01-02T08:12:32.362Z" },
{ url = "https://files.pythonhosted.org/packages/ce/b1/56723b74b07dd64c1010fee011951ea9c35a43d8020acd03111f14298225/pillow-11.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8000376f139d4d38d6851eb149b321a52bb8893a88dae8ee7d95840431977081", size = 3106192, upload-time = "2025-01-02T08:12:34.361Z" },
{ url = "https://files.pythonhosted.org/packages/e1/cd/7bf7180e08f80a4dcc6b4c3a0aa9e0b0ae57168562726a05dc8aa8fa66b0/pillow-11.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ee85f0696a17dd28fbcfceb59f9510aa71934b483d1f5601d1030c3c8304f3c", size = 4446805, upload-time = "2025-01-02T08:12:36.99Z" },
{ url = "https://files.pythonhosted.org/packages/97/42/87c856ea30c8ed97e8efbe672b58c8304dee0573f8c7cab62ae9e31db6ae/pillow-11.1.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:dd0e081319328928531df7a0e63621caf67652c8464303fd102141b785ef9547", size = 4530623, upload-time = "2025-01-02T08:12:41.912Z" },
{ url = "https://files.pythonhosted.org/packages/ff/41/026879e90c84a88e33fb00cc6bd915ac2743c67e87a18f80270dfe3c2041/pillow-11.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e63e4e5081de46517099dc30abe418122f54531a6ae2ebc8680bcd7096860eab", size = 4465191, upload-time = "2025-01-02T08:12:45.186Z" },
{ url = "https://files.pythonhosted.org/packages/e5/fb/a7960e838bc5df57a2ce23183bfd2290d97c33028b96bde332a9057834d3/pillow-11.1.0-cp313-cp313t-win32.whl", hash = "sha256:dda60aa465b861324e65a78c9f5cf0f4bc713e4309f83bc387be158b077963d9", size = 2295494, upload-time = "2025-01-02T08:12:47.098Z" },
{ url = "https://files.pythonhosted.org/packages/d7/6c/6ec83ee2f6f0fda8d4cf89045c6be4b0373ebfc363ba8538f8c999f63fcd/pillow-11.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ad5db5781c774ab9a9b2c4302bbf0c1014960a0a7be63278d13ae6fdf88126fe", size = 2631595, upload-time = "2025-01-02T08:12:50.47Z" },
{ url = "https://files.pythonhosted.org/packages/cf/6c/41c21c6c8af92b9fea313aa47c75de49e2f9a467964ee33eb0135d47eb64/pillow-11.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:67cd427c68926108778a9005f2a04adbd5e67c442ed21d95389fe1d595458756", size = 2377651, upload-time = "2025-01-02T08:12:53.356Z" },
]
[[package]]
name = "python-dotenv"
version = "1.0.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115 }
sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115, upload-time = "2024-01-23T06:33:00.505Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 },
{ url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863, upload-time = "2024-01-23T06:32:58.246Z" },
]
[[package]]
name = "python-monkey-business"
version = "1.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/21/bc/a6182bb30701d0df25ad336f2dd74343447032e0995025ba82079a94f745/python-monkey-business-1.1.0.tar.gz", hash = "sha256:8393839cc741415ed5ddc2bd58e2d4ce07f966a7d26b7aebff19dcec64818edc", size = 4270 }
sdist = { url = "https://files.pythonhosted.org/packages/21/bc/a6182bb30701d0df25ad336f2dd74343447032e0995025ba82079a94f745/python-monkey-business-1.1.0.tar.gz", hash = "sha256:8393839cc741415ed5ddc2bd58e2d4ce07f966a7d26b7aebff19dcec64818edc", size = 4270, upload-time = "2024-07-11T16:35:00.117Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/43/a2/b6a5cbd5822b4d049adfedf496ce0908480e5a41722fda7b7ffaacb086d6/python_monkey_business-1.1.0-py2.py3-none-any.whl", hash = "sha256:15b4f603c749ba9a7b4f1acd36af023a6c5ba0f7e591c945f8253f0ef44bf389", size = 4670 },
{ url = "https://files.pythonhosted.org/packages/43/a2/b6a5cbd5822b4d049adfedf496ce0908480e5a41722fda7b7ffaacb086d6/python_monkey_business-1.1.0-py2.py3-none-any.whl", hash = "sha256:15b4f603c749ba9a7b4f1acd36af023a6c5ba0f7e591c945f8253f0ef44bf389", size = 4670, upload-time = "2024-07-11T16:34:58.565Z" },
]
[[package]]
@ -309,7 +309,7 @@ dev = [
[package.metadata]
requires-dist = [
{ name = "django", specifier = ">=5.1.5" },
{ name = "django", specifier = ">=5.2" },
{ name = "django-admin-sortable2", specifier = ">=2.2.4" },
{ name = "django-browser-reload", marker = "extra == 'dev'", specifier = "~=1.13" },
{ name = "django-jazzmin", specifier = ">=3.0.1" },
@ -327,25 +327,25 @@ provides-extras = ["dev"]
name = "sqlparse"
version = "0.5.3"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e5/40/edede8dd6977b0d3da179a342c198ed100dd2aba4be081861ee5911e4da4/sqlparse-0.5.3.tar.gz", hash = "sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272", size = 84999 }
sdist = { url = "https://files.pythonhosted.org/packages/e5/40/edede8dd6977b0d3da179a342c198ed100dd2aba4be081861ee5911e4da4/sqlparse-0.5.3.tar.gz", hash = "sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272", size = 84999, upload-time = "2024-12-10T12:05:30.728Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a9/5c/bfd6bd0bf979426d405cc6e71eceb8701b148b16c21d2dc3c261efc61c7b/sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca", size = 44415 },
{ url = "https://files.pythonhosted.org/packages/a9/5c/bfd6bd0bf979426d405cc6e71eceb8701b148b16c21d2dc3c261efc61c7b/sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca", size = 44415, upload-time = "2024-12-10T12:05:27.824Z" },
]
[[package]]
name = "typing-extensions"
version = "4.12.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 }
sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321, upload-time = "2024-06-07T18:52:15.995Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438, upload-time = "2024-06-07T18:52:13.582Z" },
]
[[package]]
name = "tzdata"
version = "2025.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/43/0f/fa4723f22942480be4ca9527bbde8d43f6c3f2fe8412f00e7f5f6746bc8b/tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694", size = 194950 }
sdist = { url = "https://files.pythonhosted.org/packages/43/0f/fa4723f22942480be4ca9527bbde8d43f6c3f2fe8412f00e7f5f6746bc8b/tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694", size = 194950, upload-time = "2025-01-21T19:49:38.686Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/0f/dd/84f10e23edd882c6f968c21c2434fe67bd4a528967067515feca9e611e5e/tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639", size = 346762 },
{ url = "https://files.pythonhosted.org/packages/0f/dd/84f10e23edd882c6f968c21c2434fe67bd4a528967067515feca9e611e5e/tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639", size = 346762, upload-time = "2025-01-21T19:49:37.187Z" },
]