django-googler


Namedjango-googler JSON
Version 0.0.16 PyPI version JSON
download
home_pageNone
SummaryDjango Googler is a simple way to integrate Google Auth Platform with your Django project.
upload_time2025-10-20 06:13:47
maintainerNone
docs_urlNone
authorNone
requires_python>=3.12
licenseNone
keywords auth django djangorestframework google oauth oauth2 oauthlib
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Django Googler

Simple Google OAuth authentication for Django. Returns JWT tokens for your API.

## What It Does

1. User clicks "Sign in with Google"
2. Google handles authentication
3. Your Django app gets JWT tokens + user info
4. Use JWT tokens for authenticated API requests

## Installation

```bash
uv add django-googler
```

or

```bash
pip install django-googler
```

## Quick Setup

### 1. Add to `settings.py`

```python
INSTALLED_APPS = [
    # ...
    "rest_framework",
    "rest_framework_simplejwt",
    "rest_framework_simplejwt.token_blacklist",  # Optional: for logout
    "django_googler",
]

# Get these from Google Cloud Console
GOOGLE_OAUTH_CLIENT_ID = "your-client-id"
GOOGLE_OAUTH_CLIENT_SECRET = "your-client-secret"
```

### 2. Add URLs

```python
# urls.py
from django.urls import path, include

urlpatterns = [
    # Django Rest Framework OAuth API views
    path("api/auth/", include("django_googler.urls.drf")),
    # Standard Django OAuth views (non django rest framework)
    path("auth/", include("django_googler.urls.default")),
]
```

### 3. Run Migrations

```bash
python manage.py migrate
```

Done! You now have these endpoints:
- `GET /api/auth/google/login/` - Get Google OAuth URL
- `POST /api/auth/google/callback/` - Exchange code for JWT tokens
- `GET /api/auth/me/` - Get current user (requires JWT)
- `POST /api/auth/logout/` - Logout (requires JWT)

You can also use the Django views directly:
- `GET /auth/google/login/` - To automatically start Google OAuth which will automatically redirect you to `/auth/google/callback/`
- `GET /auth/google/callback/` - To handle Google's callback
- To `logout` you'll use a standard Django logout view or logout method to end the User's session

## Usage

### API Examples:

```bash
curl http://localhost:8000/api/auth/google/login/
```
Yields:

```json
{
  "authorization_url": "https://accounts.google.com/...",
  "state": "..."
}
```
Opening `authorization_url` in a new tab will start the Google OAuth flow and automatically redirect you to `/api/auth/google/callback/`. If you set `DJANGO_GOOGLER_ALLOW_GET_ON_DRF_CALLBACK = True` in `settings.py`, your automatic redirect to `/api/auth/googler/callback/` will automatically provider your auth tokens in the response such as:

```json
{
  "access": "eyJ0eXAiOiJKV1Q...",  // JWT access token (short-lived)
  "refresh": "eyJ0eXAiOiJKV1Q...", // JWT refresh token (long-lived)
  "user": {
    "id": 1,
    "email": "user@example.com",
    "username": "user",
    "first_name": "John",
    "last_name": "Doe"
  }
}
```

From here you can do an authenticated request to `/api/auth/me/` to get the user's information:
```bash
curl http://localhost:8000/api/auth/me/ \
  -H "Authorization: Bearer <access_token>"
```

