Real Python: Python String Formatting Tips & Best Practices

Learn the four main approaches to string formatting in Python, as well as their strengths and weaknesses. You’ll also get a simple rule of thumb for how to pick the best general purpose string formatting approach in your own programs.


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

Planet Python

Techiediaries – Django: Django REST Framework Image File Upload Tutorial & Example [FormData & Angular 7 UI]

Throughout this tutorial, we’ll see how you can implement file upload in Django and Django REST Framework with a step by step example. Our application will expose an /upload endpoint that accepts POST requests that contain the file posted with a multipart/form-data content type using FormData. For the frontend, we’ll be using Angular 7 to create a simple interface that allows the user to select a file and upload it to the server via a POST request and FormData.

These tutorials is divided in two parts: In the first part we’ll create the Django application and make a REST API client to make sure it properly work. In the second part, we’ll proceed to create a frontend with Angular 7.

Let’s get started!

Prerequisites

For this tutorial, you will need to have a few prerequisites such as:

  • Python and pip installed on your system. We’ll be using Python 3.7,
  • Familiarity with Python and Django.
  • Node.js and NPM installed on your system. These are required by Angular CLI.
  • Familiarity with TypeScript.

Creating a Virtual Environment & Installing Django

If you have Python and pip installed on your system, let’s get started by creating a new virtual environment for our project’s dependencies. Open a new terminal, navigate to your working directory and run the following command:

$   cd ~/demos $   python3.7 -m venv .env  

Next, activate your virtual environment using the following command:

$   source .env/bin/activate 

Let’s now install Django using pip. In your terminal run:

$   pip install django 

As of this time, this command will install Django 2.1.7.

Creating a Django Project

Now, let’s proceed to create a django project using the following command:

$   mkdir django-file-upload $   django-admin startproject fileuploadexample . 

Installing Django REST Framework

We’ll be using Django REST framework for creating a REST API endpoint in our application:

$   pip install djangorestframework 

Open the fileuploadexample/settings.py file and add
rest_framework to the INSTALLED_APPS array:

INSTALLED_APPS = [     'django.contrib.admin',     'django.contrib.auth',     'django.contrib.contenttypes',     'django.contrib.sessions',     'django.contrib.messages',     'django.contrib.staticfiles',     'rest_framework' ] 

Creating a Django Application

Next, let’s create a django application using the following commands:

$   cd django-file-upload $   python manage.py startapp uploadapp 

Open the fileuploadexample/settings.py file and add uploadapp to the INSTALLED_APPS array:

INSTALLED_APPS = [     'django.contrib.admin',     'django.contrib.auth',     'django.contrib.contenttypes',     'django.contrib.sessions',     'django.contrib.messages',     'django.contrib.staticfiles',     'rest_framework',     'uploadapp' ] 

You also need to add the following settings to specify where the uploaded files will be saved and from which URL they can be served:

MEDIA_URL =  '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, "media") 

Adding Database Model

Next, open the uploadapp/models.py file and add the following model:

from django.db import models from .models import File  class File(models.Model):     file = models.FileField(blank=False, null=False)     def __str__(self):         return self.file.name 

Our model has only one field name file of type FileField. You can also use ImageField

Note: Please note that the files uploaded to FileField or ImageField are not saved in the database but in the file system of your server. In the database it’s the fields are represented by a VARCHAR containing the reference to the file.

It’s mandatory to MEDIA_URL and MEDIA_ROOT in your settings file.

See How to use Django ImageField, and why use it at all?

Adding the Model Serializer

Create a serializers.py file in uploadapp and add the following code:

from rest_framework importserializers  class FileSerializer(serializers.ModelSerializer):     class Meta:         model = File         fields = "__all__" 

Adding the API View

Next, let’s add the API view that will handle file uploading. Open the uploadapp/views.py file and add the following code:

