App: Subscribe

Welcome to the documentation for the Subscribe App. The subscribe app is the central app for this Django project.

The subscribe app handles the following:

  • Frontend: The subscribe app has the logic for all the Views that are used to render the complete frontend website

  • Models: The subscribe app also defines the main model - Subscribe - that manages the newsletter subscriptions

  • Tasks: In the backend, Warmmail uses Luigi tasks to update data every day as well as to send emails to subscribed users

There are complete details available about these functionalities below.

Frontend: Views

warmmail.subscribe.views.index(request)

Base view - the entry page for the website. Renders a page with a search box allowing the user to search for a city or location

Parameters

request – The HTTP request

Returns

Renders the page


warmmail.subscribe.views.findplace(request)

Renders the page showing a list of all the locations. The user is allowed to submit a text name for the location including any significant address details (like city, country, etc.). Using the API exposed from geonames.org => the system renders a list of all the possible locations from which the user may select a location. Selecting a location means selecting a lat/long which is used for the subsequent steps in the journey. The function calls the Geonames.org API and requires an environment variable as follows: GEONAMES_API_USERNAME=”<geonames-username>”

Parameters

request – HTTP request, expects a POST request with param: search_term

Returns

Renders the page


warmmail.subscribe.views.selectplace(request, lat, long)

Renders the page showing the current AQI stats and historic graphs for the selected location. The page also gives a button to the user to “subscribe” to this report. The function calls the AQICN API and requires an environment variable as follows: AQICN_TOKEN=”<token from aqicn>”

Parameters
  • request – HTTP GET Request

  • lat – The selected latitute (passed automatically from findplace)

  • long – The selected longiture (passed automatically from findplace)

Returns

Renders page with the report for the location with a button for user to subscribe.


warmmail.subscribe.views.subscribeplace(request, city, dominentpol)

The last step for the subsription - this view renders a page that allows the user to subscribe to the chosen report. It shows a form to the user which has the following options: * email address - with generic verification * city - auto-populated basis report selected - non editable * time of day - gives option to user to receive report in Morning / Afternoon / Evening * timezone

Parameters
  • request – HTTP GET Request

  • city – The name of the city selected for the report - auto-populated by the previous page

  • dominentpol – The name of the dominent pollutant in that city - this is a hidden field in the form which is used by the backend report generation

Returns

Renders the HTML page


warmmail.subscribe.views.confirmsubscription(request)

A simple page which saves the subscription request and sends out an email verification link The email is sent via Sendgrid and requires an environment variable with the SendGrid API token: SENDGRID_API_KEY=”<the token from Sendgrid>”

Parameters

request – HTTP Post request with fields from subscribeplace view

Returns

Sends out an email using SendGrid


warmmail.subscribe.views.verifyemail(request, subscription_id, token)

The view that users come to after clicking on the email verification link. It verifies the subscription to allow processing from next day.

Parameters
  • request – HTTP Get Request

  • subscription_id – Available from the URL

  • token – Available from the URL

Returns

Renders the HTML page


Models

warmmail.subscribe.models.Subscription(*args, **kwargs)

The main subscription model with below fields. Constraints: Only 1 subscription allowed per email + city combination.

Variables
  • email – The email address of the user

  • verified – A boolean flag indicating if the subscription has been verified

  • temp_token – Temporary token generated for verification

  • city – The name of the city selected

  • dominentpol – the name of the dominent pollutant for that city

  • next_email_date – the date when the next email has to be sent

  • created_date – the date when this subscription was created

  • update_date – the date when this subscription was last updated

  • status – an ENUM if subscription is active or not


Tasks

warmmail.subscribe.tasks_fetch.DownloadAQI(*args, **kwargs)

Task that downloads the daily AQI report from aqicn.org. No inputs required.


warmmail.subscribe.tasks_fetch.ConvertAQIFileToParquet(*args, **kwargs)

Task to clean up the file fetched from AQICN.org and save as a Parquet (using Salted Output).


warmmail.subscribe.tasks_send.GenerateEmails(*args, **kwargs)

Task to generate the html content to be sent via email. Uses Django’s render to string functionality.

Parameters
  • city – name of the city for which report has to be generated

  • pol – name of the dominant pollutant for that city

  • date – the date for which report has to be generated


warmmail.subscribe.tasks_send.CheckForPendingEmails(*args, **kwargs)

Task to check for pending emails. This uses a “RowFilterOutput” which checks for rows in the database which have the “next_email_date” in the past. For each such row found (city + dominent pollutant fetched frm the DB), the task requires a GenerateEmails task.


Helper Functions for Tasks

warmmail.subscribe.tasks_send.UrlParameter(default=<object object>, is_global=False, significant=True, description=None, config_path=None, positional=True, always_in_help=False, batch_method=None, visibility=<ParameterVisibility.PUBLIC: 0>)

Descriptor to ensure that a file name is url safe i.e. quoted


warmmail.subscribe.tasks_send.RowFilterTarget(model, **kwargs)

A target class for filters on rows Checks to see if any rows exist that satisfy the given filter If no results found, return True (i.e. task is complete), else False False - causes Luigi to think that task is pending and runs it + check requirements


warmmail.subscribe.tasks_send.RowFilterOutput(model, entries_param=None, field=None, **kwargs)

Descriptor for the output method Returns a “RowFilterTarget” for the Luigi task Additional feature: in case there are values returned from the filter, descriptor can accept name of fields and parameters on the parent class and update the parent class parameters - this ensures that downstream tasks do not need to call the database again