That said sometimes you do, and I indeed have had to once myself but I still used the django users table I just had to use different way of performing authentication and then used the login() function to programmatically log the user in afterwards.
Putting that aside from what you have described I do not see why you could not and indeed should not use the built in authentication system. You can extend the users table by creating a new model with a models.OneToOneField and then setup a post_save signal on the User model to automatically an instance of that new model (assuming it had no required attributes other than the foreign key.
If you wish to have custom registration forms then just create them as you would any other form and use Django's authentication system to authenticate them and then log them in -
https://docs.djangoproject.com/en/3.0/topics/auth/default/#authenticating-usersHere's a very loose example of a user profile model that extends the user table to store the date of birth
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")
dob = models.DateField(blank=True, null=True, verbose_name="Date Of Birth")
With this being an example of a signal that is used to ensure that a record is created when the user instance is saved
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)