You are viewing the Spanish (Mexico) site, but your language preference is set to English. Switch to English site →

Menu

Expand
Calificar esta página:

Recordatorios de citas con Python y Django

¡Ahoy! Ahora te recomendamos que crees tus recordatorios de citas SMS con la funcionalidad de programación de mensajes integrada de Twilio. Dirígete a la Documentación de recursos de mensajes para obtener más información sobre la programación de mensajes de SMS.

¿Estás listo para implementar recordatorios de citas por SMS en tu aplicación web de Django? Usaremos la Biblioteca auxiliar de Python de Twilio y la API de Twilio SMS para enviar recordatorios a nuestros clientes cuando se aproximen las citas. Así es como funciona a un nivel alto:

  1. Un administrador (nuestro usuario) crea una cita para una fecha y hora futuras y almacena el número de teléfono de un cliente en la base de datos de esa cita
  2. Cuando se guarda esa cita, se programa una tarea en segundo plano para enviar un recordatorio a ese cliente antes de que comience la cita
  3. A una hora configurada antes de la cita, la tarea en segundo plano envía un recordatorio por SMS al cliente para recordarle su cita

Comprueba cómo Yelp utiliza SMS para confirmar las reservas de restaurantes para los comensales.

Componentes básicos de los recordatorios de citas

Estas son las tecnologías que utilizaremos:

  • Django para crear una aplicación web basada en bases de datos
  • El recurso mensajes de la API REST de Twilio para enviar mensajes de texto
  • Dramatiq para ayudarnos a programar y ejecutar tareas en segundo plano de forma recurrente

Cómo leer este tutorial

Para implementar los recordatorios de citas, trabajaremos en una serie de historias de usuarios que describen cómo implementar por completo los recordatorios de citas en una aplicación web.

Analizaremos el código necesario para satisfacer cada historia y exploraremos lo que necesitábamos añadir en cada paso.

Todo esto se puede hacer con la ayuda de Twilio en menos de media hora.

¡Empecemos!

Conoce nuestra pila de recordatorios de citas de Django

Estamos creando esta app para Django 2.1 en Python 3.6. Somos grandes admiradores de Two Scoops of Django y utilizaremos muchas de las prácticas recomendadas descritas allí.

Además de Dramatiq, usaremos algunas otras bibliotecas de Python para hacer nuestra tarea más fácil:

También usaremos PostgreSQL para nuestra base de datos y Redis como nuestro agente de mensajes de Dramatiq.

