My first (real?) program.
The client connects to a Django restframework API by sending user credentials to obtain a token for headers. Then the user can drag and drop an image from a OS folder into the terminal and press enter, then write a title for it to upload.
The image(s) URL is obtained from the server and then turned into markdown that are listed in a bytearray. This byte array gets loaded into a tempfile that can be edited with the system's default editor or Vim. When this is saved and closed, it's converted to html and the article is published.
api_client.py
import requests
import tempfile
import os
import pypandoc
import json
from getpass import getpass
from subprocess import call
EDITOR = os.environ.get('EDITOR', 'vim')
ARTICLE_URL = 'http://127.0.0.1:8000/api/articles/'
IMAGE_URL = 'http://127.0.0.1:8000/api/media/images/'
TOKEN_URL = 'http://127.0.0.1:8000/api-auth-token/'
def obtain_token(username, password):
"""Authenticate and obtain token"""
data = {'username': username, 'password': password}
req = requests.post(TOKEN_URL, data=data)
res = req.json()
token = res['token']
headers = {'Authorization': 'Token {}'.format(token)}
return headers
"""
Ask for user credentials to set header, not sure how to
place this code in a functional way
"""
username = input("Username: ")
password = getpass()
headers = obtain_token(username=username, password=password)
def image_upload(img_file, img_title):
"""Upload image with title"""
files = {'image': img_file}
payload = {'title': img_title}
upload = requests.post(IMAGE_URL, files=files, data=payload,
headers=headers)
return upload
md_urls = bytearray()
def img_docload():
"""
Get the latest uploaded image and convert it
to a html string so that pypandoc again can make
it into markdown, then extend each to the bytearray.
"""
get_url = requests.get(IMAGE_URL)
get_json = json.loads(get_url.content)
clean = get_json[-1]['image']
md_html = "<img src='"+clean+"'>"
md = pypandoc.convert_text(md_html, 'md', format='html')
md_urls.extend(md.encode())
def article(headline, summary):
"""
Make a tempfile and write the list of markdown inserts,
then open it in Vim or any default editor. Save and quit
to convert from markdown to html and upload the article.
"""
with tempfile.NamedTemporaryFile(suffix='.md') as tmp:
tmp.write(md_urls)
tmp.flush()
call([EDITOR, tmp.name])
tmp.seek(0)
edited = tmp.read()
article = edited.decode('utf-8')
content = pypandoc.convert_text(article, 'html', format='md')
payload = {
'headline': headline,
'summary': summary,
'content': content,
}
upload = requests.post(ARTICLE_URL, json=payload, headers=headers)
return upload
def main():
while True:
action = input("Upload image? (k): ")
if action == 'k':
img_file = open(input("Image - Filename: ").strip('\''), 'rb')
img_title = input("Image - Title: ")
image_upload(img_file=img_file, img_title=img_title)
img_docload()
continue
else:
headline = input("Article - Headline: ")
summary = input("Article - Summary: ")
article(headline=headline, summary=summary)
print("Article is published")
break
main()
Questions:
- I wrote the program without a single function to begin with. Then I tried to follow the functional design to learn more about functions and how to structure programs. What could be done better?
- How would you place the
obtain_token
function and its I/O? - My next goal is to learn about classes and OOP; is there a place for classes in this program or is it unnecessary?
- What do you think about the way it first upload an image and then gets the URL, then puts it into a HTML
img
element, and then converts it to md (pypandoc needs it to make the markdown, and I wanted the links to be "dynamic")? This can't be the best approach; would you do it server-side? Or is it best to do as much as possible on the client-side?
In general I would like to know about all the mistakes I have made - what could be done better - especially regarding structure, before I move on to learn more.