To refresh the access token, you can use the `/api/auth/google/refresh/` endpoint:
```bash
curl -X POST http://localhost:8000/api/auth/google/refresh/ \
  -H "Content-Type: application/json" \
  -d '{"refresh": "<refresh_token>"}'
```
This is a standard JWT refresh endpoint provided by [rest_framework_simplejwt](https://django-rest-framework-simplejwt.readthedocs.io/) with `TokenRefreshView`.

### Frontend Flow

**1. Get Google OAuth URL**

```javascript
const redirect_uri = 'http://localhost:3000/auth/callback';
const apiBaseUrl = 'http://localhost:8000';
const loginApiEndpoint = `${apiBaseUrl}/api/auth/google/login/`;
const requestUrl = `${loginApiEndpoint}?redirect_uri=${redirect_uri}`;
const response = await fetch(requestUrl);
const data = await response.json();
// data = { "authorization_url": "https://accounts.google.com/...", "state": "..." }

// Redirect user to Google
window.location.href = data.authorization_url;
```

**2. Handle Google's Callback**

After Google redirects back to your frontend with a `code` and `state`:

```javascript
// Get the callback data from the current URL
const currentUrl = new URL(window.location.href);
const googleCallbackData = Object.fromEntries(currentUrl.searchParams);

// Send the callback data to the backend
const apiBaseUrl = 'http://localhost:8000';
const callbackApiEndpoint = `${apiBaseUrl}/api/auth/google/callback/`;
const response = await fetch(callbackApiEndpoint, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(googleCallbackData)
});

const responseData = await response.json();
/* responseData = {
  "access": "eyJ0eXAiOiJKV1Q...",  // JWT access token (short-lived)
  "refresh": "eyJ0eXAiOiJKV1Q...", // JWT refresh token (long-lived)
  "user": {
    "id": 1,
    "email": "user@example.com",
    "username": "user",
    "first_name": "John",
    "last_name": "Doe"
  }
} */

// Save tokens
localStorage.setItem('access_token', responseData.access);
localStorage.setItem('refresh_token', responseData.refresh);
```

**3. Make Authenticated Requests**

```javascript
const apiBaseUrl = 'http://localhost:8000';
const meApiEndpoint = `${apiBaseUrl}/api/auth/me/`;
const response = await fetch(meApiEndpoint, {
  headers: {
    'Authorization': `Bearer ${localStorage.getItem('access_token')}`
  }
});

const responseData = await response.json();
/* responseData = {
  "id": 1,
  "email": "user@example.com",
  "username": "user",
  "first_name": "John",
  "last_name": "Doe"
} */
```

**4. Logout**

```javascript
const apiBaseUrl = 'http://localhost:8000';
const logoutApiEndpoint = `${apiBaseUrl}/api/auth/logout/`;
const response = await fetch(logoutApiEndpoint, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${localStorage.getItem('access_token')}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    refresh: localStorage.getItem('refresh_token')
  })
});

localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
```

## Configuration

### Required Settings

```python
GOOGLE_OAUTH_CLIENT_ID = "your-client-id"
GOOGLE_OAUTH_CLIENT_SECRET = "your-client-secret"
```

### Optional Settings

```python
# Return Google tokens in callback response (for calling Google APIs from frontend)
# Default: False
GOOGLE_OAUTH_RETURN_TOKENS = False

# Revoke Google access on logout
# Default: False
GOOGLE_OAUTH_REVOKE_ON_LOGOUT = False

# Save Google OAuth tokens to database (for backend Google API calls)
# Default: True
GOOGLE_OAUTH_SAVE_TOKENS_TO_DB = True

# Request additional Google API scopes
# Default: ["openid", "email", "profile"]
GOOGLE_OAUTH_SCOPES = [
    "openid",
    "https://www.googleapis.com/auth/userinfo.email",
    "https://www.googleapis.com/auth/userinfo.profile",
    # "https://www.googleapis.com/auth/calendar",  # Add if needed
]
```

## Google Cloud Setup

For Development:
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create a project
3. Go to **Google Auth Platform**
4. Navigate to **Clients** > **+Create Client**

For Development use:

- **Application type**: Web application
- **Name**: Django Googler Dev
- **Authorized redirect URIs**:
  - `http://localhost:8000/api/auth/google/callback/`
  - `http://localhost:8000/auth/google/callback/` (frontend handler for Django-based frontend)
  - `http://localhost:3000/auth/google/callback/` (frontend handler for React, Next.js or Vue)
  - Any others you might need during development

For Production use:

- **Application type**: Web application
- **Name**: Django Googler Prod
- **Redirect URIs**:
  - `https://yourdomain.com/api/auth/google/callback/`
  - `https://yourdomain.com/auth/google/callback/` (frontend handler for Django or Next.js/React/Vue frontend)
  - Any others you might need (adding more is fine especially if you have multiple frontend frameworks)

After you configure it, click **Create** and for _each environment_ (prod/dev) grab:

- **Client ID** (such as `django-googler-dev.apps.googleusercontent.com` and `django-googler-prod.apps.googleusercontent.com`)
- **Client Secret**

For dev, update your `.env` file with:

```bash
GOOGLE_OAUTH_CLIENT_ID=django-googler-dev.apps.googleusercontent.com
GOOGLE_OAUTH_CLIENT_SECRET=your-dev-client-secret
```

For prod, update your runtime secrets with:

```bash
GOOGLE_OAUTH_CLIENT_ID=django-googler-prod.apps.googleusercontent.com
GOOGLE_OAUTH_CLIENT_SECRET=your-prod-client-secret
```

## Making Google API Calls

If your backend needs to call Google APIs on behalf of users:

```python
from django_googler.services import GoogleOAuthService


def my_view(request):
    # Get valid access token (auto-refreshes if expired)
    access_token, expiry = GoogleOAuthService.get_valid_token(request.user)

    if access_token:
        import requests

        headers = {"Authorization": f"Bearer {access_token}"}
        response = requests.get(
            "https://www.googleapis.com/calendar/v3/calendars/primary/events",
            headers=headers,
        )
        return response.json()
```

## Using Django Views (Instead of API)

If you prefer browser redirects over API calls:

```python
# urls.py
urlpatterns = [
    path("auth/", include("django_googler.urls.default")),
]
```

Then in your template:
```html
<a href="{% url 'django_googler:google-login' %}?next=/dashboard/">
    Sign in with Google
</a>
```

Users will be redirected to Google and back, then logged into Django's session.

## Architecture

- **Views** - Handle OAuth flow and return JWT tokens
- **Services** - Business logic for OAuth, users, and tokens
- **Models** - Store Google OAuth tokens in database

## License

MIT License

## Support

[GitHub Issues](https://github.com/jmitchel3/django-googler/issues)

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "django-googler",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": null,
    "keywords": "auth, django, djangorestframework, google, oauth, oauth2, oauthlib",
    "author": null,
    "author_email": "Justin Mitchel <justin@codingforentrepreneurs.com>",
    "download_url": "https://files.pythonhosted.org/packages/7f/17/828ad2aa3c6236a28c5e5f0dced2abaf70f8e6ebba613b72428c113da21e/django_googler-0.0.16.tar.gz",
    "platform": null,
    "description": "# Django Googler\n\nSimple Google OAuth authentication for Django. Returns JWT tokens for your API.\n\n## What It Does\n\n1. User clicks \"Sign in with Google\"\n2. Google handles authentication\n3. Your Django app gets JWT tokens + user info\n4. Use JWT tokens for authenticated API requests\n\n## Installation\n\n```bash\nuv add django-googler\n```\n\nor\n\n```bash\npip install django-googler\n```\n\n## Quick Setup\n\n### 1. Add to `settings.py`\n\n```python\nINSTALLED_APPS = [\n    # ...\n    \"rest_framework\",\n    \"rest_framework_simplejwt\",\n    \"rest_framework_simplejwt.token_blacklist\",  # Optional: for logout\n    \"django_googler\",\n]\n\n# Get these from Google Cloud Console\nGOOGLE_OAUTH_CLIENT_ID = \"your-client-id\"\nGOOGLE_OAUTH_CLIENT_SECRET = \"your-client-secret\"\n```\n\n### 2. Add URLs\n\n```python\n# urls.py\nfrom django.urls import path, include\n\nurlpatterns = [\n    # Django Rest Framework OAuth API views\n    path(\"api/auth/\", include(\"django_googler.urls.drf\")),\n    # Standard Django OAuth views (non django rest framework)\n    path(\"auth/\", include(\"django_googler.urls.default\")),\n]\n```\n\n### 3. Run Migrations\n\n```bash\npython manage.py migrate\n```\n\nDone! You now have these endpoints:\n- `GET /api/auth/google/login/` - Get Google OAuth URL\n- `POST /api/auth/google/callback/` - Exchange code for JWT tokens\n- `GET /api/auth/me/` - Get current user (requires JWT)\n- `POST /api/auth/logout/` - Logout (requires JWT)\n\nYou can also use the Django views directly:\n- `GET /auth/google/login/` - To automatically start Google OAuth which will automatically redirect you to `/auth/google/callback/`\n- `GET /auth/google/callback/` - To handle Google's callback\n- To `logout` you'll use a standard Django logout view or logout method to end the User's session\n\n## Usage\n\n### API Examples:\n\n```bash\ncurl http://localhost:8000/api/auth/google/login/\n```\nYields:\n\n```json\n{\n  \"authorization_url\": \"https://accounts.google.com/...\",\n  \"state\": \"...\"\n}\n```\nOpening `authorization_url` in a new tab will start the Google OAuth flow and automatically redirect you to `/api/auth/google/callback/`. If you set `DJANGO_GOOGLER_ALLOW_GET_ON_DRF_CALLBACK = True` in `settings.py`, your automatic redirect to `/api/auth/googler/callback/` will automatically provider your auth tokens in the response such as:\n\n```json\n{\n  \"access\": \"eyJ0eXAiOiJKV1Q...\",  // JWT access token (short-lived)\n  \"refresh\": \"eyJ0eXAiOiJKV1Q...\", // JWT refresh token (long-lived)\n  \"user\": {\n    \"id\": 1,\n    \"email\": \"user@example.com\",\n    \"username\": \"user\",\n    \"first_name\": \"John\",\n    \"last_name\": \"Doe\"\n  }\n}\n```\n\nFrom here you can do an authenticated request to `/api/auth/me/` to get the user's information:\n```bash\ncurl http://localhost:8000/api/auth/me/ \\\n  -H \"Authorization: Bearer <access_token>\"\n```\n\nTo refresh the access token, you can use the `/api/auth/google/refresh/` endpoint:\n```bash\ncurl -X POST http://localhost:8000/api/auth/google/refresh/ \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"refresh\": \"<refresh_token>\"}'\n```\nThis is a standard JWT refresh endpoint provided by [rest_framework_simplejwt](https://django-rest-framework-simplejwt.readthedocs.io/) with `TokenRefreshView`.\n\n### Frontend Flow\n\n**1. Get Google OAuth URL**\n\n```javascript\nconst redirect_uri = 'http://localhost:3000/auth/callback';\nconst apiBaseUrl = 'http://localhost:8000';\nconst loginApiEndpoint = `${apiBaseUrl}/api/auth/google/login/`;\nconst requestUrl = `${loginApiEndpoint}?redirect_uri=${redirect_uri}`;\nconst response = await fetch(requestUrl);\nconst data = await response.json();\n// data = { \"authorization_url\": \"https://accounts.google.com/...\", \"state\": \"...\" }\n\n// Redirect user to Google\nwindow.location.href = data.authorization_url;\n```\n\n**2. Handle Google's Callback**\n\nAfter Google redirects back to your frontend with a `code` and `state`:\n\n```javascript\n// Get the callback data from the current URL\nconst currentUrl = new URL(window.location.href);\nconst googleCallbackData = Object.fromEntries(currentUrl.searchParams);\n\n// Send the callback data to the backend\nconst apiBaseUrl = 'http://localhost:8000';\nconst callbackApiEndpoint = `${apiBaseUrl}/api/auth/google/callback/`;\nconst response = await fetch(callbackApiEndpoint, {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify(googleCallbackData)\n});\n\nconst responseData = await response.json();\n/* responseData = {\n  \"access\": \"eyJ0eXAiOiJKV1Q...\",  // JWT access token (short-lived)\n  \"refresh\": \"eyJ0eXAiOiJKV1Q...\", // JWT refresh token (long-lived)\n  \"user\": {\n    \"id\": 1,\n    \"email\": \"user@example.com\",\n    \"username\": \"user\",\n    \"first_name\": \"John\",\n    \"last_name\": \"Doe\"\n  }\n} */\n\n// Save tokens\nlocalStorage.setItem('access_token', responseData.access);\nlocalStorage.setItem('refresh_token', responseData.refresh);\n```\n\n**3. Make Authenticated Requests**\n\n```javascript\nconst apiBaseUrl = 'http://localhost:8000';\nconst meApiEndpoint = `${apiBaseUrl}/api/auth/me/`;\nconst response = await fetch(meApiEndpoint, {\n  headers: {\n    'Authorization': `Bearer ${localStorage.getItem('access_token')}`\n  }\n});\n\nconst responseData = await response.json();\n/* responseData = {\n  \"id\": 1,\n  \"email\": \"user@example.com\",\n  \"username\": \"user\",\n  \"first_name\": \"John\",\n  \"last_name\": \"Doe\"\n} */\n```\n\n**4. Logout**\n\n```javascript\nconst apiBaseUrl = 'http://localhost:8000';\nconst logoutApiEndpoint = `${apiBaseUrl}/api/auth/logout/`;\nconst response = await fetch(logoutApiEndpoint, {\n  method: 'POST',\n  headers: {\n    'Authorization': `Bearer ${localStorage.getItem('access_token')}`,\n    'Content-Type': 'application/json'\n  },\n  body: JSON.stringify({\n    refresh: localStorage.getItem('refresh_token')\n  })\n});\n\nlocalStorage.removeItem('access_token');\nlocalStorage.removeItem('refresh_token');\n```\n\n## Configuration\n\n### Required Settings\n\n```python\nGOOGLE_OAUTH_CLIENT_ID = \"your-client-id\"\nGOOGLE_OAUTH_CLIENT_SECRET = \"your-client-secret\"\n```\n\n### Optional Settings\n\n```python\n# Return Google tokens in callback response (for calling Google APIs from frontend)\n# Default: False\nGOOGLE_OAUTH_RETURN_TOKENS = False\n\n# Revoke Google access on logout\n# Default: False\nGOOGLE_OAUTH_REVOKE_ON_LOGOUT = False\n\n# Save Google OAuth tokens to database (for backend Google API calls)\n# Default: True\nGOOGLE_OAUTH_SAVE_TOKENS_TO_DB = True\n\n# Request additional Google API scopes\n# Default: [\"openid\", \"email\", \"profile\"]\nGOOGLE_OAUTH_SCOPES = [\n    \"openid\",\n    \"https://www.googleapis.com/auth/userinfo.email\",\n    \"https://www.googleapis.com/auth/userinfo.profile\",\n    # \"https://www.googleapis.com/auth/calendar\",  # Add if needed\n]\n```\n\n## Google Cloud Setup\n\nFor Development:\n1. Go to [Google Cloud Console](https://console.cloud.google.com/)\n2. Create a project\n3. Go to **Google Auth Platform**\n4. Navigate to **Clients** > **+Create Client**\n\nFor Development use:\n\n- **Application type**: Web application\n- **Name**: Django Googler Dev\n- **Authorized redirect URIs**:\n  - `http://localhost:8000/api/auth/google/callback/`\n  - `http://localhost:8000/auth/google/callback/` (frontend handler for Django-based frontend)\n  - `http://localhost:3000/auth/google/callback/` (frontend handler for React, Next.js or Vue)\n  - Any others you might need during development\n\nFor Production use:\n\n- **Application type**: Web application\n- **Name**: Django Googler Prod\n- **Redirect URIs**:\n  - `https://yourdomain.com/api/auth/google/callback/`\n  - `https://yourdomain.com/auth/google/callback/` (frontend handler for Django or Next.js/React/Vue frontend)\n  - Any others you might need (adding more is fine especially if you have multiple frontend frameworks)\n\nAfter you configure it, click **Create** and for _each environment_ (prod/dev) grab:\n\n- **Client ID** (such as `django-googler-dev.apps.googleusercontent.com` and `django-googler-prod.apps.googleusercontent.com`)\n- **Client Secret**\n\nFor dev, update your `.env` file with:\n\n```bash\nGOOGLE_OAUTH_CLIENT_ID=django-googler-dev.apps.googleusercontent.com\nGOOGLE_OAUTH_CLIENT_SECRET=your-dev-client-secret\n```\n\nFor prod, update your runtime secrets with:\n\n```bash\nGOOGLE_OAUTH_CLIENT_ID=django-googler-prod.apps.googleusercontent.com\nGOOGLE_OAUTH_CLIENT_SECRET=your-prod-client-secret\n```\n\n## Making Google API Calls\n\nIf your backend needs to call Google APIs on behalf of users:\n\n```python\nfrom django_googler.services import GoogleOAuthService\n\n\ndef my_view(request):\n    # Get valid access token (auto-refreshes if expired)\n    access_token, expiry = GoogleOAuthService.get_valid_token(request.user)\n\n    if access_token:\n        import requests\n\n        headers = {\"Authorization\": f\"Bearer {access_token}\"}\n        response = requests.get(\n            \"https://www.googleapis.com/calendar/v3/calendars/primary/events\",\n            headers=headers,\n        )\n        return response.json()\n```\n\n## Using Django Views (Instead of API)\n\nIf you prefer browser redirects over API calls:\n\n```python\n# urls.py\nurlpatterns = [\n    path(\"auth/\", include(\"django_googler.urls.default\")),\n]\n```\n\nThen in your template:\n```html\n<a href=\"{% url 'django_googler:google-login' %}?next=/dashboard/\">\n    Sign in with Google\n</a>\n```\n\nUsers will be redirected to Google and back, then logged into Django's session.\n\n## Architecture\n\n- **Views** - Handle OAuth flow and return JWT tokens\n- **Services** - Business logic for OAuth, users, and tokens\n- **Models** - Store Google OAuth tokens in database\n\n## License\n\nMIT License\n\n## Support\n\n[GitHub Issues](https://github.com/jmitchel3/django-googler/issues)\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Django Googler is a simple way to integrate Google Auth Platform with your Django project.",
    "version": "0.0.16",
    "project_urls": {
        "Changelog": "https://github.com/jmitchel3/django-googler",
        "Documentation": "https://github.com/jmitchel3/django-googler",
        "Funding": "https://github.com/jmitchel3/django-googler",
        "Repository": "https://github.com/jmitchel3/django-googler"
    },
    "split_keywords": [
        "auth",
        " django",
        " djangorestframework",
        " google",
        " oauth",
        " oauth2",
        " oauthlib"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "c6089c080d161a2394412e943a2878f2c1eb55fae82b7f67414233bee0397f45",
                "md5": "fda19d8dea7436a2bf5b476eb5d79a50",
                "sha256": "479f4f2357bef6f9c00fec02cd515ae27bd5ce849ba0607b8daa86527ee66500"
            },
            "downloads": -1,
            "filename": "django_googler-0.0.16-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "fda19d8dea7436a2bf5b476eb5d79a50",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 34118,
            "upload_time": "2025-10-20T06:13:46",
            "upload_time_iso_8601": "2025-10-20T06:13:46.184808Z",
            "url": "https://files.pythonhosted.org/packages/c6/08/9c080d161a2394412e943a2878f2c1eb55fae82b7f67414233bee0397f45/django_googler-0.0.16-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "7f17828ad2aa3c6236a28c5e5f0dced2abaf70f8e6ebba613b72428c113da21e",
                "md5": "9c77c5be4ed76ae2162e6cb983c371fa",
                "sha256": "d88f0c609f325199d7075a36d69ada96e75137f9d37843f28b85eee464644e89"
            },
            "downloads": -1,
            "filename": "django_googler-0.0.16.tar.gz",
            "has_sig": false,
            "md5_digest": "9c77c5be4ed76ae2162e6cb983c371fa",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 63120,
            "upload_time": "2025-10-20T06:13:47",
            "upload_time_iso_8601": "2025-10-20T06:13:47.887308Z",
            "url": "https://files.pythonhosted.org/packages/7f/17/828ad2aa3c6236a28c5e5f0dced2abaf70f8e6ebba613b72428c113da21e/django_googler-0.0.16.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-20 06:13:47",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "jmitchel3",
    "github_project": "django-googler",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "django-googler"
}
        
Elapsed time: 3.17121s