Code Monkey home page Code Monkey logo

automated-survey-django's Introduction

Automated surveys (Django)

Build Status

Use Twilio to conduct automated phone surveys.

Read the full tutorial!

Quickstart

Local development

This project is built using the Django web framework. It runs on Python 2.7+ and Python 3.4+.

To run the app locally, first clone this repository and cd into it. Then:

  1. Create a new virtual environment:

    • If using vanilla virtualenv, run virtualenv venv and then source venv/bin/activate.
    • If using virtualenvwrapper, run mkvirtualenv automated-surveys.
  2. Install the requirements with pip install -r requirements.txt.

  3. Start a local PostgreSQL database and create a database called surveys.

    • If on a Mac, we recommend Postgres.app. After installing, run createdb surveys;.
    • If Postgres is already installed locally, you can just run createdb surveys from a terminal.
  4. Copy the .env.example file to .env, and edit it to match your database.

  5. Run the migrations with python manage.py migrate.

  6. Optionally create a superuser so you can access the Django admin: python manage.py createsuperuser.

  7. Start the development server: python manage.py runserver.

Configure Twilio to call your webhooks

You will also need to configure Twilio to call your application when calls are received. To be able to do this you would need to to provision at least one Twilio number with voice capabilities so the application's users can take surveys. You can buy a number right here. Once you have a number you need to configure it to work with your application. Open the number management page and open a number's configuration by clicking on it. Open a number's configuration

Next, edit the "Request URL" field under the "Voice" section and point it towards your ngrok-exposed application /automated-survey/first-survey/ route. Set the HTTP method to POST. If you are running the application in production somewhere, you need to point Twilio to http://<your-app-name>.com/automated-survey/first-survey/.

See the images below as an example on how to do it:

You can then visit the application at http://localhost:8000/.

Mind the trailing slash.

Webhook Voice configuration

The same endpoint for Voice is being used for Messaging, so you can repeat this step on the Messaging section. Webhook SMS configuration

Run the tests

Configure your test database by editing .env.test file. You can then run the tests locally using py.test

$ py.test automated_survey/tests/ --cov=automated_survey

Meta

  • No warranty expressed or implied. Software is as is. Diggity.
  • MIT License
  • Lovingly crafted by Twilio Developer Education.

automated-survey-django's People

Contributors

dependabot-preview[bot] avatar hortega avatar jefflinwood avatar joliveros avatar kathyguerron avatar kwhinnery avatar shyba avatar smendes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

automated-survey-django's Issues

Add a data migration to load the sample survey data

I really like that this app comes with a sample survey. I might add some sample data to the call-tracking-django repo also.

When reviewing tutorial code, I'm always looking for ways to reduce the number of commands a developer has to run to use our project.

The load_survey management command is useful, but right now a developer has to run it as a separate command after they migrate the database. It would be better if we could load that data for them automatically as part of a data migration.

See the Django docs for an example: https://docs.djangoproject.com/en/1.8/topics/migrations/#data-migrations

By adding a data migration after your other migrations, we can automatically load the sample survey into the database for our developers.

If you like, you can just have your data migration invoke your load_survey management command using call_command: https://docs.djangoproject.com/en/1.8/ref/django-admin/#running-management-commands-from-your-code

Avoid error after first time setup

Right now when a developer sets up the app locally, they'll go to http://localhost:8000, get redirected to /automated_survey, and get a 500 error because there are no results in the system.

We want developers to know when they try to access the site for the first time that they configured the app correctly. To fix this, I would adjust the /automated_survey view and template to display some content that says "No survey data yet".

is_sms is not included in twilio request

Hey I just started implementing this, however after sniffing the request a little I discovered that there is no is_sms attribute on the twilio request coming through causing it to crash at line 38 of surveys.py

if request.is_sms:

README webhooks section needs to use a trailing slash - or use APPEND_SLASH=False

When I set up the app for the first time, my Twilio calls would error because I had configured my number to point to /first_survey instead of /first_survey/.

Django error'd because by default it tries to append a slash to inbound requests, but it can't do that on a POST request without the browser dropping the data.

So we need to either update the instructions to include the trailing slash, or change the APPEND_SLASH setting to False.

https://docs.djangoproject.com/en/1.8/ref/settings/#append-slash

Project structure

I had a hard time familiarizing myself with this Django app because it wasn't laid out in the way I expected. It felt like it was configured more like a Flask app than a Django application, but they actually have fairly different code structures.

My main concern is that there's no clear separation between the Django project directory and your automated_survey Django app directory.

