โ† Back to Connections

Connect Django to PostPenguin

Medium SetupLanguage: PythonTime: 15 minutes

Django applications can receive PostPenguin webhooks and automatically create blog posts in your Django models.

๐Ÿš€ Quick Setup

1. Install Dependencies

pip install django djangorestframework requests

2. Create Django App

python manage.py startapp blog

3. Create Post Model

# blog/models.py
from django.db import models
import uuid

class Post(models.Model):
    postpenguin_id = models.CharField(max_length=255, unique=True, blank=True)
    title = models.CharField(max_length=500)
    slug = models.SlugField(unique=True)
    html = models.TextField()
    meta_title = models.CharField(max_length=500, blank=True)
    meta_description = models.TextField(blank=True)
    featured_image = models.URLField(blank=True)
    published_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-published_at']

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        if not self.postpenguin_id:
            self.postpenguin_id = str(uuid.uuid4())
        super().save(*args, **kwargs)

4. Create Webhook View

# blog/views.py
import hmac
import hashlib
import json
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.conf import settings
from .models import Post

@csrf_exempt
@require_POST
def postpenguin_webhook(request):
    # Verify webhook signature (recommended)
    signature = request.headers.get('X-PostPenguin-Signature')
    webhook_secret = getattr(settings, 'POSTPENGUIN_WEBHOOK_SECRET', None)

    if webhook_secret and signature:
        payload = request.body
        expected_signature = hmac.new(
            webhook_secret.encode(),
            payload,
            hashlib.sha256
        ).hexdigest()

        received_signature = signature.replace('sha256=', '')

        if received_signature != expected_signature:
            return JsonResponse({'error': 'Invalid signature'}, status=401)

    try:
        data = json.loads(request.body)

        # Validate required fields
        required_fields = ['title', 'slug', 'html']
        for field in required_fields:
            if field not in data:
                return JsonResponse({'error': f'Missing required field: {field}'}, status=400)

        # Create or update post
        post, created = Post.objects.update_or_create(
            postpenguin_id=data.get('postPenguinId', str(uuid.uuid4())),
            defaults={
                'title': data['title'],
                'slug': data['slug'],
                'html': data['html'],
                'meta_title': data.get('meta_title', data['title']),
                'meta_description': data.get('meta_description', ''),
                'featured_image': data.get('featured_image', ''),
            }
        )

        return JsonResponse({
            'success': True,
            'post_id': post.id,
            'action': 'created' if created else 'updated',
            'post_url': f'/posts/{post.slug}/'  # Adjust URL pattern as needed
        })

    except json.JSONDecodeError:
        return JsonResponse({'error': 'Invalid JSON'}, status=400)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)

5. Configure URLs

# blog/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('webhooks/postpenguin/', views.postpenguin_webhook, name='postpenguin_webhook'),
]

# main urls.py
from django.urls import path, include

urlpatterns = [
    # ... other URLs ...
    path('api/', include('blog.urls')),
]

6. Settings

# settings.py
POSTPENGUIN_WEBHOOK_SECRET = 'your-webhook-secret-here'

# Add to INSTALLED_APPS
INSTALLED_APPS = [
    # ... other apps ...
    'blog',
    'rest_framework',
]

# Run migrations
python manage.py makemigrations blog
python manage.py migrate

7. Configure PostPenguin

When adding your site to PostPenguin:

  • Webhook URL: https://your-domain.com/api/webhooks/postpenguin/
  • Secret Key: Same as POSTPENGUIN_WEBHOOK_SECRET

๐Ÿงช Testing

Test Webhook

# Test the webhook endpoint
curl -X POST https://your-domain.com/api/webhooks/postpenguin/ \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Test Post from Django",
    "slug": "test-post-django",
    "html": "<p className="text-gray-700">This is a test post from Django.</p>",
    "meta_title": "Test Post Title",
    "meta_description": "Testing Django webhook integration",
    "featured_image": "https://via.placeholder.com/800x400",
    "status": "publish"
  }'

Need Help?

Read our webhook documentation for technical details, or contact support for custom integrations.