from rest_framework.parsers import FileUploadParser from rest_framework.response import Response from rest_framework.views import APIView from rest_framework import status  from .serializers import FileSerializer   class FileUploadView(APIView):     parser_class = (FileUploadParser,)      def post(self, request, *args, **kwargs):        file_serializer = FileSerializer(data=request.data)        if file_serializer.is_valid():           file_serializer.save()           return Response(file_serializer.data, status=status.HTTP_201_CREATED)       else:           return Response(file_serializer.errors, status=status.HTTP_400_BAD_REQUEST) 

FileUploadParser parses raw file upload content. The request.data property will be a dictionary with a single key file containing the uploaded file.

Adding the Upload URL

In uploadapp create an urls.py file and add the following code:

from django.urls import path from .views import *  urlpatterns = [     path('', FileUploadView.as_view()) ] 

Next, you need to add the media URL and the uploadapp URLs in the urls.py file of the project:

from django.contrib import admin from django.urls import path, include from django.conf import settings from django.conf.urls.static import static  urlpatterns = [     path('admin/', admin.site.urls),     path('upload/', include('uploadapp.urls')), ]   if settings.DEBUG:   urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 

Using the static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) we can serve media files in development mode.

Next, migrate your database and run the development server using the following commands:

$   python manage.py migrate $   python manage.py runserver 

You django application will be running from the http://127.0.0.1:8000/ address. If you visit the address with your web browser, you should see the following page:

Django File Upload Example

You can now test your file upload endpoint using a REST API client like Postman

Django REST API File Upload

Note: Make sure to name the file field as file, which needs to match the name of the model field name. In our example it’s file.

You can check if the media folder of your project contain the uploaded file and you can access your uploaded file from your browser by using appending the path retruned from in the response to the URL of your server i.e http://127.0.0.1:8000/media/925364568cc67bfb7978b8cc65f40125_OEn02GO in our example.

Enabling CORS

Since we are going to access our django API from the Angular frontend that will be served from the 127.0.0.1:4200 address we need to enable CORS in our django backend. In your terminal run the following command to install django-cors-headers:

$   pip install django-cors-headers 

Next, in your settings file, add corsheaders to the INSTALLED_APPS array:

