واجهة برمجة التطبيقات:عارض صورة اليوم المختارة

From mediawiki.org
Jump to navigation Jump to search
This page is a translated version of the page API:Picture of the day viewer and the translation is 27% complete.

نظرة عامة

سوف تتعلم في هذا التدريب التعليمي كيفية تصميم عارض ويكيبيديا:صورة اليوم المختارة مستخدما واجهة برمجة تطبيقات ميدياويكي من النوع Action.

تنزيل الكود المصدري من غت هب ابحث عن التطبيق في مصنع الأدوات

سوف يعلمك هذا التدريب التعليمي كيفية تنفيذ هذا مستخدما:

عملية خطوة بخطوة لتصميم هذا التطبيق

الخطوة 1: تأسيس بيئة تطوير البرمجيات مستخدما بايثون وفلاسك

تأسيس بايثون

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

See the Python beginner's guide for further instructions on installing Python on different operating systems.

تأسيس فلاسك

Pip is a package manager that you can use to install Flask: pip install flask. If you don't have pip already, install it from the official Pip website.


الخطوة 2: إنشاء تطبيق فلاسك بسيط

If you have everything successfully installed, place the following script in app.py, inside your project folder: $HOME/picture-of-the-day-viewer/app.py. When you run it, it should display "Hello world" at http://localhost:5000/:

#!/usr/bin/python3

from flask import Flask
APP = Flask(__name__)

@APP.route("/")
def hello():
  return "Hello World!"

if __name__ == "__main__":
  APP.run()

الخطوة 3: عارض صورة اليوم المختارة

Now that you have everything set up, you can start writing 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. You'll be getting the picture from a wiki template that changes every day.

جلب تاريخ اليوم

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

Next, define a new function, index(). Index() will render the web page and pass along any data associated with our API calls. See #Displaying the page for more information on the index.html file we'll be using as a template. For now, index() should contain a variable holding the current date. We'll be using it soon to compose a query to access the POTD.

#!/usr/bin/python3
from datetime import date
from flask import Flask, render_template

APP = Flask(__name__)

@APP.route("/")
def index():
  todays_date = date.today().isoformat()

if __name__ == "__main__":
  APP.run()

استدعاء واجهة برمجة التطبيقات التي تحمل اسم Action

The Action API works by sending back data in response to HTTP requests. To do so, you will import the Python Requests library.

Next add two new variables: SESSION = requests.Session() and ENDPOINT = "https://en.wikipedia.org/w/api.php". You will use the SESSION object to make requests to the ENDPOINT url.

In a new function, fetch_potd(), call واجهة برمجة التطبيقات:صور to request the picture embedded within a protected POTD page (example). From this call, use the picture's filename to call واجهة برمجة التطبيقات:معلومات_صورة , and retrieve the image's source url. In this example, the second API call is handled in the helper function, fetch_image_src().

Wikipedia's archives lists dates by ISO standard format -- for instance, 2019-01-31, for 31 January, 2019. You can get the correct format by using the date method, isoformat().

def fetch_potd(cur_date):
  date_iso = cur_date.isoformat()
  title = "Template:POTD_protected/" + date_iso

  params = {
    "action": "query",
    "format": "json",
    "formatversion": "2",
    "prop": "images",
    "titles": title
  }

  response = SESSION.get(url = ENDPOINT, params = params)
  data = response.json()
  filename = data["query"]["pages"][0]["images"][0]["title"]
  image_page_url = "https://en.wikipedia.org/wiki/" + title
    
  image_data = {
    "filename": filename,
    "image_page_url": image_page_url,
    "image_src": fetch_image_src(filename),
    "date": date_iso
  }

  return image_data

def fetch_image_src(filename):
  params = {
    "action": "query",
    "format": "json",
    "prop": "imageinfo",
    "iiprop": "url",
    "titles": filename
  }

  response = SESSION.get(url = ENDPOINT, params = params)
  data = response.json()
  page = next(iter(data["query"]["pages"].values()))
  image_info = page["imageinfo"][0]
  image_url = image_info["url"]

  return image_url

