A tiny flexible DRF toolkit for user registration from views.py in a few lines.
Project description
Humanoid User Registration
Humanoid User Registration is a tiny toolkit on top of Django REST Framework that helps you create a flexible user registration API from views.py in only a few lines.
It is designed for developers who do not want to write a new serializer every time they need user registration.
from humanoid_user_registration import registration_view, field, types
register = registration_view(
fields=[
field.username,
field.email(types.email, required=True),
field.given_name(types.string, source="first_name"),
field.family_name(types.string, source="last_name"),
field.phone_number(types.string, required=True),
],
allow_non_model_fields=True,
)
Main idea
You configure registration directly inside your Django views.py.
You do not need to add package settings like this:
HUMANOID_USER_REGISTRATION = {...}
You do not need to create a custom registration serializer manually.
You do not need to add this package to INSTALLED_APPS unless you want to use optional features from your own project.
You only import the toolkit and create a DRF view.
Installation
pip install humanoid-user-registration
Development install from local source:
pip install -e .
Requirements
- Python 3.9+
- Django 4.2+
- Django REST Framework 3.14+
Quick start
1. Create your registration view in views.py
from humanoid_user_registration import registration_view, field, types
register = registration_view(
fields=[
field.username,
field.email(types.email, required=True),
field.first_name(required=False),
field.last_name(required=False),
]
)
2. Connect your URL
Your Django project still needs a URL route. This is a Django rule: a request cannot reach a view unless some URL points to it.
Example in urls.py:
from django.urls import path
from .views import register
urlpatterns = [
path("api/auth/register/", register, name="register"),
]
If your project already routes to this views.py, then you only work in views.py.
3. Send a POST request
{
"username": "hekmat",
"email": "hekmat@example.com",
"first_name": "Hekmat",
"last_name": "Rahimi",
"password": "StrongPass123!",
"password_confirm": "StrongPass123!"
}
Example success response:
{
"message": "Registration successful.",
"user": {
"id": 1,
"username": "hekmat",
"email": "hekmat@example.com",
"first_name": "Hekmat",
"last_name": "Rahimi"
}
}
Important: JSON keys need quotation marks
In JSON, keys must use quotation marks:
{
"username": "hekmat"
}
This is invalid JSON:
{
username: "hekmat"
}
But inside Python views.py, the toolkit lets you avoid raw string dictionaries by using this clean style:
field.age(types.integer)
field.phone_number(types.string)
field.given_name(types.string, source="first_name")
Field syntax
Simple model fields
from humanoid_user_registration import registration_view, field, types
register = registration_view(
fields=[
field.username,
field.email(types.email),
field.first_name,
field.last_name,
]
)
Required and optional fields
register = registration_view(
fields=[
field.username,
field.email(types.email, required=True),
field.first_name(required=False),
field.last_name(required=False),
]
)
More field types
register = registration_view(
fields=[
field.username,
field.email(types.email),
field.age(types.integer, required=False),
field.is_student(types.boolean, required=False),
field.date_of_birth(types.date, required=False),
field.website(types.url, required=False),
],
allow_non_model_fields=True,
)
Supported field types
Use these inside views.py:
types.string
types.email
types.integer
types.boolean
types.date
types.datetime
types.float
types.decimal
types.url
types.uuid
types.text
There is also a type alias:
from humanoid_user_registration import registration_view, field, type
register = registration_view(
fields=[
field.username,
field.age(type.integer),
]
)
But types.integer is recommended because type is already a Python built-in name.
Rename API fields with source
Sometimes your frontend field name is different from your Django User model field name.
Example: frontend sends given_name, but Django User model has first_name.
register = registration_view(
fields=[
field.username,
field.email(types.email),
field.given_name(types.string, source="first_name"),
field.family_name(types.string, source="last_name"),
]
)
Frontend request:
{
"username": "hekmat",
"email": "hekmat@example.com",
"given_name": "Hekmat",
"family_name": "Rahimi",
"password": "StrongPass123!",
"password_confirm": "StrongPass123!"
}
Saved in Django:
given_name -> User.first_name
family_name -> User.last_name
Add non-model fields
A model field is a real database/User model field. For Django's default User model, common fields are:
username
email
first_name
last_name
password
A non-model field is a field that does not exist in your User model, for example:
phone_number
address
nid_number
age
To accept non-model fields:
register = registration_view(
fields=[
field.username,
field.email(types.email),
field.phone_number(types.string, required=True),
field.address(types.string, required=False),
field.age(types.integer, required=False),
],
allow_non_model_fields=True,
)
Request:
{
"username": "hekmat",
"email": "hekmat@example.com",
"phone_number": "0700000000",
"address": "Kabul",
"age": 22,
"password": "StrongPass123!",
"password_confirm": "StrongPass123!"
}
What happens:
username saved if User.username exists
email saved if User.email exists
phone_number accepted and returned, but not permanently saved unless User.phone_number exists
address accepted and returned, but not permanently saved unless User.address exists
age accepted and returned, but not permanently saved unless User.age exists
Important: allow_non_model_fields=True does not create database columns. It only allows the API to accept extra fields without crashing.
If you want non-model fields to be saved permanently, use one of these professional options:
- Add the fields to your custom User model.
- Create a separate Profile model.
- Save the extra values in a
post_register_hook.
Use post_register_hook
You can run custom logic after the user is created.
from humanoid_user_registration import registration_view, field, types
def after_register(user, request):
phone_number = request.data.get("phone_number")
print("New user:", user.username)
print("Phone:", phone_number)
register = registration_view(
fields=[
field.username,
field.email(types.email),
field.phone_number(types.string, required=True),
],
allow_non_model_fields=True,
post_register_hook=after_register,
)
You can also define a hook with three parameters:
def after_register(user, request, extra_fields):
print(extra_fields)
The toolkit will pass non-model fields to extra_fields.
Custom response fields
By default, the response includes id and the configured fields.
You can control the response:
register = registration_view(
fields=[
field.username,
field.email(types.email),
field.given_name(types.string, source="first_name"),
],
response_fields=["id", "username", "email", "given_name"],
)
Disable password confirmation
Default request requires both:
{
"password": "StrongPass123!",
"password_confirm": "StrongPass123!"
}
To use only password:
register = registration_view(
fields=[field.username, field.email(types.email)],
require_password_confirmation=False,
)
Password validation
By default, the toolkit calls Django's password validators.
To disable password strength validation:
register = registration_view(
fields=[field.username, field.email(types.email)],
validate_password_strength=False,
)
To add a minimum length at serializer level:
register = registration_view(
fields=[field.username, field.email(types.email)],
password_min_length=8,
)
Include DRF token in response
If your project uses DRF TokenAuthentication and has rest_framework.authtoken installed, you can return a token after registration.
register = registration_view(
fields=[field.username, field.email(types.email)],
include_token=True,
)
Response:
{
"message": "Registration successful.",
"user": {
"id": 1,
"username": "hekmat",
"email": "hekmat@example.com"
},
"token": "abc123..."
}
If rest_framework.authtoken is not installed, the user is still created, but no token is returned.
Custom permissions, authentication, and throttling
from rest_framework.throttling import AnonRateThrottle
register = registration_view(
fields=[field.username, field.email(types.email)],
throttle_classes=[AnonRateThrottle],
)
By default, registration uses AllowAny permission.
Full realistic example
# views.py
from humanoid_user_registration import registration_view, field, types
def after_register(user, request, extra_fields):
# Example: save phone_number to a Profile table in your own project.
# Profile.objects.create(user=user, phone_number=extra_fields.get("phone_number"))
pass
register = registration_view(
fields=[
field.username,
field.email(types.email, required=True),
field.given_name(types.string, source="first_name", required=True),
field.family_name(types.string, source="last_name", required=False),
field.phone_number(types.string, required=True),
field.age(types.integer, required=False),
field.date_of_birth(types.date, required=False),
],
allow_non_model_fields=True,
response_fields=[
"id",
"username",
"email",
"given_name",
"family_name",
"phone_number",
"age",
"date_of_birth",
],
post_register_hook=after_register,
)
Request:
{
"username": "hekmat",
"email": "hekmat@example.com",
"given_name": "Hekmat",
"family_name": "Rahimi",
"phone_number": "0700000000",
"age": 22,
"date_of_birth": "2004-01-01",
"password": "StrongPass123!",
"password_confirm": "StrongPass123!"
}
Older supported styles
The recommended style is:
field.age(types.integer, required=False)
But these also work:
"username"
{"name": "age", "type": "integer", "required": False}
This keeps the toolkit flexible.
Optional built-in URL
The package includes an optional default URL:
from django.urls import include, path
urlpatterns = [
path("api/auth/", include("humanoid_user_registration.urls")),
]
This creates:
POST /api/auth/register/
But the main goal of this package is still the views.py style.
Development
Clone the project:
git clone https://github.com/your-username/humanoid-user-registration.git
cd humanoid-user-registration
Install dev dependencies:
python -m pip install -e ".[dev]"
Run tests:
pytest
Run linting:
ruff check .
Build package:
python -m build
Check package:
python -m twine check dist/*
Upload to TestPyPI:
python -m twine upload --repository testpypi dist/*
Upload to PyPI:
python -m twine upload dist/*
GitHub Actions publishing
This package includes .github/workflows/publish.yml for PyPI Trusted Publishing.
Recommended flow:
- Push your code to GitHub.
- Create the project on PyPI.
- Configure Trusted Publisher on PyPI for your GitHub repository.
- Create a GitHub release.
- GitHub Actions builds and publishes the package.
Security notes
- This toolkit uses Django's active User model through
get_user_model(). - Passwords are saved through Django's
create_user()method. - Django password validators are enabled by default.
- Non-model fields are not saved unless you save them yourself through a hook or your own model.
- Always use HTTPS in production.
- Add throttling/rate limiting to public registration endpoints.
License
MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file humanoid_user_registration-1.0.0.tar.gz.
File metadata
- Download URL: humanoid_user_registration-1.0.0.tar.gz
- Upload date:
- Size: 17.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
68e554a620b6ac1890ef035f8d7e820a0f18f5b9d8ab874d232bf00d415e0685
|
|
| MD5 |
4cc7d1309228479e3b44d168e5b7678d
|
|
| BLAKE2b-256 |
8e0406ce46114740171878b81d2cac0d5a2d71cb73d9809d94b7fbd6520baf41
|
File details
Details for the file humanoid_user_registration-1.0.0-py3-none-any.whl.
File metadata
- Download URL: humanoid_user_registration-1.0.0-py3-none-any.whl
- Upload date:
- Size: 14.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
41a572188cb0a046fa476b01027fa0acfed66c6be97500db1e63208b959abcd3
|
|
| MD5 |
bed9f6c1dcc663a439ece4055885c350
|
|
| BLAKE2b-256 |
a385bf7c72f31515c07510066ed9754a2c36ab1e8d3bc78909c6ac1a481bbfd4
|