API: Mai duba hutu

This page is a translated version of the page API:Holidays viewer and the translation is 96% complete.

Bayani

Wannan koyawa ta ƙunshi yadda ake ƙirƙira ƙa'idar demo wacce ke ɗaukar ranaku da bukukuwan ranar da aka bayar daga Wikipedia, tare da zaɓi don shiga don ƙara sabbin ranaku.

Kayan aiki da fasahar da ake amfani da su don ƙirƙirar ƙa'idar demo sune:

Tsarin mataki-mataki don gina wannan aikace-aikacen

Mataki na 1: Sanya Python da yanayin ci gaban Flask =

Python ya zo an riga an shigar dashi akan yawancin rabawa na Linux. For other operating systems, see the Python beginner's guide for installation instructions.

Shigar da Flask ta hanyar gudu pip install flask. Idan ba ku da Pip, samo shi daga gidan yanar gizon Pip na hukuma


Mataki na 2: Ƙirƙiri aikace-aikacen Flask mai sauƙi =

A cikin kundin adireshin gidan ku, ƙirƙiri babban fayil mai suna holidays-viewer wanda zai ƙunshi duk fayilolin app ɗin. A cikin babban fayil ɗin, ƙirƙiri fayil mai suna app.py kuma sanya lambar mai zuwa a ciki:

#!/usr/bin/python3

from flask import Flask

APP = Flask(__name__)

@APP.route("/")
def list_holidays():
  return "Holidays and observances"

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

Gudanar da app ta amfani da umarnin python app.py kuma buɗe http://127.0.0.1:5000/ akan burauzar ku. Ya kamata ku ga an nuna "Holidays and observances".

Mataki na 3: Ƙirƙiri shimfidar tushe =

App ɗin zai sami shafuka huɗu: shafin gida, shafin bincike, shafin shiga da kuma ƙara shafi. Kowane shafi zai sami wasu abubuwan gama gari, don haka muna buƙatar ƙirƙirar fayil ɗin shimfidar wuri mai suna layout.html don ya ƙunshi waɗannan abubuwan.

Note that we are using Bootstrap classes to apply a specific CSS style to an element, Materialize icons for the add, search and arrow-back icons, and Jinja to extend the base layout to other pages and to pass variables from Python to HTML.

$HOME/holidays-viewer/templates/layout.html
<title>Holidays</title>

<link rel="stylesheet" href="//tools-static.wmflabs.org/cdnjs/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css">
<link rel="stylesheet" href="//tools-static.wmflabs.org/fontcdn/css?family=Material+Icons">

<div class="content bg-secondary rounded m-auto">
  <div class="title-bar bg-primary-dark text-white pl-2">
    <small>Holidays and observances</small>
  </div>
  <div class="header-bar bg-primary text-white shadow p-2">
    {% if request.path != url_for('list_holidays') %}
    <a class=" btn text-white" href="{{ url_for('list_holidays') }}">
      <i class="material-icons">arrow_back</i>
    </a>
    {% endif %}
    <h5>{{header}}</h5>
    <div class="filler"></div>
    <a class="btn text-white" href="{{ url_for('add') }}">
      <i class="material-icons">add</i>
    </a>
    <a class="btn text-white" href="{{ url_for('search') }}">
      <i class="material-icons">search</i>
    </a>
  </div>
  {% with messages = get_flashed_messages() %}
    {% if messages %}
    <div class="alert alert-primary mb-0" role="alert">
      {% for message in messages %}
        {{ message }}
      {% endfor %}
      <button type="button" class="close" data-dismiss="alert" aria-label="Close">
        <span aria-hidden="true">×</span>
      </button>
    </div>
    {% endif %}
  {% endwith %}
  {% block content %}{% endblock %}
</div>
<script src="//tools-static.wmflabs.org/cdnjs/ajax/libs/twitter-bootstrap/4.0.0/js/bootstrap.min.js"></script>

Sauran shafuka za su tsawaita layout.html ta amfani da lambar da ke ƙasa:

{% extends "layout.html" %}
{% block content %}
  <!--content for other pages-->
{% endblock %}

Mataki na 4: Lissafin hutu =

Tushen url na ƙa'idar zai haifar da aikin list_holidays(...), wanda ke jera ranakun hutu na takamaiman kwanan wata.

A cikin aikin da kuma cikin aikace-aikacen, holidays_date yana nufin ranar hutu da za a jera, header yana nufin taken shafin, kuma holidays_html yana nufin html wanda ya ƙunshi hutun da za a jera. Hakanan za mu yi amfani da aikin render_template(...) wanda ke samar da takamaiman fayil na html daga kundin tsarin samfuri. Sauran gardama da aka ƙara zuwa aikin sune masu canji waɗanda ake wucewa zuwa fayil ɗin html.

