You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python/Django新手:使用Twilio存储短信回复号码至数据库遇报错

Hey there! Let's break this down step by step since you're new to Django and Twilio—no worries, we'll get this sorted out.

First, let's tackle that TypeError: 'type' object is not iterable error, then walk through how to properly store subscription numbers in your database based on user responses.


Fixing the "TypeError: 'type' object is not iterable"

This error almost always happens when you're trying to loop over or iterate a class itself instead of an instance/queryset of that class. For example:

  • If you wrote for number in Subscription (referencing the model class) instead of for number in Subscription.objects.all() (referencing a queryset of actual records)
  • Or if you accidentally passed a model class (like User) instead of a value (like a phone number string) when creating a database entry

Double-check your code for these common mistakes—we'll make sure our solution below avoids this entirely.


Step 1: Create a Subscription Model

First, define a Django model to store user subscription data. This will track phone numbers, their chosen subscription type, and status.

In your app's models.py:

from django.db import models

class Subscription(models.Model):
    # Define possible subscription options (customize these to fit your campaigns)
    SUBSCRIPTION_TYPES = [
        ('GENERAL', 'General Promotions'),
        ('EXCLUSIVE', 'Exclusive Offers'),
        ('NEWS', 'Product Updates'),
    ]

    phone_number = models.CharField(max_length=20, unique=True)  # Twilio uses E.164 format (+1234567890)
    subscription_type = models.CharField(max_length=20, choices=SUBSCRIPTION_TYPES)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.phone_number} - {self.get_subscription_type_display()}"

Run migrations to create the table in your database:

python manage.py makemigrations
python manage.py migrate

Step 2: Handle Incoming SMS & Store Subscriptions

Use django_twilio's decorator to create a view that processes incoming Twilio SMS, parses the user's subscription request, and saves the data to your database.

In your app's views.py:

from django.http import HttpResponse
from twilio.twiml.messaging_response import MessagingResponse
from django_twilio.decorators import twilio_view
from .models import Subscription

@twilio_view
def handle_incoming_sms(request):
    # Extract data from Twilio's incoming request
    sender_number = request.POST.get('From')  # This is the user's phone number (E.164 format)
    message_content = request.POST.get('Body', '').strip().upper()

    # Initialize Twilio's response object
    twilio_resp = MessagingResponse()

    # Map user messages to subscription types
    subscription_map = {
        'SUBSCRIBE': 'GENERAL',
        'EXCLUSIVE': 'EXCLUSIVE',
        'NEWS': 'NEWS'
    }

    # Validate the user's request
    if message_content not in subscription_map:
        twilio_resp.message("Sorry, we didn't catch that! Reply SUBSCRIBE, EXCLUSIVE, or NEWS to join our lists.")
        return HttpResponse(str(twilio_resp))

    # Get the chosen subscription type
    selected_type = subscription_map[message_content]

    # Save or update the subscription in the database
    try:
        # Use get_or_create to avoid duplicate entries
        subscription, was_created = Subscription.objects.get_or_create(
            phone_number=sender_number,
            defaults={'subscription_type': selected_type}
        )

        # If the user already subscribed, update their preference
        if not was_created:
            subscription.subscription_type = selected_type
            subscription.is_active = True
            subscription.save()
            twilio_resp.message(f"Updated your subscription to {selected_type.lower()} offers!")
        else:
            twilio_resp.message(f"Thanks for joining our {selected_type.lower()} list!")
    except Exception as e:
        twilio_resp.message("Oops, something went wrong. Please try again later.")
        # Log the error for debugging (you can use Django's logging framework here)
        print(f"Error saving subscription: {str(e)}")

    return HttpResponse(str(twilio_resp))

Step 3: Configure the URL Route

Add a URL path so Twilio can send incoming SMS to your view.

In your project's urls.py:

from django.urls import path
from your_app_name import views

urlpatterns = [
    # ... other URLs
    path('sms/incoming/', views.handle_incoming_sms, name='handle_incoming_sms'),
]

Final Setup Tips

  1. Twilio Webhook Configuration: Go to your Twilio dashboard, select your phone number, and set the "A Message Comes In" webhook URL to your Django app's /sms/incoming/ endpoint. If you're developing locally, use a tool like ngrok to expose your server to the internet.
  2. Phone Number Validation: For extra robustness, add validation to ensure sender_number is in a valid E.164 format (Twilio sends numbers this way by default, but it's good to double-check).
  3. Error Logging: Replace the print() statement with Django's built-in logging to track errors more effectively in production.

内容的提问来源于stack exchange,提问作者Ach1916

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:47:27