A composable to handle Django forms in json
- Post and put forms methods
- Errors management from Django form errors
📚 Api doc
yarn add djangoapiforms
# or
npm install djangoapiforms
Or with script src:
<script src="https://unpkg.com/[email protected]/dist/forms.min.js"></script>
Create a forms
object with the composable, passing it an api instance
import { useApi } from "restmix";
import { useForms } from "djangoapiforms";
const api = useApi();
const forms = useForms(api);
export { forms }
For script src a $useForms
object is available once the script loaded:
<script src="https://unpkg.com/[email protected]/dist/api.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/forms.min.js"></script>
<script>
// the $api global var comes from the restmix package imported above
const forms = $useForms($api());
</script>
api
: An instance of the useApi function from the "restmix" library.statusCodes
: (Optional) An object with custom form status codes for schema and validation
Documentation of the api object: check the Restmix documentation
To use a csrf token for the post and put requests:
const api = useApi();
const token="xxx";
api.setCsrfToken(token);
const forms = useForms(api);
To post a form with a payload:
import { forms } from "@/state";
async function postLogin() {
const { error, res, errors } = await forms.post("/api/account/login", {
username: "foo",
password: "bar",
});
if (!error) {
console.log("Everything is ok, the response status code is > 200 and < 299");
} else {
if (error.type == "validation") {
const errorsObject: Record<string,string> = errors;
console.log("The form has validation errors:", errorsObject)
}
else if (res.status == 401) {
// the status code of the response is 401
}
}
}
uri
(str): the endpoint url to post or put topayload
(Record<string, any> | Array): the payload to post or putmultipart
(Optional): post the data in multipart form data format, defaults tofalse
If the form has errors, send them back to the frontend using this format:
errors: Dict[str, List[Dict[str, Any]]]
Example:
from django.contrib.auth.forms import AuthenticationForm
form = AuthenticationForm(data=payload.dict())
if form.is_valid() is False:
errors = {"errors": form.errors.get_json_data(escape_html=True)}
# send the errors data to the frontend
For more info and example check the django-spaninja template documentation
Form error types:
type FormResponseErrorType = "schema" | "validation" | "error";
- The
schema
level indicates a schema validation error from a 418 status code by default. A schema error will throw an error in the console. This is to be used with things like django-ninja that takes advantage of Pydantic schemas - The
validation
level indicates a Django form validation error with a 422 status code by default. The error messages can then be printed to the user - The
error
level happens when the response status code is > 299 and is not handled, like a 500
To customize the status codes for validation and schema levels:
import { useApi } from "restmix";
import { useForms } from "djangoapiforms";
const api = useApi();
const forms = useForms(api, {
schema: 200,
validation: 200,
});
The example above uses the 200 status code for a response with some form validation and schema errors: this is the default behavior of Django. If possible we recommend using a specific status code for errors: we use 422 by default for validation errors, and 418 for schema errors.
Example with the post function's signature:
const post: <T extends {
errors?: FormErrors;
} = Record<string, any>>(
uri: string,
formData: Record<string, any> | Array<any>,
multipart: false
) => Promise<{
error: null | {
type: FormResponseErrorType;
};
res: ApiResponse<T>;
errors: Record<string, string>;
}>
Check the src/interfaces.ts
file for more details.
T
is the expected response payload interface from the backend. This is to use
with schemas
import { FormErrors, FormResponseErrorType } from "djangoapiforms";
interface CustomResponseType {
error?: { type: FormResponseErrorType },
errors?: FormErrors,
// other user defined fields
foo: number;
bar: Array<string>;
}
const { error, res, errors } = await forms.post<CustomResponseType>("/api/account/login", {
username: "foo",
password: "bar",
});
if (!error) {
const responseData: CustomResponseType = res.data;
}
📚 Api doc