Handling File Uploads in Different Python Frameworks

Learn how to handle file uploads in popular Python frameworks like Flask, Django, FastAPI, and Frappe. Step-by-step guide with examples. Perfect for developers!

To handle file uploads from an HTML form in your Python Frameworks, you typically handle them differently depending on the web framework you’re using (e.g., Flask, Django, FastAPI, Frappe, etc.).

Note: HTML form must include enctype="multipart/form-data".

In this article, we learn how to handle file uploads in some common Python web frameworks:

Using Flask

Design an HTML form with file field as follows,

<form action="/upload" method="post" enctype="multipart/form-data">
  <input type="file" name="myfile">
  <input type="submit">
</form>

You can get the uploaded file from the myfile field as follows,

from flask import Flask, request

app = Flask(__name__)

@app.route('/upload', methods=['POST'])
def upload_file():
    uploaded_file = request.files['myfile']
    if uploaded_file.filename != '':
        uploaded_file.save(f"./uploads/{uploaded_file.filename}")
    return "File uploaded successfully!"

Using Django

In Django, HTML form is exactly same. But, you have to add csrf_token to each form.

<form method="post" enctype="multipart/form-data">
  {% csrf_token %}
  <input type="file" name="myfile">
  <input type="submit">
</form>

You can get the file from the myfile field as follows,

from django.core.files.storage import FileSystemStorage
from django.http import HttpResponse

def upload_file(request):
    if request.method == 'POST' and request.FILES['myfile']:
        uploaded_file = request.FILES['myfile']
        fs = FileSystemStorage()
        fs.save(uploaded_file.name, uploaded_file)
        return HttpResponse('File uploaded!')
    return HttpResponse('Upload form')

Get book to learn basics of python from https://amzn.to/3FIs9cW

Using FastAPI

The HTML design file is same as the Django HTML file with csrf_token.

Backend code to get the uploaded file is as follows,

from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse

app = FastAPI()

@app.post("/upload/")
async def upload_file(file: UploadFile = File(...)):
    contents = await file.read()
    with open(f"./uploads/{file.filename}", "wb") as f:
        f.write(contents)
    return {"filename": file.filename}

Using Frappe

In Frappe, when you submit a file from an HTML form, you can handle file uploads using its built-in frappe.utils.file_manager.save_file() method. The HTML design file for Frappe is as follows,

<form method="POST" enctype="multipart/form-data" action="/api/method/my_app.api.upload_file">
  <input type="file" name="file">
  <input type="submit" value="Upload">
</form>

In Frappe backend, you have to create whitelisted method for handling file upload as follows,

import frappe
from frappe.utils.file_manager import save_file
from frappe import _

@frappe.whitelist(allow_guest=True)  # or remove `allow_guest=True` if auth is needed
def upload_file():
    # Access the uploaded file from the request
    uploaded_file = frappe.request.files.get('file')
    
    if not uploaded_file:
        frappe.throw(_("No file uploaded"))

    # Save the file using Frappe's file manager
    saved_file = save_file(
        filename=uploaded_file.filename,
        content=uploaded_file.stream.read(),
        dt=None,  # You can pass doctype here if you want to attach it
        dn=None   # and document name
    )

    return {
        "message": "File uploaded successfully",
        "file_url": saved_file.file_url,
        "file_name": saved_file.file_name
    }

Conclusion

In above post, we learned file uploads using four different Python backed frameworks. We learned that different framework have different ways to handle file uploads.

Disclaimer: This post contains affiliate links. If you use these links to buy something, I may earn a commission at no extra cost to you.

Python Geocoding: Convert Addresses to Coordinates Easily

Learn how to convert physical addresses into geographic coordinates using Python libraries like Geopy. Step-by-step geocoding tutorial for beginners.

Most of the time, datasets are incomplete and often require pre-processing to make them usable. Imagine, We have some datasets with only an address column without latitude and longitude columns, and we want to represent this data geographically. To do that, we need to add geographic information to these data. These cannot be possible manually. We have to create a script to convert all those addresses to geographic information – Latitude and Longitude – to map their locations, which is known as Geocoding. We can do this geocoding using python geopy library.

Geocoding is the computational process of transforming a physical address description to a location on the Earth’s surface (spatial representation in numerical coordinates)

Wikipedia

In this article, I will show you how to perform geocoding in Python with the help of Geopy library. Geopy has different Geocoding services that you can choose from, including Google Maps, ArcGIS, AzureMaps, Bing, etc. Some of them require API keys, while others can be accessible freely.

Install Geopy

To perform geocoding, we need to install the following Geopy library using pip,

pip install geopy

Geocoding Single Address

In this example, we use Nominatim Geocoding service, which is built on top of OpenStreetMap data.

Let us Geocode a single address, the Taj Mahal in Agra, India.

locator = Nominatim(user_agent="myGeocoder")
location = locator.geocode("Taj Mahal, Agra, India")

First line of the above code will create locator that holds the Geocoding service, Nominatim. In second line, we call geocode method of the locator service and pass any address to it, in this example, the Taj Mahal address.

print("Latitude = {}, Longitude = {}".format(location.latitude, location.longitude))

Above line will print out the coordinates of the location we have created.

Latitude = 48.85614465, Longitude = 2.29782039332223

That’s it.

So, the complete code will look like this,

import geopy
from geopy.geocoders import Nominatim
from geopy.extra.rate_limiter import RateLimiter

locator = Nominatim(user_agent="myGeocoder")
geocode = RateLimiter(locator.geocode, min_delay_seconds=1)

address = "Taj Mahal, Agra, India"
location = locator.geocode(address)

print("Latitude = {}, Longitude = {}".format(location.latitude, location.longitude))

Now, try some different addresses of your own.