Finally, alter index() to call fetch_potd(). Import render_template from flask, and make index() return render_template("index.html", data=data).

{anchor|Displaying_the_page}

عرض الصفحة

A screenshot of the Picture of the Day Viewer available on the MediaWiki Code Samples repo, at GitHub
Picture of the Day Viewer app screenshot

Flask templates mostly contain HTML markup, but they also use Jinja to render dynamic content. Jinja markup looks like this -- {{ variable }} -- 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 index.html. Make sure to save it to a directory within your app, named /templates.

<!DOCTYPE html>
<html lang="en">
  <meta charset="utf-8">
  <title>Picture of the Day</title>
  <link rel="stylesheet" href="/static/style.css">

  <main>
    <h1>Picture of the day:</h1>
    <div class="card">
      <div class="potd">
        <h2>{{ data.filename }}</h2>
        <a href="{{ data.image_page_url }}" target="blank">
        <figure>
          <img src="{{ data.image_src }}">
          <figcaption>View on Wikipedia</figcaption>
        </figure>
        </a>
      </div>
      <div class = "date-container">
      <div class = "current-date">{{ data.date.strftime("%d %B %Y") }}</div>
    </div>
    </div>
</main>

تحويلها إلى صفحة تفاعلية

Add a ‎<form> element to index.html, and give it the following submit button inputs: Back and Next. When either button is selected, the form will submit a POST request, and the selected value will be passed back to app.py. This will allow users to browse through the Picture of the Day archives.

Next, update app.py with a change_date() function, for setting the date presented to the user. Also extend the / route to handle POST requests from the form. To allow app.py to read the POST request message, import Flask's Request class.

The complete Python and HTML code:

$HOME/picture-of-the-day-viewer/app.py
"""
    app.py
    MediaWiki Action API Code Samples

    Fetches Wikipedia Picture of the Day (POTD) and displays it on a webpage.
    Also allows users to go backward or forward a date to view other POTD.

    MIT License
"""

#!/usr/bin/python3

from datetime import date, timedelta
from flask import Flask, render_template, request
import requests

APP = Flask(__name__)
SESSION = requests.Session()
ENDPOINT = "https://en.wikipedia.org/w/api.php"
CURRENT_DATE = date.today()

@APP.route("/", methods=["GET", "POST"])
def index():
    """
    Requests data from Action API via 'fetch_potd' function & renders it on the
    index page accessible at '/'
    """

    if request.method == "POST":
        change_date()

    data = fetch_potd(CURRENT_DATE)

    return render_template("index.html", data=data)

def change_date():
    """
    Changes current date in response to input from the web form
    """

    global CURRENT_DATE

    user_input = request.form["change_date"]
    new_date = CURRENT_DATE
    last_date = date.today()
    first_date = date(year=2004, month=5, day=14)

    if user_input == "← Back":
        new_date = new_date - timedelta(days=1)
    elif user_input == "Next →":
        new_date = new_date + timedelta(days=1)

    if new_date > last_date or new_date < first_date:
        return

    CURRENT_DATE = new_date

def fetch_potd(cur_date):
    """
    Returns image data related to the current POTD
    """

    date_iso = cur_date.isoformat()
    title = "Template:POTD protected/" + date_iso

    params = {
        "action": "query",
        "format": "json",
        "formatversion": "2",
        "prop": "images",
        "titles": title
    }

    response = SESSION.get(url=ENDPOINT, params=params)
    data = response.json()

    filename = data["query"]["pages"][0]["images"][0]["title"]
    image_src = fetch_image_src(filename)
    image_page_url = "https://en.wikipedia.org/wiki/Template:POTD_protected/" + date_iso

    image_data = {
        "filename": filename,
        "image_src": image_src,
        "image_page_url": image_page_url,
        "date": cur_date
    }

    return image_data