INSTALLED_APPS = [     # [...]     'corsheaders',     'rest_framework',     'uploadapp' ] 

You also need to add corsheaders.middleware.CorsMiddleware in the MIDDLEWARE array:

MIDDLEWARE = [     'corsheaders.middleware.CorsMiddleware',     # [...] ] 

Next, add the following setting to enable CORS for all domains:

CORS_ORIGIN_ALLOW_ALL =  True 

Check more options from the docs.

Adding the Angular 7 Front-End

Now, let’s create the Angular 7 frontend. Open a new terminal and run the following command to install Angular CLI v7 if it’s not installed on your system:

$   npm install -g @angular/cli 

Next, let’s use the command line interface to generate an Angular 7 project:

$   cd django-file-upload $   ng new frontend 

You will be asked if you would like to add routing. Type y. And also which stylesheets format you would like to use, choose CSS. Next hit Enter and wait for the CLI to generate your project’s files and install the packages from npm.

Next, you can serve your application using the following command:

$   cd frontend $   ng serve 

You can access your application from the http://127.0.0.1:4200 address.

Importing HttpClientModule and ReactiveFormsModule

We’ll be working with HttpClient and reactive forms in our project so we need to import their modules in our application. Open the src/app/app.module.ts file and update it accordingly:

// [...] import { ReactiveFormsModule } from '@angular/forms'; import { HttpClientModule } from '@angular/common/http';   @NgModule({   declarations: [     AppComponent   ],   imports: [     // [...]     ReactiveFormsModule,     HttpClientModule      ],   providers: [],   bootstrap: [AppComponent] }) export class AppModule { } 

Create an Angular Service

Next, let’s create a service that will encapsulate the code for uploading files to the django server. Open a new terminal and run the following command:

$   ng generate service upload 

Open the src/app/upload.service.ts file and add the following code:

import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http';   @Injectable({   providedIn: 'root' }) export class UploadService {    DJANGO_SERVER: string = "http://127.0.0.1:8000";   constructor(private http: HttpClient) { }    public upload(formData) {     return this.http.post<any>(`$  {this.DJANGO_SERVER}/upload/`, formData);   } } 

We first import HttpClient and we inject it via the service constructor.

Next, we define an upload() method that takes an instance of FormData and send it to Django REST API endpoint with a POST request.

Create an Angular Component and Form

Next, let’s create a component that contains the form to use selecting the file and submit it the django upload endpoint.

In your terminal, run the following command:

$   ng generate component profile 

Next, open the src/app/app-routing.module.ts file and add a route for the profile component:

// [...] import { ProfileComponent } from './profile/profile.component';  const routes: Routes = [   {path: 'profile', component: ProfileComponent} ];  // [...] 

Next, open the src/app/profile/profile.component.ts file and update it accordingly:

import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; import { UploadService } from '../upload.service';  @Component({   selector: 'app-profile',   templateUrl: './profile.component.html',   styleUrls: ['./profile.component.css'] }) export class ProfileComponent implements OnInit {    DJANGO_SERVER = 'http://127.0.0.1:8000'   form: FormGroup;   response;   imageURL;    constructor(private formBuilder: FormBuilder, private uploadService: UploadService) { }    ngOnInit() {     this.form = this.formBuilder.group({       profile: ['']     });   }    onChange(event) {     if (event.target.files.length > 0) {       const file = event.target.files[0];       this.form.get('profile').setValue(file);     }   }    onSubmit() {     const formData = new FormData();     formData.append('file', this.form.get('profile').value);      this.uploadService.upload(formData).subscribe(       (res) => {         this.response = res;         this.imageURL = `$  {this.DJANGO_SERVER}$  {res.file}`;         console.log(res);         console.log(this.imageURL);       },       (err) => {           console.log(err);       }     );   } } 

We first create a reactive form with one profile field in the ngOnInit() method of the component. Next, we define the onChange() method which gets called when the user chooses a file in the file input interface. We simply set the selected file as a value of the profile field of the reactive form.

Finally, we define the onSubmit() method that gets called when we click on the submit button of the form. In this method, we create a FormData object, we append the value of the profile field of the form to a file field (this needs to correspond to the name of the field that the django server expects) and we send the FormData object to the API server with a POST request.

Next, open the src/app/profile.component.html file and add the following code:

<h1>Django REST API with Angular 7 File Upload Example</h1> <div>   <div *ngIf="response && imageURL">     <img [src]='imageURL' />   </div>    <form [formGroup]="form" (ngSubmit)="onSubmit()">      <input type="file" name="profile" (change)="onChange($  event)" />     <button type="submit">Upload Image File</button>    </form> </div> 

This is a screenshot of the /profile page after we upload an image to the django server:

Django REST API File Upload with Angular 7

Conclusion

In this tutorial, we’ve seen how to build a full-stack example with Django and Angular 7 for uploading image files. In the backend, we used Django REST Framework, FileUploadParserand FileField and we also enabled CORS using django-cors-headers. In the frontend, we used FormData to create an object to correspond to a form with multipart/form-data type and HttpClient for sending POST requests to the backend.

Planet Python

PyCon: How & why cities and dates are selected for Pycon

Foreword from the Chair:

The PyCon staff, volunteers, tutorial presenters, speakers, poster presenters, and community members have been hard at work preparing for PyCon 2018 in Cleveland, Ohio. Along the way, we’ve gotten a chance to have some solid discussions about what makes PyCon good as well as where it can improve.

In February one of those discussions was around the dates when PyCon 2018 will be occurring, specifically the conflict with Mother’s Day 2018. The outcome of that discussion was a commitment by the PyCon staff to better communicate what decisions and compromises were made along the way and how they were considered.


PyCon is run by the Python Software Foundation, which is a grant giving non-profit. Many misunderstand or are unaware of this relationship, but the Python Software Foundation relies on maintaining a strict budget for the operation of PyCon in order to continue its grants programs and other financial responsibilities.

The PyCon staff and Python Software Foundation Board of Directors strive to improve year over year. After realizing that PyCon 2014 and 2015 conflicted with the observance of Passover, PyCon’s scheduling has explicitly avoided major religious observances and US holidays.

The end result is a schedule which varies year to year and a myriad of compromises small and large that are made along the way. This year one of those compromises was to schedule the conference in conflict with the following holidays and religious observances:

  • May 10 – (Second day of Tutorials) Ascension Day
  • May 13 – (Third day of Talks) Mother’s Day
  • May 16 – (Third day of Sprints) Start of Ramadan

Conflicts were known and understood in advance of booking. For conflicts that staff did not have personal experience with, members of the community were asked to help fill in the blind spots. In spite of this we failed to properly and openly communicate the known conflicts, which allowed for speculation that they simply hadn’t been considered. This is a fair assumption, but it is not the case. In addition, our lack of transparency lead to the conflict being a surprise for many as they registered for PyCon or began booking their travel and accommodations.

With the help of our community, we’ve made adjustments and are planning specific events and spaces to better support mothers at PyCon this year. Moving forward, we will be more transparent about the known conflicts with PyCon’s dates and the ways that we work to accommodate groups which are impacted by those conflicts.

To better fill in the specifics of how it occurs, the team that works year-round to manage the logistics and planning for PyCon worked to develop a summary of that process, and we’d like to share it with you today.


Ernest W. Durbin III
Chair – PyCon US 2018


PyCon: How are the cities and dates selected?

Recently, community members requested a deeper look into the process of selecting a city and dates for PyCon US. Below is an overview of the steps* taken: Selecting a city and dates for PyCon a is process that usually takes about 6 months and involves many layers. First, we start with a list of cities that the Event Coordinators come up with along with any cities suggested by the community. We contact the local convention visitor bureaus and share with them our needs and expectations through a request for proposal (RFP). Our RFP includes the space we need, historical hotel costs, room night pickups, and types of services we need. Additional requirements included in the RFP are:

  • Low-cost to no-cost space rental
  • Avoiding religious holidays
  • Reasonably priced internet and food

The cities that do fulfill our requirements, respond back with a proposal, which usually includes one to three date options depending on their availability. From there we work with all available cities on space — that is usually the most work. Each city sends us the space they think will work. Our Event Coordinators go through every line to make sure it matches our needs. If a city has the space we need, we look at hotels. We consider the distance of the hotels from the convention center and their price. If hotel expectations are met, our Event Coordinators plan site visits to those cities.


* Steps can change from time to time as we constantly try to refine our process.

A Case Study

We’ll run through a sample scenario of how the above mapped out to the selection of 2020 and 2021, which was recently finalized. We started with seventeen cities. We ended up only doing site visits to four cities. The large drop in cities is mainly because several cities turned us down for various reasons such as already being booked or not having enough space. PyCon requires 11 days of meeting space for setup, tutorials, the main conference, and sprints. Because we have such a lengthy span it is not always easy to find locations that can accommodate us. City A was a large city and the dates we were looking at were in February. Since we were looking at February dates, the hotel rates were more in line with our expectations. However, once we saw the space we realized it would not work. City B had great space and good hotel rates so we were hopeful. It also had lots of places to stay near the convention center. City C had good space and hotels, but we did not feel safe walking around in it at night. It was also the second most expensive of the three. City D was having most of the convention center rebuilt but it looked promising and the hotels matched our expectations. One thing we noted is that the area around the convention center lacked places that PyCon attendees would enjoy and would have to take buses to other neighborhoods. The expenses involved with City D were also the highest so we did not select it. In the end, we recommended to the Board of Directors that we move forward with City B for 2020. We plan to announce the city soon – possibly at PyCon 2018.

Known conflicts for PyCon 2019-2021

  • 2019: May 1 to May 9
    • May 1 (First day of Tutorials) – Yom HaShoah
    • May 6 (First day of Sprints) – Start of Ramadan
    • May 9 (Last day of Sprints) – Yom Ha’atzmaut
  • 2020: April 15 to April 23*

    • April 15 (First day of Tutorials) – 7th Day of Passover

    • April 15 (First day of Tutorials) – Tax Day US

    • April 16 (Second day of Tutorials) – Last Day of Passover

    • April 17 (First day of Talks) – Orthodox Good Friday

    • April 18 (Second day of Talks) – Orthodox Holy Saturday

    • April 19 (Third day of Talks) – Orthodox Easter

    • April 21 (Second day of Sprints) – Yom HaShoah

    • April 23 (Last day of Sprints) – Take our Daughters and Sons to Work Day

    • 2021: May 12 to May 20
      • May 13 (Second day of Tutorials) – Ascension Day
      • May 13 (Second day of Tutorials) – Eid al-Fitr (End of Ramadan)
      • May 15 (Second day of Talks) – Armed Forces Day
      • May 17 (First day of Sprints) – Shavuot

    If you are aware of any conflicts we’ve missed, please reach out to pycon-local at python dot org. We will update this list and notify the community.
    If you’d like to recommend a city for us to check out in the future, feel free to email us anytime: pycon-local at python dot org


    * the 2020 holiday/import date list was updated on Feb 18, 2019 thanks to community feedback we received.

    Planet Python

    Tryton News: Tryton Unconference 2019: In Marseille on the 6th & 7th of June

    @nicoe wrote:

    The Tryton Foundation is happy to announce the venue and date of the next Tryton Unconference.

    We will go in the sunny city of Marseille in south of France on the 6th and 7th of June. Contrary to previous editions of the Tryton Unconferences the coding sprint will be organized during the two days preceding the conference.

    Both events will take place at the École de Commerce et de Management. We will publish a website with more detailed informations shortly.

    Many thanks to adiczion which is the organizer of this year event!

    Posts: 1

    Participants: 1

    Read full topic

    Planet Python

    Shannon -jj Behrens: JJ’s Mostly Adequate Summary of the Django Meetup: When *Not* To Use the ORM & Goodbye REST: Building GraphQL APIs with Django

    The Django meetup was at Prezi. They have a great space. They are big Django users.

    Goodbye REST: Building APIs with Django and GraphQL

    Jaden Windle, @jaydenwindle, lead engineer at Jetpack.

    https://github.com/jaydenwindle/goodbye-rest-talk

    They moved from Django REST Framework to GraphQL.

    It sounds like a small app.

    They’re using Django, React, and React Native.

    I think he said they used Reason and moved away from it, but I could be wrong.

    They had to do a rebuild anyway, so they used GraphQL.

    He said not to switch to GraphQL just because it’s cool, and in general, avoid hype-driven development.

    GraphQL is a query language, spec, and collection of tools, designed to operate over a single endpoint via HTTP, optimzing for perf and flexibility.

    Key features:

    • Query for only the data you need.
    • Easily query for multiple resources in a single request.
    • Great front end tooling for handling caching, loading / error states, and updates.

    (I wonder if he’s talking about Apollo, not just GraphQL. I found out later, that they are using Apollo.)

    GraphQL Schema:

    • Types
    • Queries
    • Mutations
    • *Subscriptions

    Graphene is the goto framework for GraphQL in Django.

    He showed an example app.

    You create a type and connect it to a model. It’s like a serializer in DRF.

    (He’s using VS Code.)

    It knows how to understand relationships between types based on the relationships in the models.

    He showed the query syntax.

    He showed how Graphene connects to the Django model. You’re returning raw Django model objects, and it takes care of serialization.

    There’s a really nice UI where you can type in a query, and it queries the server. It has autocomplete. I can’t tell if this is from Apollo, Graphene, or some other GraphQL tool.

    You only pass what you need across the wire.

    When you do a mutation, you can also specify what data it should give back to you.

    There is some Mutation class that you subclass.

    The code looks a lot like DRF.

    Subscriptions aren’t fully implemented in Graphene. His company is working on implementing and open sourcing something. There are a bunch of other possible real-time options–http://graphql-python/graphql-ws is one.

    There’s a way to do file uploads.

    Important: There’s this thing called graphene-django-extras. There’s even something to connect to DRF automatically.

    Pros:

    • Dramatically improves front end DX
    • Flexible types allow for quick iteration
    • Always up-to-date documentation
    • Only send needed data over the wire

    Cons:

    • Graphene isn’t as mature as some other GraphQL implementations (for instance, in JS and Ruby)
    • Logging is different when using a single GraphQL endpoint
    • REST is currently better at server-side caching (E-Tag, etc.)

    Graphene 3 is coming.

    In the Q&A, they said they do use Apollo.

    They’re not yet at a scale where they have to worry about performance.

    He’s not entirely sure whether it’s prone to the N+1 queries problem, but there are GitHub issues related to that.

    You can do raw ORM or SQL queries if you need to. Otherwise, he’s not sure what it’s doing behind the scenes.

    You can add permissions to the models. There’s also a way to tie into Django’s auth model.

    Their API isn’t a public API. It’s only for use by their own client.

    The ORM, and When Not To Use It

    Christophe Pettus from PostgreSQL Experts.

    He thinks the ORM is great.

    The first ORM he wrote was written before a lot of the audience was born.

    Sometimes, writing code for the ORM is hard.

    Database agnosticism isn’t as important as you think it is. For instance, you don’t make the paint on your house color-agnostic.

    Libraries have to be DB agnostic. Your app probably doesn’t need to be.

    Reasons you might want to avoid the query language:

    • Queries that generate sub-optimal SQL
    • Queries more easily expressed in SQL
    • SQL features not available via the ORM

    Django’s ORM’s SQL is much better than it used to be.

    Don’t use __in with very large lists. 100 is about the longest list you should use.

    Avoid very deep joins.

    It’s not hard to chain together a bunch of stuff that ends up generating SQL that’s horrible.

    The query generator doesn’t do a separate optimization pass that makes the query better.

    It’s better to express .filter().exclude().filter() in SQL.

    There are so many powerful functions and operators in PostgreSQL!

    SomeModel.objects.raw() is your friend!

    You can write raw SQL, and yet still have it integrate with Django models.

    You can even get stuff back from the database that isn’t in the model definition.

    There’s some WITH RECURSIVE thing in PostgreSQL that would be prohibitively hard to do with the Django ORM. It’s not really recursive–it’s iterative.

    You can also do queries without using the model framework.

    The model framework is very powerful, but it’s not cheap.

    Interesting: The data has to be converted into Python data and then again into model data. If you’re just going to serialize it into JSON, why create the model objects? You can even create the JSON directly in the database and hand it back directly with PostgreSQL. But make sure the database driver doesn’t convert the JSON back to Python 😉 Return it as raw text.

    There are also tables that Django can’t treat as model tables. For instance, there are logging tables that lack a primary key. Sometimes, you have weird tables with non-Django-able primary keys.

    The ORM is great, though. For instance, it’s great for basic CRUD.

    Interfaces that require building queries in steps are better done with SQL–for instance, an advanced search function.

    Summary:

    • Don’t be afraid to step outside the ORM.
    • SQL isn’t a bug. It’s a feature. It’s code like everything else.
    • Do use the ORM for operations that it makes easier.
    • Don’t hesitate to use the full power of SQL.

    Q&A:

    Whether you put your SQL in model methods or managers is a matter of taste. Having all the code for a particular model in one place (i.e. the model or manager) is useful.

    Write tests. Use CI.

    Use parameter substitution in order to avoid SQL injection attacks. Remember, all external input is hostile. You can’t use parameter substitution if the table name is dynamic–just be careful with what data you allow.

    If you’re using PostGIS, write your own queries for sure. It’s really easy to shoot yourself in the foot with the GIS package.

     

     

    Planet Python