A cikin app.py, sabunta list_holidays() tare da lambar da ke ƙasa:

@APP.route('/', methods=['GET', 'POST'])
@APP.route('/<holidays_date>', methods=['GET', 'POST'])
def list_holidays(holidays_date=None):
    holidays_html = ""

    return render_template("index.html", header=holidays_date.replace('_', ' '),
                           holidays_html=holidays_html)
$HOME/holidays-viewer/templates/index.html
{% extends "layout.html" %}
{% block content %}
  <div class="holidays-html">
    {{holidays_html|safe}}
  </div>
{% endblock %}

= Samu ranar yau

Idan ba a bayyana kwanan wata ba, za mu jera ranakun hutu na ranar yau. Don amfani da tsarin datetime na Python don samun kwanan wata, shigo da tsarin tare da from datetime import datetime sannan ƙirƙirar aikin mai zuwa:

def get_todays_date():
    current_month = datetime.now().strftime('%B')
    current_day = datetime.now().strftime('%d')
    if current_day.startswith('0'):
        current_day = current_day.replace('0', '')

    return current_month + "_" + current_day

Kira aikin a cikin list_holidays(...):

if holidays_date is None:
        holidays_date = get_todays_date()

= Samu hutun da za a jera

= Samu hutun da za a jera

Wikipedia yana da shafi na kowace rana kuma bukukuwan suna ƙarƙashin sashe mai suna "Holidays and observances". Don samun hutu, muna buƙatar samun lambar sashin sa da abun cikin wannan lambar sashe.

Ƙirƙiri aiki don samun lambar sashe ta amfani da API:Parse :

def get_holidays_section(url, page, date_to_get):
    params = {
        "format":"json",
        "action":"parse",
        "prop":"sections",
        "page":page
    }

    response = S.get(url=url, params=params)
    data = response.json()
    sections = data['parse']['sections']
    section_number = "0"

    for index, value in enumerate(sections):
        if value['anchor'] == "Holidays_and_observances":
            section_number = index + 1

        if url == TEST_URL:
            if value['anchor'] == date_to_get:
                section_number = index + 1

    return section_number

Ƙirƙiri wani aiki da ake kira get_holidays(...) don samun hutu a wannan sashe ta amfani da API:Parse shima, sannan a kira ayyukan a cikin list_holidays(...):

section_number = get_holidays_section(URL, holidays_date, None)
holidays = get_holidays(URL, holidays_date, section_number)
holidays_html = holidays

Sabunta hanyoyin hutu

HTML na hutun da aka dawo ya ƙunshi hanyoyin ciki waɗanda ke nuna waɗancan bukukuwan, misali "/wiki/New_Years_Day". Muna buƙatar tsara "//en.wikipedia.org" zuwa waɗannan hanyoyin haɗin yanar gizon ta amfani da jQuery don sanya su hanyoyin haɗin waje a cikin app ɗin mu, da sanya su buɗe a cikin sabon shafin. Don yin haka, ƙara lambar zuwa $HOME/holidays-viewer/static/update-links.js:

$( document ).ready( function() {
    $( ".holidays-html a" ).attr( "target", "_blank" );

    $( ".holidays-html a" ).attr( "href", function( i, href ) {
      return "//en.wikipedia.org" + href;
    });
});

Sannan ƙara jQuery zuwa layout.html ta amfani da:

<script src="//tools-static.wmflabs.org/cdnjs/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="static/update-links.js"></script>


Mataki na 5: Nemo hutun wasu kwanakin =

Don samun hutu don wasu kwanakin, ƙirƙiri hanyar bincike don nuna fom da ke tattara wata da rana don bincika:

@APP.route("/search")
def search():

    return render_template("search.html", header="Search date")