def fetch_image_src(filename):
    """
    Returns the POTD's image url
    """

    params = {
        "action": "query",
        "format": "json",
        "prop": "imageinfo",
        "iiprop": "url",
        "titles": filename
    }

    response = SESSION.get(url=ENDPOINT, params=params)
    data = response.json()
    page = next(iter(data["query"]["pages"].values()))
    image_info = page["imageinfo"][0]
    image_url = image_info["url"]

    return image_url

if __name__ == "__main__":
    APP.run()
$HOME/picture-of-the-day-viewer/templates/index.html
<!DOCTYPE html>
<html lang="en">
  <meta charset="utf-8">
  <title>Picture of the Day</title>
  <link rel="stylesheet" href="/static/style.css">

  <main>
    <h1>Picture of the day:</h1>
    <div class="card">
      <div class="potd">
        <h2>{{ data.filename }}</h2>
        <a href="{{ data.image_page_url }}" target="blank">
        <figure>
          <img src="{{ data.image_src }}">
          <figcaption>View on Wikipedia</figcaption>
        </figure>
        </a>
      </div>
      <div class="date-container">
        <time class="current-date">{{ data.date.strftime("%d %B %Y") }}</time>
        <div class="date-navigator">
          <form action="/" method="POST">
            {% if data.date.strftime("%d %B %Y") == "14 May 2004" %}
            <input type="submit" name="change_date" value="← Back" disabled>
            {% else %}
            <input type="submit" name="change_date" value="← Back">
            {% endif %}
            {% if data.date == data.date.today() %}
            <input type="submit" name="change_date" value="Next →" disabled>
            {% else %}
            <input type="submit" name="change_date" value="Next →">
            {% endif %}
          </form>
        </div>
      </div>
    </div>
</main>

تحديد نمط تطبيقك

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. Our stylesheet will be using some colors and visual motifs based on the Wikimedia Style Guide. Place a CSS file in $HOME/picture-of-the-day-viewer/static/style.css.

$HOME/picture-of-the-day-viewer/style.css
html {
    margin: 0;
    padding: 0;
    height: 100vh;
    width: 100vw;
}

body {
    margin: 0;
    background: #f8f9fa; /* light grey */
    font-family: Arial, Helvetica, sans-serif;
    font-size: 16px;
}

h1 {
    margin: 0;
    padding: 12px;
    background: #2a4b8d; /* dark blue */
    color: #ffffff;
}

h2 {
    margin-top: 8px;
    padding: 12px;
    font-size: 1em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    background: #f3f9ff; /* very light blue */
    border: 1px solid #2a4b8d; /* dark blue */
}

a {
    color: #3366cc; /* blue */
}

p {
    margin: 8px;
}

.card {
    position: relative;
    margin: auto;
    min-width: 200px;
    max-width: 67vw;
    height: 90vh;
    background: #ffffff;
    border-radius: 8px;
    box-shadow: 3px 6px 10px rgba(0, 0, 0, 0.16);
}

.potd {
    width: inherit;
    height: 60vh;
}

figure {
    width: 100%;
    margin: auto;
    text-align: center;
}

figure img {
    display: block;
    margin: 12px auto; 
    max-width: 64vw;
    max-height: 50vh;
    border: 1px solid#3366cc; /* blue */
}

figure a {
    margin: 8px;
}

.date-container {
    display: block;
    position: absolute;
    bottom: 0;
    left: 0;
    right:0;
    text-align: center;
    font-weight: bold;
}

.current-date {
    margin: 16px auto;
    font-size: 2em;
    background: #ffffff;
    color: #72777d; /* grey */
}

الخطوات التالية

  • Got questions about this tutorial? Ask here on Discourse.
  • Contribute a demo app that you have developed using the MediaWiki API to this code samples repository.
  • Learn some ways to add descriptive text from the Picture of the day page:
    • API:Search provides snippets which can be used as a link preview
    • action=cirrusdump can be used to obtain the whole parsed text from articles on Wikis that have the Cirrussearch extension installed (see example).

انظر أيضا