associação pythonbrasil[11] django zope/plone planet Início Logado como (Entrar)

Revisão 1e 2007-07-12 15:28:31

Excluir mensagem

Clipper2Django

Receita: De Clipper para DJango

Essa receita foi criada após ter feito um sistema em DJango com intenção de substituir um sistema feito em Clipper. Ela segue passos simples, converter arquivos dbf em arquivos csv, criar as tabelas no banco e importar os registros. Junto com a receita vai o código para converter arquivos csv num model do Django.

A linguagem Clipper, foi muito utilizada para fazer sistemas em pequenas e médias empresas e ainda hoje é comum encontrá-los em produção. Porém, é comum também, descobrir que a empresa que forneceu o sistema já nem existe mais, ou pior, ninguém possui os fontes do sistema, esse é meu caso.

Eu sou um programador Python que gosta de usar o framework django, então graças à minha necessidade desenvolvi uma maneira de converter sistemas que usam tabelas (xbase|*.dbf) para django.

Primeiramente transformei tudo em csv com o programa dbfxtrct. Em seguida desenvolvi um script para ler os arquivos csv e gerar um arquivo model.py de acordo com as regras do django. Outro script foi desenvolvido para importar os dados, em seguida é só ajustar os relacionamentos no model.py e começar a escrever suas views e configurar o url.py.

== Procedimento ==

  • - Converter os arquivos .dbf em arquivos csv, eu usei o programa dbfxtrct. {Há fazer - Encontrar referencia/download}. - Gerar o model com o modelfromcsv.py e gerar o script de importação com o insertfromcsv.py. - Gerar a aplicação django e colocar o model gerado no diretório. - Configurar o arquivo settings.py para reconhecer a aplicação e acessar o banco. - Criar as tabelas à partir do model. - Inserir os dados com o script sql. - Nesse momento já é possível usar o site Admin do django com todas as tabelas e informações do sistema anterior. - Desenvolver as views e configurar o arquivo urls.py

Código

csv_functions.py

d={'C':'models.CharField(maxlength=%d)','D':'models.DateField()','N':'models.FloatField(max_digits=%d, decimal_places=%d)'}

def getFieldList(row):
    field_list = []
    for field_def in row:
        def_list = field_def.split('|')
        field_name = def_list[0].lower()
        field_type = def_list[1]
        field_precision = int(def_list[2])
        field_decimal = int(def_list[3])
        field_list.append({'field_name':field_name,
                           'field_type':field_type,
                           'field_precision':field_precision,
                           'field_decimal':field_decimal})
    return field_list

modelfromcsv.py

   1 import csv
   2 import glob
   3 from csv_functions import d, getFieldList
   4 from getopt import getopt
   5 import sys
   6 
   7 def model(type, digits=0, decimal_places=0, maxlength=0):
   8     if type == 'N':
   9         return d[type] % (digits,decimal_places)
  10     elif type == 'C':
  11         return d[type] % maxlength
  12     else:
  13         return d[type]
  14 
  15 def ModelFromCSV(filename):
  16     ''' Usage : ModelFromcsv('<LOCATION>/<CSVFILE>')
  17     '''
  18     class_template = 'class %s(models.Model):\n'
  19     field_template = '    %s = %s\n'
  20     result_list = []
  21     f=open(filename)
  22     f.seek(0)
  23     class_name = filename.split('/')[-1].split('.')[0].capitalize()
  24     csv_reader = csv.reader(f)
  25     row = csv_reader.next()
  26     field_list = getFieldList(row)
  27 
  28     class_def = class_template % class_name
  29     field_list = [field_template % (x['field_name'],model(x['field_type'],x['field_precision'],x['field_decimal'],x['field_precision'])) for x in field_list]
  30     result_list.append([class_def]+field_list)
  31 
  32     return ''.join([''.join(x) for x in result_list])
  33 
  34 def ModelFromFiles(globstring):
  35     file_list = glob.glob(globstring)
  36     result_list = []
  37     for file_name in file_list:
  38         result_list.append(ModelFromCSV(file_name))
  39 
  40     return '\n'.join(result_list)
  41 
  42 def main(args=sys.argv):
  43     optlist, list = getopt(args[1:], ':f:')
  44     for opt in optlist:
  45         if opt[0] == '-f':
  46             globExpr = opt[1]
  47     print '# Model genereted by modelfromcsv\n'
  48     print ModelFromFiles(globExpr)
  49 
  50 if __name__ == '__main__':
  51     main()

insertfromcsv.py

import csv
import glob
from csv_functions import d, getFieldList
from getopt import getopt
import sys

def InsertFromCSV(filename=''):
    insert_template = 'INSERT INTO %s (%s) VALUES (%s);\n'
    result_list = []
    f=open(filename)
    f.seek(0)
    table_name = filename.split('/')[-1].split('.')[0].lower()
    csv_reader = csv.reader(f)
    row = csv_reader.next()
    field_list = getFieldList(row)
    result_list = []
    for row in csv_reader:
        value_list = []
        field_name_list = []
        for idx, field_def in enumerate(field_list):
            field_value = insert_field_format(field_def['field_type'],row[idx])
            value_list.append(field_value)
            field_name_list.append(field_def['field_name'])
        result_list.append(insert_template % (table_name,','.join(field_name_list),','.join(value_list)))
    return ''.join(result_list)

def insert_field_format(field_type,field_value):
    if field_type == 'N':
        return field_value
    else:
        return '"%s"' % field_value

def SQLInsertFromFiles(globstring):
    file_list = glob.glob(globstring)
    result_list = []
    for file_name in file_list:
        result_list.append(InsertFromCSV(file_name))

    return '\n'.join(result_list)

def main(args=sys.argv):
        optlist, list = getopt(args[1:], ':f:')
    for opt in optlist:
        if opt[0] == '-f':
            globExpr = opt[1]
    print '-- SQL - Insert\n'
    print SQLInsertFromFiles(globExpr)

if __name__ == '__main__':
    main()

Exemplo de uso

   1 import modelfromcsv
   2 
   3 if __name__ == '__main__':
   4    modelText = modelfromcsv.ModelFromFiles('./csv/*dbfxtract')
   5    insertText = insertfromcsv.InsertFromFiles('./csv/*dbfxtract')
   6    print modelText
   7    print insertText

Para utilizar na linha de comando, supondo que todos os arquivos .dbfxtract estão no subdiretório csv:

ramiro@debianhome:~/src$ python modelfromcsv.py -f './csv/*dbfxtract' > model.py
ramiro@debianhome:~/src$ python insertfromcsv.py -f './csv/*dbfxtract' > model.sql

Volta para CookBook.


Nome do autor da Receita [:http://www.pythonbrasil.com.br/moin.cgi/RamiroLuz:Ramiro Batista da Luz]