$HOME/holidays-viewer/templates/search.html
{% extends "layout.html" %}
{% block content %}
  <div class="instructions m-3">
    Search for holidays by date
  </div>
  <div class="base rounded shadow bg-white m-3">
    <form class="m-auto" action="/" method="POST">
      <fieldset>
        <div class="label-field">Select Month</div>
        <select class="bg-secondary mb-5 border-0" name="monthList">
          <option value="January">January
          <option value="February">February
          <option value="March">March
          <option value="April">April
          <option value="May">May
          <option value="June">June
          <option value="July">July
          <option value="August">August
          <option value="September">September
          <option value="October">October
          <option value="November">November
          <option value="December">December
        </select>
      </fieldset>
      <fieldset>
        <div class="label-field">Select Day</div>
        <select class="bg-secondary mb-5 border-0" name="dayList">
          <option value="1">1
          <option value="2">2
          <option value="3">3
          <option value="4">4
          <option value="5">5
          <option value="6">6
          <option value="7">7
          <option value="8">8
          <option value="9">9
          <option value="10">10
          <option value="11">11
          <option value="12">12
          <option value="13">13
          <option value="14">14
          <option value="15">15
          <option value="16">16
          <option value="17">17
          <option value="18">18
          <option value="19">19
          <option value="20">20
          <option value="21">21
          <option value="22">22
          <option value="23">23
          <option value="24">24
          <option value="25">25
          <option value="26">26
          <option value="27">27
          <option value="28">28
          <option value="29">29
          <option value="30">30
          <option value="31">31
        </select>
      </fieldset>
      <button type="submit" name="search" class="bg-primary btn btn-submit text-white">Submit</button>
    </form>
  </div>
{% endblock %}

Da zarar an ƙaddamar da fom ɗin nema, sabunta holidays_date don zama ranar da aka shigar. Don yin haka, ƙara lambar zuwa list_holidays(...):

if request.method == 'POST' and 'search' in request.form:
        search_month = str(request.form.get('monthList'))
        search_day = str(request.form.get('dayList'))
        holidays_date = search_month +"_"+search_day

Mataki na 6: Ƙara hutu =

Shafin da za mu ƙara sabon hutu zuwa gare shi yana da kariya daga gyarawa daga masu amfani da ba a san su ba, don haka muna buƙatar shiga ta amfani da API:Login#clientlogin da farko.

Don ƙara hutu, aika buƙatu zuwa API:Edit tare da kwanan wata da bayanin biki. Gyaran yana ƙara sabbin ranaku zuwa wannan shafin akan Gwajin Wikipedia: Sandbox/Holidays_and_observances. Wannan don hana ƙara hutun gwaji zuwa Wikipedia na Ingilishi.

Bayan an ƙara biki, a tura zuwa shafin farko inda za a nuna bukukuwan da aka ƙara, kuma a tsara su da ƙarfi don bambanta su da ainihin bukukuwan. Don samo hutun gwaji tare da ainihin hutu, sabunta list_holidays(...):

test_section_number = get_holidays_section(TEST_URL, TEST_PAGE, holidays_date)
test_holidays = get_holidays(TEST_URL, TEST_PAGE, test_section_number)

holidays_html = test_holidays + holidays
flash("Holidays added through this app are in bold")
$HOME/holidays-viewer/templates/login.html
{% extends "layout.html" %}
{% block content %}
  <div class="instructions m-3">
    <p>You need to login to Wikipedia in order to add a new holiday
  </div>
  <div class="base rounded shadow bg-white m-3">
    <form class="m-auto" action="/login" method="POST">
      <div class="form-group">
        <div class="form-field">
          <div class="label-field">Username</div>
          <input class="bg-secondary mb-5 border-0" name="username">
        </div>
        <div class="form-field">
          <div class="label-field">Password</div>
          <input class="bg-secondary mb-5 border-0" type="password" name="password">
        </div>
      </div>
      <button type="submit" name="login" class="bg-primary btn btn-submit text-white">Login</button>
    </form>
  </div>
{% endblock %}
$HOME/holidays-viewer/templates/add.html
{% extends "layout.html" %}
{% block content %}
  <div class="instructions m-3">
    <p>Add a new test holiday
  </div>
  <div class="base rounded shadow bg-white m-3">
    <form class="m-auto" action="" method="POST">
      <div class="form-group">
        <div class="form-field">
          <div class="label-field">Date [MMMM dd]</div>
          <input class="bg-secondary border-0 mb-5" name="date" placeholder="e.g April 1">
        </div>
        <div class="form-field">
          <div class="label-field">Description</div>
          <input class="bg-secondary border-0 mb-5" name="description" placeholder="e.g April fools' day">
        </div>
      </div>
      <button type="submit" name="add" class="bg-primary btn btn-submit text-white">Add</button>
    </form>
  </div>
{% endblock %}

Mataki na 7: Salon app =

Don ƙara ƙarin salo a app ɗin mu, ƙirƙiri salon salo mai suna style.css kuma ku haɗa shi daga layout.html ta ƙara <link rel="stylesheet" href="static/style.css">.

$HOME/holidays-viewer/static/style.css
.content {
    width: 420px;
    min-height: 100vh;
}

