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