User:Martyav/Apps/Tutorial

This tutorial will teach you how to use the Mediawiki Action API to build a Picture of the Day web app in Flask.

A complete version of the app is available online: Download the code from Github

Although this tutorial provides examples walking you through most of the code, it is good to have knowledge of the following items before you begin:


 * Python 3
 * Flask
 * Jinja
 * HTML
 * CSS
 * JSON

Setting up Python
This tutorial uses Python 3. You can download the latest Python version from here:


 * Python for Windows 7, 8, and 10
 * Python for Mac OS X

If your operating system is Windows XP, a Linux distro, or something else, see the Python beginner's guide for further instructions on installation.

Setting up Flask
Pip is a package manager that should have come with your Python installation. If you don't have it already, install it from the official Pip website. Once you've got it, open your command line interface of choice and run

Hello world in Flask
If you have everything successfully installed, the following script should display "Hello world" inside your web browser, at http://localhost:5000/:

hello.py

Picture of the day viewer
Now that we have everything set up and know that Flask is working, we can start writing our code for the Picture of the Day viewer.

Picture of the day, or POTD, is a featured image displayed daily on the home page of Wikipedia. We'll be hitting an endpoint containing a wiki template that changes every day, and using the data we find there to get at the image source. Then, we'll use this data to render a web page.

Create a new file, and name it app.py.

Getting today's date
The first order of business is simply knowing what day it is. Because POTD updates daily, we need today's date to access the archives and get at a stable version of the correct picture. To do this, we're going to have to import Python's class.

After adding the import statement, define a function, and name it index. We'll be using this function to render the web page soon. For now, add a variable containing the current date inside.

app.py

Adding Flask to app.py
Import the following from the  framework: ,  , and, of course,.

Look back at the  function in First steps. It contains some additional code that we need to get our app working.

allows us to call our app later and run it. tells our app which route to listen to, and what functions are associated with that route. triggers the app to fire up a local server, which we can use to pass data or render a web page.

After you add the code from  to , we'll be ready to make our API calls and do something with them.

app.py

Calling the Action API
The Action API works by sending back data in response to HTTP requests. We should import the Python Requests library, as it will make our lives easier. Despite the name, this library is quite distinct from our earlier import,. Flask's  is a class that allows   to communicate back and forth with the web page it is serving, while Python's   is for general communication via HTTP.

After importing, add two new variables:   and. We will use SESSION to make requests to the ENDPOINT url.

Now define a new function,. Wikipedia hosts the current Picture of the Day in several different places. This function will call on API:Images to request the picture embedded within the protected Picture of the Day page, for any given day. Then, it'll use the filename from API:Images, to call a helper function that uses API:Imageinfo to retrieve the image's source url. Define this helper function,.

Wikipedia's archives lists dates by [w:ISO_8601|ISO standard] format -- for instance, 2019-01-31, for 31 January, 2019. We can get the correct format by using the date method,. This gives us a correctly formatted date string.

Finally, alter  to call. Make  return. We'll be discussing the meaning of this call in the next section.

app.py

Displaying the page
Flask uses a directory named templates to hold files that contain some dynamic elements. When  is called, it finds the file named index.html inside this directory, serves it as a web page, and fills it with content based on the information passed along in.

Template directory
Create a new directory, and name it templates. Add a new file to it, and name it index.html.

Flask templates mostly contain HTML markup, but they also use Jinja to render dynamic content. Jinja markup looks like this --  -- and is used to inject Python variables or expressions into our basic page structure.

Add some basic HTML 5 boilerplate and a few elements to. Amongst our HTML scaffold is Jinja syntax indicating where the data from  will go.

templates/index.html

Static directory
Flask uses a directory, named static, to contain any helper files that stay the same throughout the lifecycle of the app. This is a useful place to put any stylesheets or additional scripts.

On the same level as  and , create a new directory, and name it static. Inside this directory, create a new file, and name it style.css.

Our stylesheet will be using some colors and visual motifs based on the Wikimedia Style Guide.

static/style.css

Making it interactive
works by responding to GET and POST requests along a designated route. If we add a form to our page, we can use the POST requests from it to allow users to browse through the Picture of the Day archives.

Go back to. Inside, add another div, for our new control scheme. This will have the class of, and will contain our form. The form will have submit button inputs, each with a designated value: Back or Next. When either button is selected, the form will submit a POST request, and the selected value will be passed back to. This will allow the user to navigate backward or forward through the archives

The Picture of the Day archives start on 14 May 2004, and range forward to the current date. Jinja allows us to add conditional formatting to our page, so that if the next date would be out of range, the button corresponding to that date can be automatically disabled. However, from inside, we don't have full access to the   class. We need a bit of a hack: because we can't create a separate date object to compare our date against, we must make a comparison against the properties on our current date, or against a string.

templates/index.html

Since we've added new HTML elements, we need to style them.

static/style.css

Now we need to update  to navigate through the archives.

Pull out the date variable from, and put it in module scope, so that its initialized on the same level as   and.

We need to accurately add or subtract from this date. Import Python's so we can perform math on it.

Now, define a  function. It will be in charge of setting the date we present to the user. If the date is beyond the valid date range (i.e., before 14 May 2004 or after today), execution should cut short and the function should not return anything.

After defining, update the "/" route to handle POST requests from our form.

If "/" receives a GET or POST request,  is called. We already have a code path for GET --  renders the page. Create another code path for the POST from our form, and have it call.

app.py

Final notes
The finished app should look something like this:



If you are curious about adding descriptive text from the POTD page, there are several ways: API:Search provides  of text off a page, which can be used as a link preview, while   can be used to obtain the whole parsed text from articles on Wikis that have the Cirrussearch extension to API:Search installed. For example, the query https://en.wikipedia.org/wiki/Template:POTD_protected/2019-02-01?action=cirrusdump returns JSON containing the plaintext from 1 February, 2019's Picture of the Day. It can be found within the first index of.