API from a remote database
Let's go create a Django REST API from a remote DB with Django 3. In my development folder:
django-admin startproject my_apis
I would do an API targeting a remote emailing tool, I will call here acy_vcs. Let's go create our Django app dedicated in my_apis folder, then migrations and a super-user:
python manage.py startapp acy_vcs
python manage.py migrate
python manage.py createsuperuser
Get URL endpoints from another field than the id
I wanted update data from a tool (tool A), after users updates from another tool (tool B). The perfect field of action for Django REST framework I guess. So I built my own API.
But I faced a problem: the relationship between the data had to be on the email field. And by default Django REST framework uses ids to create URL endpoints of each record. Indeed it seems to be this kind of URLs which allow updates by record (
PUT command with httpie for example).
These are the ones I need to include in the code that will run in the forms of tool B!
Example of httpie command to update fields through a REST API
http -a UserLogin:PassWord PUT http://127.0.0.1:8000/users/4/ firstname="Gretha" lastname="Thunberg"
- The URL contained above is the endpoint of a record, using its id (4) from tool A. But tool B does not know this id, and does not have to know it. He just want to update firstname and lastname according an email relationship. Kwarghhh!
First I tried to generate URL endpoints with emails, hoping something like:
... http://127.0.0.1:firstname.lastname@example.org/ ...
- I know, it's weird. No matter, I never succeeded.
So I had to find a way to get the good URL endpoints without knowing their ids, comparing emails.
Email field and URL endpoint for each record being provided in the json from my API, I use the code below:
- Json authentication, then reading
- Json querying to recover URL endpoint according email value
- Build of the
PUTcommand, then execution
import requests, json, subprocess REQUEST_URL = 'http://127.0.0.1:8000/users/?format=json' login = 'DjangoLogin' password = 'DjangoPassWord' response = requests.get(REQUEST_URL, auth=(login, password)) json_data = response.text.encode('utf-8', 'ignore') readable_json = json.loads(json_data) email_reference = YOUR_EMAIL_FIELD_TOOL_B new_firstname = YOUR_FIRSTNAME_FIELD_TOOL_B new_lastname = YOUR_LASTNAME_FIELD_TOOL_B match_count = 0 for results in readable_json['results']: match_count += 1 if results['email'] == email_reference and results['email'] is not None and match_count != 1: my_url = results['url'] my_cmd = 'http -a ' + login + ':' + password + ' PUT ' + my_url + ' firstname="' + new_firstname + '"' + ' lastname="' + new_lastname + '"' p = subprocess.Popen(my_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p.communicate()
I check that email is not empty (
is not None), and I add an iteration to retrieve only the first result of the data from tool A (
match_count). It will also be better for your tests.