Skip to main content

Django integration for Lark billing

Project description

django-lark

Django integration for Lark billing.

Installation

pip install django-lark

Quick Start

  1. Add django_lark to your INSTALLED_APPS:
INSTALLED_APPS = [
    ...
    'django_lark',
]
  1. Configure your Lark API key in settings.py:
LARK_API_KEY = "lark_api_..."

Or set the LARK_API_KEY environment variable.

  1. Include the URLs (optional, for customer portal):
urlpatterns = [
    ...
    path('billing/', include('django_lark.urls')),
]

Configuration

All settings are prefixed with LARK_:

Setting Default Description
LARK_API_KEY Required Your Lark API key
LARK_BASE_URL https://api.uselark.ai Lark API base URL
LARK_TIMEOUT 60.0 Request timeout in seconds
LARK_MAX_RETRIES 2 Max retry attempts
LARK_USER_SUBJECT_FIELD email User field to use as external_id
LARK_AUTO_CREATE_SUBJECTS False Auto-create Lark subjects for users

How It Works

django-lark uses Lark's external_id feature to identify users without maintaining a local database mapping. When you create a subject in Lark with an external_id, you can use that same external_id in any API call that accepts a subject_id.

By default, django-lark uses the user's email as the external_id. You can customize this with the LARK_USER_SUBJECT_FIELD setting:

# Use user's primary key
LARK_USER_SUBJECT_FIELD = "id"  # Results in "django_user_{pk}"

# Use email (default)
LARK_USER_SUBJECT_FIELD = "email"

# Use a custom field
LARK_USER_SUBJECT_FIELD = "uuid"

# Use a callable for full control
LARK_USER_SUBJECT_FIELD = lambda user: f"myapp_{user.organization_id}_{user.id}"

Usage

Client Access

from django_lark import get_lark_client, get_async_lark_client

# Sync
client = get_lark_client()
subjects = client.subjects.list()

# Async
async def my_view(request):
    client = get_async_lark_client()
    subjects = await client.subjects.list()

Get External ID for a User

from django_lark.utils import get_external_id_for_user

external_id = get_external_id_for_user(user)
# Use this external_id in any Lark API call

Create Lark Subjects for Users

from django_lark.utils import get_or_create_subject_for_user

# Get or create a Lark subject for a Django user
subject, created = get_or_create_subject_for_user(user)

Check Subscription Status

from django_lark.utils import get_billing_state_for_user

billing_state = get_billing_state_for_user(user)
if billing_state.has_active_subscription:
    print("User has active subscription!")

Create Subscriptions

from django_lark.utils import create_subscription_for_user

# Create a subscription and redirect to checkout
response = create_subscription_for_user(
    user,
    rate_card_id="rc_pro",
    success_url="https://example.com/welcome/",
    cancelled_url="https://example.com/pricing/",
)

# Check if checkout is required
if response.result.result_type == "requires_action":
    return redirect(response.result.action.checkout_url)
else:
    # Subscription created directly (e.g., free plan or payment method on file)
    subscription = response.result.subscription

# With fixed rate quantities (e.g., seat-based pricing)
subscription = create_subscription_for_user(
    user,
    rate_card_id="rc_team",
    fixed_rate_quantities={"seats": 5},
    success_url="https://example.com/welcome/",
)

# With price multipliers (e.g., discounts)
subscription = create_subscription_for_user(
    user,
    rate_card_id="rc_pro",
    rate_price_multipliers={"seats": 0.8},  # 20% discount
    success_url="https://example.com/welcome/",
)

Cancel Subscriptions

from django_lark.utils import cancel_subscription, cancel_subscription_for_user

# Cancel by subscription ID (no ownership check)
cancelled = cancel_subscription("sub_abc123")

# Cancel with ownership verification (recommended)
cancelled = cancel_subscription_for_user(user, "sub_abc123")

Change Rate Card (Upgrade/Downgrade)

from django_lark.utils import change_subscription_rate_card, change_subscription_rate_card_for_user

# Change rate card by subscription ID (no ownership check)
response = change_subscription_rate_card(
    "sub_abc123",
    rate_card_id="rc_enterprise",
    success_url="https://example.com/upgraded/",
    cancelled_url="https://example.com/plans/",
    upgrade_behavior="prorate",  # or "rate_difference"
)

# Change with ownership verification (recommended)
response = change_subscription_rate_card_for_user(
    user,
    "sub_abc123",
    rate_card_id="rc_enterprise",
    success_url="https://example.com/upgraded/",
)

