A Django app to manage postcode/home number address forms
Project description
postcodes
A dutch postcode lookup app for Django.
By default we use the free (but rate limited) API from postcode.go-dev.nl.
You must create an account and get an API key to use this package (in the default configuration).
This API key must be set in the settings.
Features
- Lookup addresses by postcode and home number
- Customizable form fields
- Customizable API endpoint
- Autofill form fields with the address data
- Validation of form fields when the address is not found
- Validation of form fields when user input was given (regex, min, max.)
Quick start
-
Install the package via pip:
pip install django-postcodes
-
Add 'postcodes' to your INSTALLED_APPS setting like this:
INSTALLED_APPS = [ ..., 'postcodes', ]
-
Add the postcodes URL to your project's
urls.py
:path('postcodes/', include('postcodes.urls', namespace='postcodes')),
Example usage
First we must define the appropriate form.
This is an example of a form that uses the default API endpoint (custom ones can be defined in the settings):
Every attribute can be customized, except for the postcode and home number fields, which are required for the lookup.
These are hard-coded.
All other elements provided in the bind
object will be filled in with the data from the API.
class AddressForm(forms.Form):
# These are required for the lookup
postcode = forms.CharField(max_length=10, widget=forms.TextInput(attrs={"placeholder": "1234 AB", "class": "postcode", "pattern": "^[0-9]{4}(\s+|)[A-Z]{2}$"}))
home_number = forms.CharField(max_length=10, widget=forms.TextInput(attrs={"placeholder": "123", "class": "home_number"}))
# Custom fields
street = forms.CharField(max_length=255, widget=forms.TextInput(attrs={"placeholder": "Main street", "class": "street"}))
city = forms.CharField(max_length=255, widget=forms.TextInput(attrs={"placeholder": "Amsterdam", "class": "city"}))
municipality = forms.CharField(max_length=255, widget=forms.TextInput(attrs={"placeholder": "Amsterdam", "class": "municipality"}))
province = forms.CharField(max_length=255, widget=forms.TextInput(attrs={"placeholder": "Noord-Holland", "class": "province"}))
build_year = forms.IntegerField(widget=forms.NumberInput(attrs={"placeholder": "1990", "class": "build_year", "pattern": "^[0-9]{4}$", "min": "1900", "max": "2022"}))
floor_area = forms.DecimalField(widget=forms.NumberInput(attrs={"placeholder": "100", "class": "floor_area", "pattern": "^[0-9]{1,3}$"})) # "pattern": "^[0-9]{1,3}$"
geo_x = forms.DecimalField(widget=forms.NumberInput(attrs={"placeholder": "52.123456", "class": "geo_x"}))
geo_y = forms.DecimalField(widget=forms.NumberInput(attrs={"placeholder": "4.123456", "class": "geo_y"}))
rd_x = forms.DecimalField(widget=forms.NumberInput(attrs={"placeholder": "123456", "class": "rd_x"})) # Rijksdriehoek
rd_y = forms.DecimalField(widget=forms.NumberInput(attrs={"placeholder": "123456", "class": "rd_y"})) # Rijksdriehoek
Then we can define our template
{% extends 'base.html' %}
{% block content %}
<link rel="stylesheet" href="{% static 'postcodes/css/postcodes.css' %}">
<script src="{% static 'postcodes/js/postcodes.js' %}" data-api-url="{% url "postcodes:api" %}"></script>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
...
<script>
document.addEventListener('DOMContentLoaded', function() {
lookupPostcode({
bind: {
// These are required for the lookup
postcode: document.querySelector('#id_postcode'),
home_number: document.querySelector('#id_home_number'),
// Custom fields returned by the API
straat: document.querySelector("#id_street"),
woonplaats: document.querySelector("#id_city"),
gemeente: document.querySelector("#id_municipality"),
provincie: document.querySelector("#id_province"),
bouwjaar: document.querySelector("#id_build_year"),
vloeroppervlakte: document.querySelector("#id_floor_area"),
// Or optionally as a queryselector
// If everything is a string - it is safe to omit the DOMContentLoaded eventListener
latitude: "#id_geo_x",
longitude: "#id_geo_y",
rd_x: "#id_rd_x",
rd_y: "#id_rd_y",
},
success: function(addr) {
console.log(addr);
},
error: function(error) {
console.log(error);
}
})
});
</script>
{% endblock %}
The form will now automatically fill in the address fields when a valid postcode and home number is entered.
If it is invalid or not found, the error callback will be called.
Settings
ADDR_VALIDATOR_API_KEY
The API key to use for the postcode lookup.
This will be used by the postcodes.postcode.address_check
function.
ADDR_VALIDATOR_API_URL
The API URL to use for the postcode lookup.
This will be used by the postcodes.postcode.address_check
function.
It should contain the {postcode}
and {home_number}
placeholders.
ADDR_VALIDATOR_PARAMETER_FORMAT
An actual function that formats the parameters for the API URL.
This may not be a path to a function, but the function itself.
Example:
def default_parameter_formatter(**kwargs):
return "&".join([f"{key}={value}" for key, value in kwargs.items()])
ADDR_VALIDATOR_ERROR_ATTRIBUTE
The attribute in the response that contains the error message.
This will be used by the postcodes.postcode.address_check
function.
AddressValidationError exceptions will return the appropriate error message if the attribute is found.
ADDR_VALIDATOR_CACHE_TIMEOUT
The timeout for the cache in seconds.
This will be used by the postcodes.postcode.address_check
function.
It is highly recommended to set this to a high number; by default it caches for a week.
The default endpoint is free to use, but has a rate limit.
ADDR_VALIDATOR_API_KEY_ATTRIBUTE
The attribute in the response that contains the API key.
This will be used by the postcodes.postcode.address_check
function.
It is the header that should be sent with the request.
Defaults to X-API-Token
.
ADDR_VALIDATOR_REQUIRES_AUTH
Whether the API requires authentication.
This will be used by the internal view to check if the user is authenticated.
If the user is authenticated; the view will return the address data.
This does not matter if you use the postcodes.postcode.address_check
function.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file django_postcodes-1.0.5.tar.gz
.
File metadata
- Download URL: django_postcodes-1.0.5.tar.gz
- Upload date:
- Size: 21.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.11.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 35f7d35f427a8510086050590aac6c402b4fb3508e1ab5ae81442c18d3fe6636 |
|
MD5 | 2fe9ea2e42e88243ec04a0e5ade9a42c |
|
BLAKE2b-256 | ced1688a2b3fa6f5ac874dd9c15a1c3fcee35d39970038d1e5caaca48bda86b8 |