.holidays-html{
    overflow-y: auto;
    overflow-x: hidden;
    max-height: 88vh;
    scrollbar-width: thin;
}

.base {
    height: 400px;
    display: flex;
}

input, select {
    width: 300px;
    height: 40px;
}

.btn-submit {
    width: 300px;
}

.btn {
    cursor: pointer;
    align-content: center;
    background-color: transparent;
}

.bg-primary {
    background-color: #36c !important;
}

.bg-primary-dark {
    background-color: #2a4b8d !important;
}

.bg-secondary {
    background-color: #eaecf0 !important;
}

.header-bar {
    height: 48px;
    display: flex;
    flex: 1;
    align-items: center;
}

.filler {
    flex-grow: 1;
    text-align: center
}

h2 {
    display: none;
}

ul {
    margin: 5px;
    padding: 0;
}

li  {
    list-style-type: none;
    margin-bottom: 4px;
    background-color: white;
    padding: 8px;
    border-radius: 5px;
}

ul li li {
    box-shadow: 0 .5rem 1rem rgba(0,0,0,.15);
}

Tsarin aikace-aikacen

A wannan gaba, tsarin aikace-aikacenku yakamata ya kasance:

$HOME/holidays-viewer
├── templates/
│   └── add.html
    └── index.html
    └── layout.html
    └── login.html
    └── search.html
├── static/
│   └── style.css
    └── update-links.js
├── app.py

Tare da app.py da layout.html kasancewa:

$HOME/holidays-viewer/app.py
#!/usr/bin/python3

"""
    app.py

    MediaWiki API Demos

    Mai duba hutu: ƙa'idar demo mai ɗaukar ranaku hutu daga Wikipedia tare da zaɓuɓɓuka don bincika hutun wasu ranaku, da shiga don ƙara sabbin ranaku.

    lasisin MIT
"""

from datetime import datetime
from flask import Flask, render_template, flash, request, url_for, redirect
import requests


APP = Flask(__name__)
APP.secret_key = 'your_secret_key'

URL = "https://en.wikipedia.org/w/api.php"
TEST_URL = "https://test.wikipedia.org/w/api.php"
TEST_PAGE = "Sandbox/Holidays_and_observances"
S = requests.Session()
IS_LOGGED_IN = False

@APP.route('/', methods=['GET', 'POST'])
@APP.route('/<holidays_date>', methods=['GET', 'POST'])
def list_holidays(holidays_date=None):
    """ Ya lissafa ranakun hutu don kwanan wata ko kwanan wata na al'ada
    """

    if holidays_date is None:
        holidays_date = get_todays_date()

    # Update date to a custom date
    if request.method == 'POST' and 'search' in request.form:
        search_month = str(request.form.get('monthList'))
        search_day = str(request.form.get('dayList'))
        holidays_date = search_month +"_"+search_day

    # Get the section numbers for the holidays on Wikipedia and for those on the test page
    section_number = get_holidays_section(URL, holidays_date, None)
    test_section_number = get_holidays_section(TEST_URL, TEST_PAGE, holidays_date)

    holidays = get_holidays(URL, holidays_date, section_number)
    test_holidays = get_holidays(TEST_URL, TEST_PAGE, test_section_number)

    holidays_html = test_holidays + holidays
    flash('Holidays added through this app are in bold')

    return render_template("index.html", header=holidays_date.replace('_', ' '),
                           holidays_html=holidays_html)


def get_todays_date():
    """ Samu watan a matsayin rubutu da rana ta yanzu a matsayin lamba
    """

    current_month = datetime.now().strftime('%B')
    current_day = datetime.now().strftime('%d')
    if current_day.startswith('0'):
        current_day = current_day.replace('0', '')

    return current_month + "_" + current_day

def get_holidays_section(url, page, date_to_get):
    """ Samu lambar sashe don hutu akan Wikipedia da hutu akan shafin gwaji
    """

    params = {
        "format":"json",
        "action":"parse",
        "prop":"sections",
        "page":page
    }

    response = S.get(url=url, params=params)
    data = response.json()
    sections = data['parse']['sections']
    section_number = "0"

    for index, value in enumerate(sections):
        if value['anchor'] == "Holidays_and_observances":
            section_number = index + 1

        if url == TEST_URL:
            if value['anchor'] == date_to_get:
                section_number = index + 1

    return section_number

def get_holidays(url, page, section_number):
    """ Samu html wanda ya ƙunshi biki
    """

    params = {
        "format":"json",
        "action":"parse",
        "prop":"text",
        "page": page,
        "section": section_number,
        "disableeditsection":1
    }

    response = S.get(url=url, params=params)
    data = response.json()
    text = data['parse']['text']['*']

    return text