Loading Code Sample...
        
        
        requirements.txt

        Dependencias del proyecto

        requirements.txt

        Ahora que hemos definido todas nuestras dependencias, podemos empezar con nuestra primera historia de usuario: crear una cita nueva.

        Creación de una cita

        Creación de una cita

        Como usuario, quiero crear una cita con un nombre, un número de teléfono de invitado y una hora en el futuro.

        Para crear una app de recordatorios de citas automatizada, probablemente deberíamos empezar con una cita. Esta historia requiere que creemos un objeto de modelo y un poco de la interfaz de usuario para crear y guardar una Appointment nueva en nuestro sistema.

        A un nivel alto, esto es lo que necesitaremos añadir:

        • Un modelo Appointment para almacenar información que tenemos que enviar el recordatorio
        • Una vista para representar nuestro formulario y aceptar datos POST de este
        • Un formulario HTML para introducir detalles sobre la cita

        Bien, sabemos lo que necesitamos para crear una cita nueva. Ahora, empecemos por observar el modelo, en el que decidimos qué información queremos almacenar con la cita.

        Consulta nuestro modelo de cita

        El modelo de cita

        Solo necesitamos almacenar cuatro datos sobre cada cita para enviar un recordatorio:

        • El nombre del cliente
        • Su número de teléfono
        • La fecha y hora de su cita
        • La zona horaria de la cita

        También hemos incluido dos campos adicionales: task_id y created. El campo task_id nos ayudará a realizar un seguimiento de la tarea de recordatorio correspondiente a esta cita. El campo created es solo una marca de tiempo que se rellena cuando se crea una cita.

        Por último, definimos un método __str__ para decirle a Django cómo representar instancias de nuestro modelo como texto. Este método utiliza la clave principal y el nombre del cliente para crear una representación legible de una cita.

        Loading Code Sample...
              
              
              reminders/models.py

              Campos del modelo de cita

              reminders/models.py

              Nuestro modelo de cita ya está configurado, el siguiente paso es escribirle una vista.

              Consulta la vista de cita nueva

              Vista de cita nueva

              Django permite a los desarrolladores escribir vistas como funciones o clases.

              Las vistas basadas en clases son excelentes cuando tus vistas necesitan soportar funciones sencillas de tipo CRUD, perfectas para nuestro proyecto de citas.

              Para crear una vista que crea objetos de Appointment nuevos, usaremos la clase CreateView genérica de Django.

              Lo que necesitamos especificar es el modelo que debe utilizar y los campos que debe incluir. Ni siquiera necesitamos declarar un formulario, Django usará un ModelForm para nosotros en segundo plano.

              Mensajes de éxito

              Nuestra vista está lista con solo esas tres primeras líneas de código, pero la mejoraremos un poco al añadir el SuccessMessageMixin.

              Este mixin le dice a nuestra vista que pase la propiedad success_message de nuestra clase al marco de mensajes de Django después de una creación exitosa. Mostraremos esos mensajes al usuario en nuestras plantillas.

              Loading Code Sample...
                    
                    
                    reminders/views.py

                    Crear cita nueva

                    reminders/views.py

                    Ahora que tenemos una vista para crear citas nuevas, necesitamos añadir una URL nueva a nuestro distribuidor de URL a fin de que los usuarios puedan acceder a ella.

                    Conectar la URL con la vista que acabamos de crear

                    Conectar las URL

                    Para satisfacer la historia de usuario de creación de citas, crearemos una URL nueva en /new y la dirigiremos a nuestra AppointmentCreateView.

                    Como estamos utilizando una vista basada en clases, pasamos nuestra vista a nuestra dirección URL con el método .as_view() en lugar de solo utilizar el nombre de la vista.

                    Loading Code Sample...
                          
                          
                          reminders/urls.py

                          Conectar la URL con la vista de creación de citas

                          reminders/urls.py

                          Con una vista y un modelo en su lugar, la última gran pieza que necesitamos para permitir que nuestros usuarios creen citas nuevas es el formulario HTML.

                          Consulta el formulario de cita nuevo

                          Formulario de cita nuevo

                          Nuestra plantilla de formulario hereda de nuestra plantilla base, lo que puedes consultar en templates/base.html.

                          Estamos usando Bootstrap para la interfaz de nuestra app, y usamos la biblioteca django-forms-bootstrap a fin de ayudarnos a representar nuestro formulario con el filtro de plantilla |as_bootstrap_horizontal.

                          Cuando se nombra este archivo como appointment_form.html, nuestra AppointmentCreateView utilizará esta plantilla de forma automática cuando represente su respuesta. Si deseas asignar otro nombre a la plantilla, puedes especificar su nombre al añadir una propiedad template_name en nuestra clase de vista.

                          Loading Code Sample...
                                
                                
                                templates/reminders/appointment_form.html

                                Formulario de cita nuevo

                                templates/reminders/appointment_form.html

                                Todavía no terminamos con este formulario. Echemos un vistazo más de cerca a uno de sus widgets: el selector de fecha.

                                Echa un vistazo al widget de selector de fecha

                                Selector de fecha del formulario de la cita

                                Para facilitar a nuestros usuarios la introducción de la fecha y la hora de una cita, utilizaremos un widget de selector de fecha de JavaScript.

                                En este caso, bootstrap-datetimepicker es una buena opción. Incluimos los archivos CSS y JS necesarios de las redes de entrega de contenido y, a continuación, añadimos JavaScript personalizado para inicializar el widget en el formulario de entrada de nuestro campo de tiempo.

                                Loading Code Sample...
                                      
                                      
                                      templates/reminders/appointment_form.html

                                      Widget de selector de fecha

                                      templates/reminders/appointment_form.html

                                      Ahora volvamos a nuestro modelo Appointment para ver lo que sucede después de publicar este formulario con éxito.

                                      Añadir un método get_absolute_url

                                      Añadir un método get_absolute_url()

                                      Cuando un usuario hace clic en "Submit" en nuestro formulario de cita nuevo, AppointmentCreateView recibirá su entrada y, a continuación, lo validará en los campos especificados en nuestro modelo Appointment.

                                      Si todo es correcto, Django guardará la cita nueva en la base de datos. Tenemos que decirle a nuestra AppointmentCreateView a dónde enviar a nuestro usuario a continuación.

                                      Podríamos especificar una propiedad success_url en nuestra AppointmentCreateView, pero de forma predeterminada la clase CreateView de Django usará el método get_absolute_url del objeto recién creado para averiguar dónde ir a continuación.

                                      Definiremos un método get_absolute_url en nuestro modelo Appointment, que usa la función de utilidad reverse de Django para crear una URL en la página de detalles de esta cita. Puedes ver esa plantilla en templates/reminders/appointment_detail.html.

                                      Y ahora todos nuestros usuarios están listos para crear citas nuevas.

                                      Loading Code Sample...
                                            
                                            
                                            reminders/models.py

                                            método get_absolute_url

                                            reminders/models.py

                                            Ahora podemos crear citas nuevas. A continuación, implementaremos con rapidez algunas otras funciones básicas: enumerar, actualizar y eliminar citas.

                                            Conoce lo que necesitamos para interactuar con las citas

                                            Interactuar con citas

                                            Como usuario, deseo ver una lista de todas las citas futuras y poder editarlas y eliminarlas.

                                            Si eres una organización que gestiona muchas citas, es probable desees poder verlas y gestionarlas en una única interfaz. Eso es lo que abordaremos en esta historia de usuario. Crearemos una interfaz de usuario para:

                                            • Mostrar todas las citas
                                            • Editar citas individuales
                                            • Eliminar citas individuales

                                            Debido a que se trata de operaciones básicas de tipo CRUD, seguiremos utilizando las vistas genéricas basadas en clases de Django para ahorrarnos mucho trabajo.

                                            Loading Code Sample...
                                                  
                                                  
                                                  reminders/views.py

                                                  Interactuar con citas

                                                  reminders/views.py

                                                  Tenemos una vista de alto nivel de la tarea, así que comencemos con una lista de todas las citas próximas.

                                                  Comprueba la vista para enumerar las citas

                                                  Mostrar una lista de citas

                                                  La clase ListView de Django nació para esto.

                                                  Todo lo que debemos hacer es apuntarla a nuestro modelo Appointment y manejará la creación de un QuerySet de todas las citas por nosotros.

                                                  Y la conexión de esta vista en nuestro módulo reminders/urls.py es tan sencilla como nuestra AppointmentCreateView:

                                                  from .views import AppointmentListView
                                                  
                                                  re_path(r'^$', AppointmentListView.as_view(), name='list_appointments'),
                                                  
                                                  Loading Code Sample...
                                                        
                                                        
                                                        reminders/views.py

                                                        Enumerar las citas

                                                        reminders/views.py

                                                        Nuestra vista está lista, ahora comprobemos la plantilla para mostrar esta lista de citas.

                                                        Consulta la plantilla de lista de citas

                                                        Plantilla de lista de citas

                                                        Nuestra AppointmentListView pasa su lista de objetos de cita a nuestra plantilla en la variable object_list.

                                                        Si esa variable está vacía, incluimos una etiqueta <p> que indica que no hay citas próximas.

                                                        De lo contrario, rellenamos una tabla con una fila para cada cita de la lista. Podemos utilizar nuestro práctico método get_absolute_url de nuevo para incluir un enlace a la página de detalles de cada cita.

                                                        También utilizamos la etiqueta de la plantilla {% url %} para incluir enlaces a nuestras vistas de edición y eliminación.

                                                        Loading Code Sample...
                                                              
                                                              
                                                              templates/reminders/appointment_list.html

                                                              Representar la lista de citas

                                                              templates/reminders/appointment_list.html

                                                              Ahora que nuestro requisito de listado de citas está completo, veamos cómo podemos utilizar el formulario de cita nuevo para actualizar las citas existentes.

                                                              Conoce cómo se puede utilizar el formulario de cita nuevo para actualizar citas

                                                              Ajustar nuestra plantilla de formulario

                                                              UpdateView de Django facilita la adición de una vista para actualizar citas. Sin embargo, nuestra plantilla de formulario necesita algunos ajustes para gestionar los datos rellenados previamente de una cita existente.

                                                              Django almacenará nuestras fechas y horas con precisión, pero no queremos molestar a nuestros usuarios obligándolos a elegir el segundo exacto en el que comienza una cita.

                                                              Para solucionar este problema utilizamos la opción de configuración extraFormats de bootstrap-datetimepicker.

                                                              Cuando se configura nuestro datetimepicker con un valor format que no pregunta a los usuarios por segundos y un valor extraFormat que acepta una fecha y hora con segundos, nuestro formulario se rellenará de forma correcta cuando Django proporcione una fecha y hora completa a nuestra plantilla.

                                                              Loading Code Sample...
                                                                    
                                                                    
                                                                    templates/reminders/appointment_form.html

                                                                    Ajustar el formulario de cita nuevo

                                                                    templates/reminders/appointment_form.html

                                                                    Ahora tenemos todo para List, Create y Update una Appointment. Solo queda manejar la Delete.

                                                                    DeleteView al rescate

                                                                    Eliminar vista

                                                                    DeleteView es una clase de vista especialmente útil. Muestra a los usuarios una página de confirmación antes de eliminar el objeto especificado.

                                                                    Al igual que UpdateView, DeleteView busca el objeto que se va a eliminar mediante el parámetro pk en su URL, declarada en reminders/urls.py:

                                                                    from .views import AppointmentDeleteView
                                                                    
                                                                    re_path(r'^/(?P[0-9]+)/delete$', AppointmentDeleteView.as_view(), name='delete_appointment'),
                                                                    

                                                                    También necesitamos especificar una propiedad success_url en nuestra clase de vista. Esta propiedad indica a Django dónde enviar a los usuarios después de una eliminación con éxito. En nuestro caso, las devolveremos a la lista de citas en la URL denominada list_appointments.

                                                                    Cuando un proyecto de Django comienza a ejecutarse, evalúa las vistas antes de que las URL, por lo que necesitamos usar la función de utilidad reverse_lazy para obtener la URL de nuestra lista de citas en lugar de reverse.

                                                                    De forma predeterminada, nuestra AppointmentDeleteView buscará una plantilla denominada appointment_confirm_delete.html. Puedes consultar la nuestra en el directorio de templates/reminders.

                                                                    Esto cierra esta historia de usuario.

                                                                    Loading Code Sample...
                                                                          
                                                                          
                                                                          reminders/views.py

                                                                          Importar vistas genéricas

                                                                          reminders/views.py

                                                                          Ahora nuestros usuarios tienen todo lo que necesitan para gestionar las citas; lo que queda por implementar es enviar los recordatorios.

                                                                          Consulta los requisitos para enviar un recordatorio

                                                                          Envío del recordatorio

                                                                          Como sistema de citas, quiero notificar a un cliente mediante SMS en un intervalo arbitrario antes de una cita futura.

                                                                          Para satisfacer esta historia de usuario, necesitamos hacer que nuestra aplicación móvil funcione de forma asincrónica, independiente de cualquier interacción de usuario individual.

                                                                          Una de las bibliotecas de Python más populares para tareas asincrónicas es Dramatiq. Para integrar Dramatiq en nuestra aplicación móvil, necesitamos hacer algunos cambios:

                                                                          • Crear una función nueva que envíe un mensaje SMS con información de un objeto Appointment
                                                                          • Registrar esa función como una tarea con Dramatiq para que se pueda ejecutar de forma asincrónica
                                                                          • Ejecutar un proceso de trabajador de Dramatiq separado junto con nuestra aplicación de Django para llamar a nuestra función de recordatorio de SMS en el momento adecuado de cada cita

                                                                          Si eres nuevo en Dramatiq, te recomendamos echar un vistazo a su página Introducción a Dramatiq antes de continuar.

                                                                          Loading Code Sample...
                                                                                
                                                                                
                                                                                reminders/tasks.py

                                                                                Enviar tarea de recordatorio por SMS

                                                                                reminders/tasks.py

                                                                                A continuación, configuraremos Dramatiq para trabajar con nuestro proyecto.

                                                                                Configurar Dramatiq

                                                                                Configurar Dramatiq

                                                                                Dramatiq y Django son grandes proyectos de Python, pero pueden trabajar juntos con facilidad.

                                                                                Al seguir las instrucciones en la documentación de Dramatiq, podemos incluir nuestra configuración de Dramatiq en nuestros módulos de configuración de Django. También podemos escribir nuestras tareas de Dramatiq en módulos de tasks.py que se encuentran en nuestras apps de Django, lo que mantiene el diseño de nuestro proyecto coherente y simple.

                                                                                Para usar Dramatiq, también necesitas un servicio separado para que sea tu agente de mensajería. Utilizamos Redis en este proyecto.

                                                                                La configuración específica de Dramatiq en nuestro módulo de configuración common.py es DRAMATIQ_BROKER.

                                                                                Si deseas ver todos los pasos para hacer que Django, Dramatiq, Redis y Postgres trabajen en tu equipo, consulta el archivo README de este proyecto en GitHub.

                                                                                Loading Code Sample...
                                                                                      
                                                                                      
                                                                                      appointments/settings/common.py

                                                                                      Configuración de Dramatiq

                                                                                      appointments/settings/common.py

                                                                                      Ahora que Dramatiq está trabajando con nuestro proyecto, es el momento de escribir una tarea nueva para enviar a un cliente un mensaje SMS sobre su cita.

                                                                                      Comprueba cómo crear una tarea de Dramatiq nueva

                                                                                      Crear una tarea de Dramatiq

                                                                                      Nuestra tarea toma el ID de una cita, su clave principal, como único argumento. Podríamos pasar el objeto Appointment por sí solo como argumento, pero esta práctica recomendada garantiza que nuestro SMS utilizará la versión más actualizada de los datos de nuestra cita.

                                                                                      También nos da la oportunidad de comprobar si la cita se ha eliminado antes de enviar el recordatorio, lo que hacemos en la parte superior de nuestra función. De esta forma no enviaremos recordatorios por SMS para citas que ya no existen.

                                                                                      Loading Code Sample...
                                                                                            
                                                                                            
                                                                                            reminders/tasks.py

                                                                                            Obtener citas en la tarea de Dramatiq

                                                                                            reminders/tasks.py

                                                                                            Seguiremos en nuestra tarea un poco más, porque el siguiente paso es redactar el texto de nuestro mensaje SMS.

                                                                                            Conoce cómo enviar un SMS con el cliente de Python de Twilio

                                                                                            Enviar un mensaje SMS

                                                                                            Utilizamos la práctica biblioteca arrow para dar formato a la hora de nuestra cita. Después de eso, usamos la biblioteca twilio-python para enviar nuestro mensaje.

                                                                                            Instanciamos un cliente de REST de Twilio en la parte superior del módulo, que busca las variables del entorno TWILIO_ACCOUNT_SID y TWILIO_AUTH_TOKEN para autenticarse. Puedes encontrar los valores correctos para ti en el panel de control de la cuenta.

                                                                                            Enviar el mensaje SMS en sí es tan fácil como llamar a client.messages.create(), pasar argumentos para el cuerpo del mensaje SMS, el número de teléfono del destinatario y el número de teléfono de Twilio desde el que deseas enviar este mensaje. Twilio entregará el mensaje SMS de inmediato.

                                                                                            Loading Code Sample...
                                                                                                  
                                                                                                  
                                                                                                  reminders/tasks.py

                                                                                                  Enviar un SMS en la tarea de Dramatiq

                                                                                                  reminders/tasks.py

                                                                                                  Ahora que finalizamos nuestra tarea de send_sms_reminder, veamos cómo llamarla cuando se crean o actualizan nuestras citas.

                                                                                                  ¿Cómo llamamos a esta tarea?

                                                                                                  Llamar a nuestra tarea de recordatorio

                                                                                                  Hemos añadido un método nuevo a nuestro modelo Appointment para ayudar a programar un recordatorio en una cita individual.

                                                                                                  Nuestro método comienza mediante el uso de arrow de nuevo para crear una nueva fecha y hora con la time y time_zone de la cita.

                                                                                                  Moverse hacia atrás en el tiempo puede ser difícil en Python normal, pero el método .replace() de arrow nos permite quitar minutos con facilidad de nuestra appointment_time. El valor predeterminado de REMINDER_TIME son 30 minutos.

                                                                                                  Terminamos al invocar nuestra tarea de Dramatiq, con el parámetro delay para decirle a Dramatiq cuándo debe ejecutarse esta tarea.

                                                                                                  No se puede importar la tarea send_sms_reminder en la parte superior de nuestro módulo models.py porque el módulo tasks.py importa el modelo Appointment. Importarlo en nuestro método schedule_reminder evita una dependencia circular.

                                                                                                  Loading Code Sample...
                                                                                                        
                                                                                                        
                                                                                                        reminders/models.py

                                                                                                        Programar una tarea de Dramatiq nueva

                                                                                                        reminders/models.py

                                                                                                        Lo último que debemos hacer es asegurar de que Django llame a nuestro método schedule_reminder cada vez que se crea o actualiza un objeto Appointment.

                                                                                                        Anular el método de guardar cita

                                                                                                        Anular el método de Guardar cita

                                                                                                        La mejor manera de hacerlo es anular el método de guardar de nuestro modelo, incluida una llamada adicional a schedule_reminder después de que se haya asignado la clave principal del objeto.

                                                                                                        Evitar recordatorios duplicados o inoportunos

                                                                                                        Programar una tarea de Dramatiq cada vez que se guarda una cita tiene un efecto secundario no deseado, nuestros clientes recibirán recordatorios duplicados si una cita se ha guardado más de una vez. Y esos recordatorios podrían enviarse en el momento equivocado si el campo time de una cita se cambiaba después de su creación.

                                                                                                        Para corregir esto, realizamos un seguimiento de la tarea de recordatorio de cada cita mediante el campo task_id, que almacena el identificador único de Dramatiq para cada tarea.

                                                                                                        A continuación, buscamos una tarea programada de forma previa en la parte superior de nuestro método save personalizado y la cancelamos si está presente.

                                                                                                        Esto garantiza que se enviará solo un recordatorio para cada cita de nuestra base de datos y que se enviará a la time más reciente prevista para esa cita.

                                                                                                        Loading Code Sample...
                                                                                                              
                                                                                                              
                                                                                                              reminders/models.py

                                                                                                              Anular el método save() para llamar a schedule_reminder()

                                                                                                              reminders/models.py

                                                                                                              Un tutorial divertido, ¿verdad? ¿Dónde podemos ir desde aquí?

                                                                                                              ¿Dónde ir a continuación?

                                                                                                              Finalizar la implementación del recordatorio de cita de Django

                                                                                                              Utilizamos las vistas basadas en clases de Django para ayudarnos a crear con rapidez las funciones a fin de soportar operaciones CRUD sencillas en nuestro modelo Appointment.

                                                                                                              Luego integramos Dramatiq en nuestro proyecto y usamos la biblioteca auxiliar twilio-python para enviar recordatorios de SMS sobre nuestras citas de forma asincrónica.

                                                                                                              Encontrarás instrucciones para ejecutar este proyecto de forma local en el archivo README de GitHub.

                                                                                                              Loading Code Sample...
                                                                                                                    
                                                                                                                    
                                                                                                                    reminders/models.py

                                                                                                                    El modelo de cita

                                                                                                                    reminders/models.py

                                                                                                                    ¿Dónde ir a continuación?

                                                                                                                    Con un poco de código y una pizca de configuración, estamos listos para recibir recordatorios de citas automatizados en nuestra aplicación móvil. ¡Bien hecho!

                                                                                                                    Si eres un desarrollador de Python que trabaja con Twilio, puedes consultar otros tutoriales en Python:

                                                                                                                    Llamada del navegador

                                                                                                                    Coloca un botón en tu página web que conecte a los visitantes con el servicio de asistencia en directo o con el personal de ventas por teléfono.

                                                                                                                    Autenticación de dos factores

                                                                                                                    Mejora la seguridad de la funcionalidad de inicio de sesión de la app Python al añadir autenticación de dos factores por mensajes de texto.

                                                                                                                    ¿Te ayudó esto?

                                                                                                                    Gracias por consultar este tutorial. Si tienes algún comentario que compartir con nosotros, comunícate con nosotros en Twitter... nos encantaría saber lo que piensas y conocer lo que estás creando.

                                                                                                                    Andrew Baker Kevin Segovia Daniel Erazo
                                                                                                                    Calificar esta página:

                                                                                                                    ¿Necesitas ayuda?

                                                                                                                    Todos la necesitamos a veces; la programación es difícil. Obtén ayuda ahora de nuestro equipo de soporte, o recurre a la sabiduría de la multitud visitando Stack Overflow Collective de Twilio o navegando por la etiqueta de Twilio en Stack Overflow.

                                                                                                                    Loading Code Sample...
                                                                                                                          
                                                                                                                          
                                                                                                                          

                                                                                                                          Gracias por tus comentarios.

                                                                                                                          Selecciona los motivos de tus comentarios. La información adicional que nos brindas nos ayuda a mejorar nuestra documentación:

                                                                                                                          Enviando tus comentarios…
                                                                                                                          🎉 Gracias por tus comentarios.
                                                                                                                          Se produjo un error. Inténtalo de nuevo.

                                                                                                                          Gracias por tus comentarios.

                                                                                                                          thanks-feedback-gif