# Check if checkout is required (e.g., for payment)
if response.result.type == "requires_action":
    return redirect(response.result.action.checkout_url)
else:
    # Rate card changed directly
    subscription = response.result.subscription

The upgrade_behavior parameter controls how charges are calculated:

  • "prorate" - Customer is charged for the prorated difference based on remaining time
  • "rate_difference" - Customer is charged the full difference between rate cards

View Decorators

from django_lark.decorators import subscription_required

@subscription_required()
def premium_view(request):
    return render(request, 'premium.html')

@subscription_required(rate_card_ids=['rc_pro', 'rc_enterprise'])
def pro_view(request):
    return render(request, 'pro.html')

@subscription_required(redirect_url='/pricing/')
def feature_view(request):
    return render(request, 'feature.html')

Template Tags

{% load lark_tags %}

{% has_active_subscription as is_subscribed %}
{% if is_subscribed %}
    <p>Welcome, premium member!</p>
{% else %}
    <a href="/pricing/">Upgrade now</a>
{% endif %}

{% has_subscription_to_rate_card "rc_pro" as has_pro %}
{% if has_pro %}
    <p>Pro features unlocked!</p>
{% endif %}

{% get_subscriptions as subscriptions %}
{% for sub in subscriptions %}
    <p>{{ sub.rate_card_id }} -
       <span class="badge {{ sub.status|lark_subscription_status_badge }}">
           {{ sub.status }}
       </span>
    </p>
{% endfor %}

{% get_lark_external_id as external_id %}

Customer Portal

Redirect users to the Lark customer portal:

<a href="{% url 'django_lark:customer_portal' %}?return_url={{ request.path }}">
    Manage Subscription
</a>

Checkout

Redirect users to Lark checkout to subscribe to a rate card:

{# Link-based checkout #}
<a href="{% url 'django_lark:checkout' %}?rate_card_id=rc_pro&success_url=/welcome/">
    Subscribe to Pro
</a>

{# Form-based checkout #}
<form method="post" action="{% url 'django_lark:checkout' %}">
    {% csrf_token %}
    <input type="hidden" name="rate_card_id" value="rc_pro">
    <input type="hidden" name="success_url" value="/welcome/">
    <input type="hidden" name="cancelled_url" value="/pricing/">
    <button type="submit">Subscribe</button>
</form>

Change Rate Card

Upgrade or downgrade a user's subscription to a different rate card:

{# Link-based upgrade #}
<a href="{% url 'django_lark:change_rate_card' %}?subscription_id={{ subscription.id }}&rate_card_id=rc_enterprise&success_url=/upgraded/">
    Upgrade to Enterprise
</a>

{# Form-based upgrade with proration #}
<form method="post" action="{% url 'django_lark:change_rate_card' %}">
    {% csrf_token %}
    <input type="hidden" name="subscription_id" value="{{ subscription.id }}">
    <input type="hidden" name="rate_card_id" value="rc_enterprise">
    <input type="hidden" name="success_url" value="/upgraded/">
    <input type="hidden" name="cancelled_url" value="/plans/">
    <input type="hidden" name="upgrade_behavior" value="prorate">
    <button type="submit">Upgrade Plan</button>
</form>

License

MIT

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

django_lark-0.2.0.tar.gz (20.7 kB view details)

Uploaded Source

Built Distribution

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

django_lark-0.2.0-py3-none-any.whl (16.2 kB view details)

Uploaded Python 3

File details

Details for the file django_lark-0.2.0.tar.gz.

File metadata

  • Download URL: django_lark-0.2.0.tar.gz
  • Upload date:
  • Size: 20.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for django_lark-0.2.0.tar.gz
Algorithm Hash digest
SHA256 3567da2ec86ed1408a828cf7dcf931ab7484a1ac7a999a9224a26d8b9bf63b74
MD5 ccf995ac4094b70fa1b15c1d9080cee3
BLAKE2b-256 162067e9b24dc82e0b535364d0a163e9ecaa954c6ea5d66b9fdedf3c05219765

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_lark-0.2.0.tar.gz:

Publisher: publish.yml on uselark/django-lark

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file django_lark-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: django_lark-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 16.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for django_lark-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3f5004ab5d858af9c32bf4f5f76b2b3108b15c5a1f66881005eeabf47f3eb661
MD5 f5e5526bfd8d8b8f10133dc23e670886
BLAKE2b-256 94f549d0c802563a6a6899d9b4567453c1b27c9b6ff75387543470e42584ae25

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_lark-0.2.0-py3-none-any.whl:

Publisher: publish.yml on uselark/django-lark

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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