@APP.route("/search")
def search():
    """ Bincika hutu na kwanakin al'ada
    """

    return render_template("search.html", header="Search date")

@APP.route("/login", methods=['GET', 'POST'])
def login():
    """ Shiga Wikipedia
    """

    if request.method == 'POST' and 'login' in request.form:
        params_0 = {
            "action": "query",
            "meta": "tokens",
            "type": "login",
            "format": "json"
        }

        response = S.get(url=URL, params=params_0)
        data = response.json()

        login_token = data['query']['tokens']['logintoken']

        params_1 = {
            "action": "clientlogin",
            "username": str(request.form.get('username')),
            "password": str(request.form.get('password')),
            "loginreturnurl": "http://127.0.0.1:5000/login",
            "logintoken": login_token,
            "format": "json"
        }

        response = S.post(url=URL, data=params_1)
        data = response.json()

        if data['clientlogin']['status'] != 'PASS':
            flash('Oops! Something went wrong -- ' + data['clientlogin']['messagecode'])
        else:
            global IS_LOGGED_IN
            IS_LOGGED_IN = True
            flash('Login success! Welcome, ' + data['clientlogin']['username'] + '!')
            return redirect(url_for('add'))

    return render_template("login.html", header="Login")

@APP.route("/add", methods=['GET', 'POST'])
def add():
    """ Ƙara sabon biki zuwa shafin gwaji kuma a tura zuwa ranakun hutun don nuna ƙarin hutu
    """

    if not IS_LOGGED_IN:
        return redirect(url_for('login'))

    if request.method == 'POST' and 'add' in request.form:

        # Wiki markup to format the added holiday's text as a list item and in bold
        holiday_text = "* '''" + str(request.form.get('description')) + "'''"
        date = str(request.form.get('date'))

        params_2 = {
            "action": "query",
            "meta": "tokens",
            "format": "json"
        }

        response = S.get(url=TEST_URL, params=params_2)
        data = response.json()

        csrf_token = data['query']['tokens']['csrftoken']

        params_4 = {
            "action": "edit",
            "title": TEST_PAGE,
            "token": csrf_token,
            "format": "json",
            "section": "new",
            "sectiontitle": date,
            "text": holiday_text,
        }

        response = S.post(url=TEST_URL, data=params_4)
        data = response.json()

        if data['edit']['result'] != 'Success':
            flash('Oops! Something went wrong -- ' + data['clientlogin']['messagecode'])
        else:
            flash('New holiday added successfully!')
            return redirect(url_for('list_holidays', holidays_date=date.replace(' ', '_')))

    return render_template("add.html", header="Add holiday")

if __name__ == "__main__":
    APP.run()
$HOME/holidays-viewer/templates/layout.html
<title>Holidays</title>

<link rel="stylesheet" href="//tools-static.wmflabs.org/cdnjs/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css">
<link rel="stylesheet" href="//tools-static.wmflabs.org/fontcdn/css?family=Material+Icons">
<link rel="stylesheet" href="static/style.css">

<script src="//tools-static.wmflabs.org/cdnjs/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="static/update-links.js"></script>

<div class="content bg-secondary rounded m-auto">
  <div class="title-bar bg-primary-dark text-white pl-2">
    <small>Holidays and observances</small>
  </div>
  <div class="header-bar bg-primary text-white shadow p-2">
    {% if request.path != url_for('list_holidays') %}
    <a class=" btn text-white" href="{{ url_for('list_holidays') }}">
      <i class="material-icons">arrow_back</i>
    </a>
    {% endif %}
    <h5>{{header}}</h5>
    <div class="filler"></div>
    <a class="btn text-white" href="{{ url_for('add') }}">
      <i class="material-icons">add</i>
    </a>
    <a class="btn text-white" href="{{ url_for('search') }}">
      <i class="material-icons">search</i>
    </a>
  </div>
  {% with messages = get_flashed_messages() %}
    {% if messages %}
    <div class="alert alert-primary mb-0" role="alert">
      {% for message in messages %}
        {{ message }}
      {% endfor %}
      <button type="button" class="close" data-dismiss="alert" aria-label="Close">
        <span aria-hidden="true">×</span>
      </button>
    </div>
    {% endif %}
  {% endwith %}
  {% block content %}{% endblock %}
</div>
<script src="//tools-static.wmflabs.org/cdnjs/ajax/libs/twitter-bootstrap/4.0.0/js/bootstrap.min.js"></script>
 
Hoton hoto na mahalli mai kallon hutu

Matakai na gaba

Duba nan