I just recently finished the Call Tracking Django tutorial. I think we should structure all our Django tutorials like this going forward: https://github.com/TwilioDevEd/call-tracking-django

Here's a tree output of the call-tracking-django project structure with some comments:

├── LICENSE
├── Procfile
├── README.md
├── app.json
├── call_tracking <- This is your Django app - in your case, automated_survey
│   ├── __init__.py
│   ├── admin.py
│   ├── forms.py
│   ├── migrations
│   ├── models.py
│   ├── static <- This is where the static files your app needs go
│   ├── templatetags
│   ├── test_models.py
│   ├── test_utils.py <- Test modules can be like this or in a separate 'tests' subdirectory if you prefer
│   ├── test_views.py
│   ├── tests.pyc
│   ├── urls.py <- These are the URLs for views within your automated_survey app
│   ├── utils.py
│   ├── views.py <- You can make a views directory instead if you don't want to put them all in one module
├── manage.py
├── requirements.txt
├── runtime.txt
├── templates <- This contains all the templates you use in your app
│   ├── base.html
│   ├── call_tracking
│   └── index.html
└── twilio_sample_project <- you should also name your Django project folder twilio_sample_project
    ├── __init__.py
    ├── settings <- This is the same as your settings directory
    ├── staticfiles <- This is the directory that's created by 'manage.py collectstatic' - not the directory where static files are committed to the repo
    ├── urls.py <- This is the root URLs for your project
    ├── wsgi.py

I wish I had finished the call-tracking-django app before you started on this one. I'm going to spend time this week making a template Django starter project for us all to use so we don't need to worry about this in the future.

URLs should have hypens in their regex patterns and underscores in their names

Mostly because Google says so, URLs should have hypens instead of underscores in their patterns.

Because the URL names in Django are Python strings, people usually use underscores for those.

So in this example: https://github.com/TwilioDevEd/automated-survey-django/blob/master/automated_survey/urls.py#L39-L41

It should look like this:

    url(r'^first-survey/',
        csrf_exempt(redirect_to_first_survey),
        name='first_survey'),

Change simple class-based views to functional views

Unlike with Flask, few people use class-based views in Django, instead opting for functional views.

Your QuestionResponseView is a big view, so I think it's good that it's a class-based view with helper methods.

Some other views are simpler, though, and should just be normal function-based views that Django developers will understand more easily:

  • QuestionView
  • SurveyView
  • SurveyResultsView

These views are better off looking like redirect_to_first_survey - functions that return their response.

Stuck on 500 error

I forked this Tutorial and am trying to get it to run locally. The current behavior is that, I send a text to the Twilio number and then it correctly texts me the first question of the survey. However, then when I text back, I don't get a response (should be the 2nd question of the survey) and I see a 500 error in Django. I can see that the second text message is being received by Django and, from the following function, it prints HELLO. However, it doesn't make it to YEP, so it appears to be erroring on answering_question = request.session.get('answering_question_id'), which seems like it is a problem with the session. I can see that there is a new session in the Django_session table created from my first text. I'm stuck on what is going wrong. request.session['answering_question_id'] is being set elsewhere in the code, but, my understanding, is if wasn't set, then answering_question would just be false, not an error. I'm stuck - any thoughts?

def redirects_twilio_request_to_proper_endpoint(request):
    print("HELLO")
    answering_question = request.session.get('answering_question_id')
    print("YEP")
    if not answering_question:
        print('1')
        first_survey = Survey.objects.first()
        redirect_url = reverse('survey',
        kwargs={'survey_id': first_survey.id})
   else:
       print('2')
       question = Question.objects.get(id=answering_question)
       redirect_url = reverse('save_response',
       kwargs={'survey_id': question.survey.id,
               'question_id': question.id})
  return HttpResponseRedirect(redirect_url)

Example error
[03/Jun/2022 03:34:36]"GET /automated-survey/first-survey/?ToCountry=US&ToState=CA&SmsMessageSid=SM9f799005f09308ae910a7c5af722bf76&NumMedia=0&ToCity=LOS+ANGELES&FromZip=95747&SmsSid=SM9f799005f09308ae910a7c5af722bf76&FromState=CA&SmsStatus=received&FromCity=ROSEVILLE&Body=Pink&FromCountry=US&To=%2B17472454008&ToZip=&NumSegments=1&ReferralNumMedia=0&MessageSid=SM9f799005f09308ae910a7c5af722bf76&AccountSid=ACef9b14863560f9a5b30961d21029d03c&From=%2B19164327401&ApiVersion=2010-04-01 HTTP/1.1" 500 139520

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.