{"id":3340,"date":"2024-08-22T14:17:10","date_gmt":"2024-08-22T14:17:10","guid":{"rendered":"https:\/\/www.infobip.com\/developers\/?p=3340"},"modified":"2024-10-02T10:35:15","modified_gmt":"2024-10-02T10:35:15","slug":"co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2","status":"publish","type":"post","link":"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2","title":{"rendered":"Co-ordinating a gift exchange with Flask and Infobip (Part 2)"},"content":{"rendered":"\n<p>This is the second part of a five-part guide that shows you how to build a web app to co-ordinate a gift exchange. We&#8217;ll use Flask, a Python web framework, and Infobip&#8217;s Python SDK.<\/p>\n\n\n\n<p>In this part of the guide, we add a database to our app to store names and phone numbers.<\/p>\n\n\n\n<p>You can follow along with the code at the <a href=\"https:\/\/github.com\/infobip-community\/gift-exchange-with-flask\">project repository on GitHub<\/a>, where each step of this guide corresponds to <a href=\"https:\/\/github.com\/infobip-community\/gift-exchange-with-flask\/branches\">a branch in the repo<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Defining our database schema<\/h2>\n\n\n\n<p>A relational database needs a schema, which defines what tables exist in the database and how they relate to each other. Our database is going be very simple: a single table which stores a phone number, a name, whether or not that person has bought a gift for their giftee, and whether or not that phone number has been verified (along with a code later used in the verification process). Each row also contains a link to another row in the same table, which tells us who each person has to buy a gift for.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Primary key<\/td><td>Phone number<\/td><td>Name<\/td><td>Gift bought?<\/td><td>Verified?<\/td><td>Verification code<\/td><td>Giftee<\/td><\/tr><tr><td>001<\/td><td>44 1234 567 890<\/td><td>Alice<\/td><td>0<\/td><td>0<\/td><td>065AC81..<\/td><td>002<\/td><\/tr><tr><td>002<\/td><td>44 0987 654 321<\/td><td>Bob<\/td><td>0<\/td><td>1<\/td><td>A63E80D&#8230;<\/td><td>001<\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\">In this example table, we have two participants, Alice and Bob. The last column of the table &#8216;Giftee&#8217;, shows that Alice needs to buy a gift for person 002 &#8211; that&#8217;s Bob&#8217;s primary key &#8211; and vice versa.<br><br>SQLite doesn&#8217;t have booleans as a first-class type, so we store the answers to the yes\/no questions (&#8216;Gift bought?&#8217; and &#8216;Verified?&#8217;) as 0 or 1.<\/figcaption><\/figure>\n\n\n\n<p>To create a database with this structure, we&#8217;re going to write a SQL file that lives within our Flask application. Create a file called <code>schema.sql<\/code> in the top level of your directory, so that your directory structure looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gift-exchange-app\/\n    app.py\n    requirements.txt\n    schema.sql\n    templates\/\n        app.html<\/code><\/pre>\n\n\n\n<p>Now add the following code to that file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE people (\n    id INTEGER PRIMARY KEY AUTOINCREMENT,\n    phone_number TEXT NOT NULL,\n    name TEXT NOT NULL,\n    gift_bought INTEGER,    \n    verified INTEGER,\n    verification_code TEXT,\n    giftee INTEGER REFERENCES people(id)\n);<\/code><\/pre>\n\n\n\n<p>This SQL statement, when applied to a database, will create a new table called people with the structure that we described above. Currently, we don&#8217;t have a database to execute this command against, so that&#8217;s our next task.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating our database<\/h2>\n\n\n\n<p>Create a Python file in your app&#8217;s directory called <code>create_db.py<\/code>, and add the following code into it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import sqlite3\nconn = sqlite3.connect('database.db')\n\nwith open('schema.sql') as f:\n    conn.executescript(f.read())\n\nconn.commit()\nconn.close()<\/code><\/pre>\n\n\n\n<p>This code creates a new database with the line <code>sqlite3.connect('database.db')<\/code>, and executes the SQL code we just wrote in that database, creating our new table.<\/p>\n\n\n\n<p>Now, in your terminal, run the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>python create_db.py<\/code><\/pre>\n\n\n\n<p>You&#8217;ll see that a new file has been created in the same directory called <code>database.db<\/code>, and your directory structure now looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gift-exchange-app\/\n    app.py\n    create_db.py\n    requirements.txt\n    schema.sql\n    database.db\n    templates\/\n        app.html<\/code><\/pre>\n\n\n\n<p>The <code>create_db.py<\/code> file isn&#8217;t needed any more; you can delete it if you like.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Storing data from our app<\/h2>\n\n\n\n<p>Now that we have a database, we need to connect to it from within our app&#8217;s code. Open up your app.py file, and look at the <code>index<\/code> method, which looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@app.route('\/', methods=&#91;'GET', 'POST'])\ndef index():\n   if request.method == 'GET':\n       pass\n   else:\n       name = request.form.get(\"name\")\n       number = request.form.get(\"number\")\n       print(f\u2018You clicked the button with name {name} and number {phone}!\u2019)\n   return render_template('app.html')<\/code><\/pre>\n\n\n\n<p>We&#8217;re going to add code into this so that it handles the user input correctly, and inserts suitable data into our database.<\/p>\n\n\n\n<p>First, add the following imports to the top of the file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import sqlite3\nfrom flask import flash<\/code><\/pre>\n\n\n\n<p>We use <code>sqlite3<\/code> to access our database, and the <code>flash<\/code> method lets us display messages to the user.<\/p>\n\n\n\n<p>In order to make this work ,our app needs a &#8216;secret key&#8217; which Flask uses to manage sessions. For our purposes, what this means is that, just above your <code>index<\/code> method, you&#8217;ll need to add the following line:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>app.secret_key = \"secret key\"<\/code><\/pre>\n\n\n\n<p>Next, change your <code>index<\/code> method to include the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@app.route('\/', methods=&#91;'GET', 'POST'])\ndef index():\n   if request.method == 'GET':\n       pass\n   else:\n       name = request.form.get(\"name\")\n       number = request.form.get(\"number\")\n       if not all((name, number)):\n           flash(\"Please enter both a name and a phone number.\")\n       else:\n           print(f\"You clicked the button with name {name} and number {number}!\")\n           add_new_person_to_db(name, number)\n           flash(f\"You added {name} with number {phone}!\")\n   return render_template('app.html')<\/code><\/pre>\n\n\n\n<p>With this code, we check that both pieces of data are present, then add them into the database. The <code>flash<\/code> method tells Flask that a message needs to be displayed to the user; in order for it to actually happen, we need to edit our HTML.<\/p>\n\n\n\n<p>In your <code>app.html<\/code> file, add the following code to the beginning of the <code>&lt;body><\/code> section:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>        {% with msg = get_flashed_messages() %}\n            {% if msg %}\n                {% for message in msg %}\n                    &lt;strong>{{ message }}&lt;\/strong>\n                {% endfor %}\n            {% endif %}\n        {% endwith %}<\/code><\/pre>\n\n\n\n<p>Now, when the flash method is called in your Python code with a message, that message will be displayed at the top of the page.<\/p>\n\n\n\n<p>Next, we need to actually write the <code>add_new_person_to_db<\/code> method that we call in the success scenario. Add this code into your <code>app.py<\/code> file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def add_new_person_to_db(name, number):\n   conn = sqlite3.connect('database.db')\n   cur = conn.cursor\n   cur.execute(f\"\"\"\n      INSERT INTO people (name, phone_number) VALUES\n         ({name}, {number})\"\"\")\n   conn.commit()\n   conn.close()<\/code><\/pre>\n\n\n\n<p>This code opens a connection to our database, and adds the data from the user into it.<\/p>\n\n\n\n<p>NOTE: This is wildly insecure, and in a real-life scenario you would need to do extra input sanitisation to protect against SQL injection attacks. For the purposes of this tutorial, we&#8217;re not going to worry about that. If you&#8217;d like to learn more about SQL injection and how to protect against it, RealPython has <a href=\"https:\/\/realpython.com\/prevent-python-sql-injection\/\">an excellent guide<\/a> to get you started.<\/p>\n\n\n\n<p>We&#8217;ve now created a database and extended our app to allow it to store data from users within that database!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Next time<\/h2>\n\n\n\n<p>In the next part, we&#8217;ll add functionality to our app so that each participant is required to opt-in and verify their phone number so that the gift exhange can be arranged.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is the second part of a five-part guide [&hellip;]<\/p>\n","protected":false},"author":53,"featured_media":3111,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","footnotes":""},"categories":[28,12,255,13],"tags":[43,76],"coauthors":[285],"class_list":["post-3340","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","category-guide","category-infobip-products","category-python","tag-api","tag-sdk"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v25.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Co-ordinating a gift exchange with Flask and Infobip (Part 2) - Infobip Developers Hub<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Co-ordinating a gift exchange with Flask and Infobip (Part 2) - Infobip Developers Hub\" \/>\n<meta property=\"og:description\" content=\"This is the second part of a five-part guide [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2\" \/>\n<meta property=\"og:site_name\" content=\"Infobip Developers Hub\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/infobip\/\" \/>\n<meta property=\"article:published_time\" content=\"2024-08-22T14:17:10+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-10-02T10:35:15+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.infobip.com\/developers\/wp-content\/uploads\/2024\/02\/flask2.png\" \/>\n\t<meta property=\"og:image:width\" content=\"694\" \/>\n\t<meta property=\"og:image:height\" content=\"451\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Eli Holderness\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@InfobipDev\" \/>\n<meta name=\"twitter:site\" content=\"@InfobipDev\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Eli Holderness\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2\"},\"author\":{\"name\":\"Eli Holderness\",\"@id\":\"https:\/\/www.infobip.com\/developers\/#\/schema\/person\/2d3f818bd258646bc997a3ec04146bbd\"},\"headline\":\"Co-ordinating a gift exchange with Flask and Infobip (Part 2)\",\"datePublished\":\"2024-08-22T14:17:10+00:00\",\"dateModified\":\"2024-10-02T10:35:15+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2\"},\"wordCount\":804,\"publisher\":{\"@id\":\"https:\/\/www.infobip.com\/developers\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.infobip.com\/developers\/wp-content\/uploads\/2024\/02\/flask2.png\",\"keywords\":[\"API\",\"SDK\"],\"articleSection\":[\"Blog Post\",\"Guide\",\"Infobip Products\",\"Python\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2\",\"url\":\"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2\",\"name\":\"Co-ordinating a gift exchange with Flask and Infobip (Part 2) - Infobip Developers Hub\",\"isPartOf\":{\"@id\":\"https:\/\/www.infobip.com\/developers\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.infobip.com\/developers\/wp-content\/uploads\/2024\/02\/flask2.png\",\"datePublished\":\"2024-08-22T14:17:10+00:00\",\"dateModified\":\"2024-10-02T10:35:15+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2#primaryimage\",\"url\":\"https:\/\/www.infobip.com\/developers\/wp-content\/uploads\/2024\/02\/flask2.png\",\"contentUrl\":\"https:\/\/www.infobip.com\/developers\/wp-content\/uploads\/2024\/02\/flask2.png\",\"width\":694,\"height\":451,\"caption\":\"A blog cover image showing the Python logo on the left and the Infobip logo on the right.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.infobip.com\/developers\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Co-ordinating a gift exchange with Flask and Infobip (Part 2)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.infobip.com\/developers\/#website\",\"url\":\"https:\/\/www.infobip.com\/developers\/\",\"name\":\"Infobip Developers Hub\",\"description\":\"Build meaningful customer relationships across any channel\",\"publisher\":{\"@id\":\"https:\/\/www.infobip.com\/developers\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.infobip.com\/developers\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.infobip.com\/developers\/#organization\",\"name\":\"Infobip Developers Hub\",\"url\":\"https:\/\/www.infobip.com\/developers\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.infobip.com\/developers\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.infobip.com\/developers\/wp-content\/uploads\/2023\/03\/Infobip_logo_favicon.png\",\"contentUrl\":\"https:\/\/www.infobip.com\/developers\/wp-content\/uploads\/2023\/03\/Infobip_logo_favicon.png\",\"width\":696,\"height\":696,\"caption\":\"Infobip Developers Hub\"},\"image\":{\"@id\":\"https:\/\/www.infobip.com\/developers\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/infobip\/\",\"https:\/\/x.com\/InfobipDev\",\"https:\/\/www.youtube.com\/channel\/UCUPSTy53VecI5GIir3J3ZbQ\",\"https:\/\/github.com\/infobip-community\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.infobip.com\/developers\/#\/schema\/person\/2d3f818bd258646bc997a3ec04146bbd\",\"name\":\"Eli Holderness\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.infobip.com\/developers\/#\/schema\/person\/image\/e3fd4a8aa6b78952d057f724bcf1dff0\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/2261319993db9030e1328c712ee20e4aaedf2c9cb8e4379ae8af57f2c877d5f4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/2261319993db9030e1328c712ee20e4aaedf2c9cb8e4379ae8af57f2c877d5f4?s=96&d=mm&r=g\",\"caption\":\"Eli Holderness\"},\"description\":\"Developer advocate, conference speaker &amp; professional nerd. Likes maths, knitting, and cats.\",\"url\":\"https:\/\/www.infobip.com\/developers\/blog\/author\/eli\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Co-ordinating a gift exchange with Flask and Infobip (Part 2) - Infobip Developers Hub","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2","og_locale":"en_US","og_type":"article","og_title":"Co-ordinating a gift exchange with Flask and Infobip (Part 2) - Infobip Developers Hub","og_description":"This is the second part of a five-part guide [&hellip;]","og_url":"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2","og_site_name":"Infobip Developers Hub","article_publisher":"https:\/\/www.facebook.com\/infobip\/","article_published_time":"2024-08-22T14:17:10+00:00","article_modified_time":"2024-10-02T10:35:15+00:00","og_image":[{"width":694,"height":451,"url":"https:\/\/www.infobip.com\/developers\/wp-content\/uploads\/2024\/02\/flask2.png","type":"image\/png"}],"author":"Eli Holderness","twitter_card":"summary_large_image","twitter_creator":"@InfobipDev","twitter_site":"@InfobipDev","twitter_misc":{"Written by":"Eli Holderness","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2#article","isPartOf":{"@id":"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2"},"author":{"name":"Eli Holderness","@id":"https:\/\/www.infobip.com\/developers\/#\/schema\/person\/2d3f818bd258646bc997a3ec04146bbd"},"headline":"Co-ordinating a gift exchange with Flask and Infobip (Part 2)","datePublished":"2024-08-22T14:17:10+00:00","dateModified":"2024-10-02T10:35:15+00:00","mainEntityOfPage":{"@id":"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2"},"wordCount":804,"publisher":{"@id":"https:\/\/www.infobip.com\/developers\/#organization"},"image":{"@id":"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2#primaryimage"},"thumbnailUrl":"https:\/\/www.infobip.com\/developers\/wp-content\/uploads\/2024\/02\/flask2.png","keywords":["API","SDK"],"articleSection":["Blog Post","Guide","Infobip Products","Python"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2","url":"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2","name":"Co-ordinating a gift exchange with Flask and Infobip (Part 2) - Infobip Developers Hub","isPartOf":{"@id":"https:\/\/www.infobip.com\/developers\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2#primaryimage"},"image":{"@id":"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2#primaryimage"},"thumbnailUrl":"https:\/\/www.infobip.com\/developers\/wp-content\/uploads\/2024\/02\/flask2.png","datePublished":"2024-08-22T14:17:10+00:00","dateModified":"2024-10-02T10:35:15+00:00","breadcrumb":{"@id":"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2#primaryimage","url":"https:\/\/www.infobip.com\/developers\/wp-content\/uploads\/2024\/02\/flask2.png","contentUrl":"https:\/\/www.infobip.com\/developers\/wp-content\/uploads\/2024\/02\/flask2.png","width":694,"height":451,"caption":"A blog cover image showing the Python logo on the left and the Infobip logo on the right."},{"@type":"BreadcrumbList","@id":"https:\/\/www.infobip.com\/developers\/blog\/co-ordinating-a-gift-exchange-with-flask-and-infobip-part-2#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.infobip.com\/developers\/"},{"@type":"ListItem","position":2,"name":"Co-ordinating a gift exchange with Flask and Infobip (Part 2)"}]},{"@type":"WebSite","@id":"https:\/\/www.infobip.com\/developers\/#website","url":"https:\/\/www.infobip.com\/developers\/","name":"Infobip Developers Hub","description":"Build meaningful customer relationships across any channel","publisher":{"@id":"https:\/\/www.infobip.com\/developers\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.infobip.com\/developers\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.infobip.com\/developers\/#organization","name":"Infobip Developers Hub","url":"https:\/\/www.infobip.com\/developers\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.infobip.com\/developers\/#\/schema\/logo\/image\/","url":"https:\/\/www.infobip.com\/developers\/wp-content\/uploads\/2023\/03\/Infobip_logo_favicon.png","contentUrl":"https:\/\/www.infobip.com\/developers\/wp-content\/uploads\/2023\/03\/Infobip_logo_favicon.png","width":696,"height":696,"caption":"Infobip Developers Hub"},"image":{"@id":"https:\/\/www.infobip.com\/developers\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/infobip\/","https:\/\/x.com\/InfobipDev","https:\/\/www.youtube.com\/channel\/UCUPSTy53VecI5GIir3J3ZbQ","https:\/\/github.com\/infobip-community"]},{"@type":"Person","@id":"https:\/\/www.infobip.com\/developers\/#\/schema\/person\/2d3f818bd258646bc997a3ec04146bbd","name":"Eli Holderness","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.infobip.com\/developers\/#\/schema\/person\/image\/e3fd4a8aa6b78952d057f724bcf1dff0","url":"https:\/\/secure.gravatar.com\/avatar\/2261319993db9030e1328c712ee20e4aaedf2c9cb8e4379ae8af57f2c877d5f4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/2261319993db9030e1328c712ee20e4aaedf2c9cb8e4379ae8af57f2c877d5f4?s=96&d=mm&r=g","caption":"Eli Holderness"},"description":"Developer advocate, conference speaker &amp; professional nerd. Likes maths, knitting, and cats.","url":"https:\/\/www.infobip.com\/developers\/blog\/author\/eli"}]}},"_links":{"self":[{"href":"https:\/\/www.infobip.com\/developers\/wp-json\/wp\/v2\/posts\/3340","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.infobip.com\/developers\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.infobip.com\/developers\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.infobip.com\/developers\/wp-json\/wp\/v2\/users\/53"}],"replies":[{"embeddable":true,"href":"https:\/\/www.infobip.com\/developers\/wp-json\/wp\/v2\/comments?post=3340"}],"version-history":[{"count":10,"href":"https:\/\/www.infobip.com\/developers\/wp-json\/wp\/v2\/posts\/3340\/revisions"}],"predecessor-version":[{"id":3393,"href":"https:\/\/www.infobip.com\/developers\/wp-json\/wp\/v2\/posts\/3340\/revisions\/3393"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.infobip.com\/developers\/wp-json\/wp\/v2\/media\/3111"}],"wp:attachment":[{"href":"https:\/\/www.infobip.com\/developers\/wp-json\/wp\/v2\/media?parent=3340"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.infobip.com\/developers\/wp-json\/wp\/v2\/categories?post=3340"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.infobip.com\/developers\/wp-json\/wp\/v2\/tags?post=3340"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.infobip.com\/developers\/wp-json\/wp\/v2\/coauthors?post=3340"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}