Uma das grandes vantagens e ao mesmo tempo desvantagens do Django é que ele faz muita mágica para você. Não é raro o desenvolvedor se perguntar como as coisas são feitas, justamente pelo fato do Django realizar um monte de coisa sem que o programador tenha que interferir.
Inclusive, quando um erro acontece, muitas vezes é difícil detectar porque o framework encapsula muita coisa para nós e ficarmos a mercê dele.
Agora, respondendo suas perguntas. Você esta correto em suas colocações. Agora, vamos detalhar. Vamos por parte. Vejamos esse código:
#connectedin/usuarios/urls.py
from django.conf.urls import patterns, url
from views import RegistrarUsuarioView
urlpatterns = patterns('',
url(r'^registrar/$', RegistrarUsuarioView.as_view(), name="registrar"),
url(r'^login/$', 'django.contrib.auth.views.login', {'template_name':'login.html'}, name='login'),
url(r'^logout/$', 'django.contrib.auth.views.logout_then_login', {'login_url':'/login/'}, name='logout')
)
Veja que são as rotas passadas como primeiro parâmetro para a função url
que indica que o RegistraUsuarioView deve ser chamado para lidar com as informações. As demais rotas para login e logout usam django.contrib.auth..
que já existe no Django prontinho para ser usado. Isso para facilitar a parte que lida com o login e o logout.
Já o RegistraUsuarioForm é usado pelo RegistraUsuarioView para validar a entrada do usuário, verificar se ele preencheu tudo direitinho. É por isso que se abrirmos RegistraUsuarioView
vemos:
# código posterior omitido
class RegistrarUsuarioView(View):
#codigo omitido
def post(self, request):
#preenche o from
form = RegistrarUsuarioForm(request.POST)
Consegui ajudar?