Django forms handle HTML form rendering, validation, and data cleaning through Python classes. A form is defined by subclassing forms.Form and declaring fields like CharField and EmailField. The form.is_valid() method triggers validation, and form.cleaned_data provides access to the validated, converted data. A ModelForm automatically generates form fields from a model by specifying a Meta class with model and fields, and calling form.save() directly creates or updates the corresponding database record. Validation occurs at multiple layers: field-level validation uses built-in validators and clean_<fieldname>() methods, form-level validation is handled in the clean() method for cross-field rules, and model-level validation is implemented on the model itself, with errors stored in form.errors.
The Django admin is an auto-generated web interface for managing data, available at /admin/ after creating a superuser with python manage.py createsuperuser. Models are registered in admin.py using admin.site.register(Model), and a ModelAdmin class allows customization of the interface. The list_display attribute controls which columns appear in the list view, list_filter adds sidebar filters, and search_fields enables a search bar. The @admin.register(Model) decorator is an alternative to the explicit register() call. This combination of ModelForm and the admin interface provides a complete content management experience with very little code.
Django's authentication system is provided by django.contrib.auth, which includes a User model storing credentials and profile information, the authenticate() function to verify credentials, and login() and logout() functions to manage sessions. The @login_required decorator restricts a view to authenticated users, redirecting unauthenticated visitors to the login URL, while the LoginRequiredMixin provides the same functionality for class-based views. The UserPassesTestMixin enables custom authorization by calling a test_func() method. For anonymous visitors, request.user returns an AnonymousUser instance with is_authenticated == False. Django includes a permission system with per-object and per-model permissions, accessed via the @permission_required decorator following the <app_label>.<action>_<modelname> naming convention. Groups bundle permissions and assign them to multiple users at once. A custom user model is created by subclassing AbstractUser or AbstractBaseUser and setting AUTH_USER_MODEL in settings, but this must be done before the first migration. Passwords are hashed using PBKDF2 with SHA256 by default, with user.set_password('new') and user.save() used to update; the default iteration count is 600,000 since Django 4.1, with argon2 or bcrypt as recommended alternatives for stronger security.