.. .. META INFORMATION OF TRANSLATION .. .. $TranslationStatus: Done, waiting for revision $ .. $OriginalRevision: 11332 $ .. $TranslationAuthors: Robson Mendonça $ .. .. INFO OF THIS FILE (DO NOT EDIT! UPDATED BY SUBVERSION) .. .. $HeadURL$ .. $LastChangedRevision$ .. $LastChangedBy$ .. $LastChangedDate$ .. .. _howto-custom-model-fields: ======================================= Escrevendo campos de model customizados ======================================= .. versionadded:: 1.0 Introdução ========== A documentação de :doc:`referência do model ` explica como usar as classes de campos padrão do Django -- :class:`~django.db.models.CharField`, :class:`~django.db.models.DateField`, etc. Para muitos propósitos, estas classes são todas necessárias. Algumas vezes, contudo, a versão do Django não atenderá precisamente as suas exigências, ou você desejará usar um campo que é completamente diferente daqueles entregues com o Django. Os tipos de campos nativos do Django não cobrem todas as possibilidades de tipos de colunas -- somente os tipos comuns, como ``VARCHAR`` e ``INTEGER``. Para os tipos de campos mais obscuros, com polígonos geográficos ou mesmo tipos criados pelo usuário como `tipos personalizados do PostgreSQL`_, você pode definir sua própria subclasse ``Field`` do Django. .. _tipos personalizados do PostgreSQL: http://www.postgresql.org/docs/8.2/interactive/sql-createtype.html Alternativamente, você pode ter um objeto do Python complexo que pode de alguma forma ser serializado para caber dentro da coluna padrão do bando de dados. Este é outro caso onde uma subclasse de ``Field`` ajudará você a usar seu objeto com seus models. Nosso objeto exemplo -------------------- Criar campos personalizados requer um pouco de atenção nos detalhes. Para tornar as coisas mais fáceis de seguir, nós usaremos um exmplo consistente através deste documento: envolvendo um objeto Python representando a oferta de cartas numa mão de Bridge_. Não se preocupe, você não precisa saber como jogar Bridge para seguir este exemplo. Você somente precisa saber que 52 cartas são oferecidas igualmente para 4 jogadores, que são tradicionalmente chamados de *north*, *east*, *south* e *west*. Nossa classe se parece com essa:: class Hand(object): def __init__(self, north, east, south, west): # Input parameters are lists of cards ('Ah', '9s', etc) self.north = north self.east = east self.south = south self.west = west # ... (outros métodos possivelmente úteis omitidos) ... .. _Bridge: http://en.wikipedia.org/wiki/Contract_bridge Esta é somente uma classe Python, com nada específico do Django nela. Nós gostariámos de ter a possibilidade de fazer coisas como essa nos nossos models (nós assumimos que o atributo ``hand`` no model é uma instância de ``Hand``):: example = MyModel.objects.get(pk=1) print example.hand.north new_hand = Hand(north, east, south, west) example.hand = new_hand example.save() Nós atribuímos e recebemos do atributo ``hand`` no nosso model assim como em qualquer outra classe Python. O truque é dizer ao Django como guardar e carregar um objeto. A fim de usar a classe ``Hand`` em nossos models, nós **não** temos que mudar esta classe em nada. Este é o ideal, pois significa que você pode facilmente escrever um suporte de model para classes existentes onde você não pode mudar o código fonte. .. note:: Você pode estar somente querendo obter vantagem dos tipos de campos personalizados de banco de dados e lidar com dados como tipos padrões do Python nos seus models; string, ou floats, por exemplo. Este caso é semelhante ou nosso exemplo ``Hand`` e vamos notar as diferenças a medida que avançamos. Teoria de fundo =============== Armazenamento de banco de dados ------------------------------- A forma mais simples de pensar um campo de model é que ele fornece uma forma de obter um objeto Python normal -- string, boolean, ``datetime``, ou algo mais complexo como ``Hand`` -- e convertê-lo de e para um formato que é útil quando se trabalha com o banco de dados (e serialização, mas, como veremos depois, que cai quase que naturalmente quando você tem o lado do banco de dados sob controle ). Campos num model de alguma forma devem ser convertidos para caber num tipo de coluna de banco de dados existente. Diferentes bancos de dados oferencem diferentes conjuntos de tipos de colunas válidas, mas a regra se mantem a mesma: esses são somente tipos com os quais você tem que trabalhar. Qualquer coisa que você queira armazenar num banco de dados deve combinar com algum desses tipos. Normalmente, você quer escrever um campo do Django para um tipo de coluna de banco de dados em particular, ou existe uma maneira bastante simples para converter seus dados para, digamos, uma string. Para o nosso exemplo ``Hand``, nós poderíamos converter os dados das cartas para uma string de 104 caracteres concatenando todas as cartas juntas numa ordem pre-determinada -- digamos, todas as cartas *north* primeiro, então as cartas *east*, *south* e *west*. Então os objetos ``Hand`` podem ser salvos em colunas de texto ou caracteres no banco de dados. O que uma classee de campo faz? ------------------------------- Todos os campos do Django (e quando dizemos *campos* neste documento, nós sempre nos referimos a campos dos models e não :ref:`campos de formulário `) são subclasses de :class:`django.db.models.Field`. A maior parte das informações que o Django grava sobre um campo é comum a todos os campos -- nome, texto de ajuda, unicidade e assim em diante. O armazenamento de toda essa informação é feito pelo ``Field``. Nós entraremos nos detalhes precisos do que o ``Field`` pode fazer depois; por agora, é suficiente dizer que tudo descende de ``Field`` e então personalizar peças chave do comportamento da classe. É importante notar que uma classe de campos do Django não é o que é armazenado nos atributos do seu model. Os atributos do model contêm objetos Python normais. As classes campo que você define num model são na verdade armazenadas na classe ``Meta`` quando a classe model é criada (os detalhes de como isso é feito não são importantes aqui). Isso é porque as classes campo não são necessárias quando você estiver criando e modificando atributos. Em vez disso, elas fornecem o mecanismo pra conversão entre o valor do atributo e o que é armazenado no banco de dados ou enviado para o :doc:`serializer `. Mantenha isso em mente quando estiver criando seus próprios campos. A subclasse ``Field`` do Djando que você escrever, fornece mecanismos para conversão entre suas instâncias do Python e os valores do banco de dados ou serializer de várias formas (há diferenças entre armazenar um valor e usar um valor para pesquisas, por exemplo). Se isso soa um pouco complicado, não se preocupe -- ele se tornará claro nos exemplos abaixo. Basta lembrar que muitas vezes você vai acabar criando duas classes quando você quer um campo personalizado: * A primeira classe é o objeto Python que seus usuários irão manipular. Eles a atribuirão para o atributo do model, eles irão lê-lo para fins de exibição, coisas desse tipo. Esta é a classe ``Hand`` no nosso exemplo. * A segunda classe é a subclasse de ``Field``. Esta é a classe que sabe como converter sua primeira classe em ambos sentidos entre sua fora de armazenamento permanente e na forma do Python. Escrevendo uma subclasse de campo ================================= Quando estiver brincando com sua subclasse de :class:`~django.db.models.Field`, primeiro reflita um pouco sobre a classe :class:`~django.db.models.Field` existente, sua nova classe é muito semelhante a ela. Você consegue estender um campo existente do Django e poupar um pouco de trabalho? Se não, você deve estender a classe :class:`~django.db.models.Field`d, a partir da qual todas descendem. Inicializar o seu novo campo é uma questão de separar os argumentos que são específicos para seu caso dos argumentos comuns e passando este último para o método :meth:`~django.db.models.Field.__init__` da classe :class:`~django.db.models.Field` (ou sua classe pai). No nosso exemplo, nós chamaremos nosso campo de ``HandField``. (É uma boa idéia chamar sua subclasse :class:`~django.db.models.Field` de ``Field``, isso a torna fácil de identificar como uma subclasse de :class:`~django.db.models.Field`.) Ele não se comporta como qualquer campo existente, sendo assim, nós estenderemos a :class:`~django.db.models.Field` diretamente:: from django.db import models class HandField(models.Field): def __init__(self, *args, **kwargs): kwargs['max_length'] = 104 super(HandField, self).__init__(*args, **kwargs) Nosso ``HandField`` aceita a maioria das opções padrão (veja a lista abaixo), mas nós asseguramos que ela tenha um comprimento fixo, já que somente precisa manter 52 valores de cartas mais seus ternos; 104 caracteres no total. .. note:: Muitos campos de models do Django aceitam opções com as quais não fazem nada. Por exemplo, você pode passar ambos :attr:`~django.db.models.Field.editable` e :attr:`~django.db.models.Field.auto_now` para um :class:`django.db.models.DateField` e ele simplesmente irá ignorar o parâmetro :attr:`~django.db.models.Field.editable` (:attr:`~django.db.models.Field.auto_now` sendo definidos implica em ``editable=False``). Nenhum erro será mostrado nesse caso. Este comportamento simplica as classes de campo, pois elas não precisam verificar por opções que não são necessárias. Elas somente passam todas as opções para a classe pai e então não as usam depois. Cabe a você decidir se você deseja que os campos sejam mais estritos quanto as opções que eles podem selecionar, ou usar a forma mais simples, um comportamento mais permissivo dos campos atuais. O método :meth:`~django.db.models.Field.__init__` recebe os seguintes parâmetros: * :attr:`~django.db.models.Field.verbose_name` * :attr:`~django.db.models.Field.name` * :attr:`~django.db.models.Field.primary_key` * :attr:`~django.db.models.Field.max_length` * :attr:`~django.db.models.Field.unique` * :attr:`~django.db.models.Field.blank` * :attr:`~django.db.models.Field.null` * :attr:`~django.db.models.Field.db_index` * :attr:`~django.db.models.Field.rel`: Usado para relacionar campos (como :class:`ForeignKey`). Para uso avançado somente. * :attr:`~django.db.models.Field.default` * :attr:`~django.db.models.Field.editable` * :attr:`~django.db.models.Field.serialize`: Se ``False``, o campo não será serializado quando o model é passado para o :doc:`serializers ` do Django. O padrão é ``True``. * :attr:`~django.db.models.Field.unique_for_date` * :attr:`~django.db.models.Field.unique_for_month` * :attr:`~django.db.models.Field.unique_for_year` * :attr:`~django.db.models.Field.choices` * :attr:`~django.db.models.Field.help_text` * :attr:`~django.db.models.Field.db_column` * :attr:`~django.db.models.Field.db_tablespace`: Atualmente somente usado com o backend do Oracle e somente para criação de índice. Você normalmente pode ignorar esta opção. * :attr:`~django.db.models.Field.auto_created`: True se o campo foi automaticamente criado, como o `OneToOneField` usado pela herança de model. Somente para uso avançado. Todas as opções sem uma exmplicação na lista acima, tem o mesmo significado que nos campos normais do Django. Veja a :ref:`documentação de campos ` para exemplos e detalhes. A metaclasse ``SubfieldBase`` ----------------------------- Como indicammos na introdução_, subclasses de campo são frequentemente necessárias por duas razões: tanto para se obter vantagem sobre um tipo de coluna de anco de dados personalizada, quanto para manipular tipos complexos do Python. Obviamente, uma combinação dos dois também é possível. Se você está trabalhando somente com tipos de colunas de banco de dados personalizados e seus campos de model aparecem no Python como tipos do Python padrão direto do banco de dados, você não precisa se preocupar com essa seção. Se você estiver manipulando tipos personalizados do Python, como a nossa classe ``Hand``, nós precisamos ter certeza de que quando o Django inicializar uma instância de seu model e atributir um valor do banco de dados para nosso atributo personalizado, nós converteremos esse valor para dentro do objeto Python apropriado. Os detalhes de como isso acontece internamente são um pouco complexos, mas o código que você precisa escrever na sua classe ``Field`` é simples: assegure-se de que sua subclasse use uma metaclasse especial: .. class:: django.db.models.SubfieldBase Por exemplo:: class HandField(models.Field): __metaclass__ = models.SubfieldBase def __init__(self, *args, **kwargs): # ... Isso assegura que o método :meth:`to_python`, documentado abaixo, sempre será chamado quando o atributo for inicializado. Método úteis ------------ Uma vez que você tenha criado sua subclasse de :class:`~django.db.models.Field` e configurado o ``__metaclass__``, você pode considerar sobrescrever alguns métodos padrão, dependendo do comportamento do seu campo. A lista de métodos abaixo está numa ordem descrescente aproximada de importância, então comece de cima. Tipos de banco de dados personalizados ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. method:: db_type(self) Retorna o tipo da coluna do banco de dados para :class:`~django.db.models.Field`, tendo em conta a configuração atual :setting:`DATABASE_ENGINE`. Digamos que você criou um tipo personalizado do PostgreSQL chamado ``mytype``. Você pode usar este campo com o Django através de uma extensão de ``Field`` e implementando o método :meth:`db_type`, tipo assim:: from django.db import models class MytypeField(models.Field): def db_type(self): return 'mytype' Uma vez que você tenha ``MytypeField``, você pode usá-lo em qualquer model, assim como qualquer outro tipo ``Field``:: class Person(models.Model): name = models.CharField(max_length=80) gender = models.CharField(max_length=1) something_else = MytypeField() Se você pretende construir uma aplicação agnóstica de banco de dados, você deve considerar diferenças nos tipos de campos de banco de dados. Por exemplo, o tipo de coluna data/hora no PostgreSQL é chamado ``timestamp``, enquanto que a mesma coluna no MySQL é chamado de ``datetime``. A forma mais simples de lidar com isso dentro do método ``db_type()`` é importando o módulo de configurações do Django e verificando o :setting:`DATABASE_ENGINE`. Por exemplo:: class MyDateField(models.Field): def db_type(self): from django.conf import settings if settings.DATABASE_ENGINE == 'mysql': return 'datetime' else: return 'timestamp' O método :meth:`db_type` é somente chamado pelo Django quando o framework constrói a cláusula ``CREATE_TABLE`` para sua aplicação -- isto é, quando você criar suas tabelas. Ele não é chamado em qualquer outro momento, assim ele pode executar um código pouco complexo, tal como a verificação do :setting:`DATABASE_ENGINE` do exemplo acima. Alguns typos de colunas aceitam parâmetros, como o ``CHAR(25)``, onde o parâmetro ``25`` representa o comprimento máximo da coluna. Em casos como este, é mais flexível se o parâmetro for especificado no model ao invês de ser embutido no código do método ``db_type()``. Por exemplo, não faria muito sentido ter o ``CharMaxlength25Field``, mostrado aqui:: # Este é um exemplo estranho de parâmetros embutidos no código. class CharMaxlength25Field(models.Field): def db_type(self): return 'char(25)' # No model: class MyModel(models.Model): # ... my_field = CharMaxlength25Field() A melhor forma de fazer isso, seria fazer o parâmetro especificável em tempo de execução -- i.e., quando a classe for instânciada. Para fazer isso, basta implementar o :meth:`django.db.models.Field.__init__`, tipo assim:: # Este é um exemplo muito mais flexível. class BetterCharField(models.Field): def __init__(self, max_length, *args, **kwargs): self.max_length = max_length super(BetterCharField, self).__init__(*args, **kwargs) def db_type(self): return 'char(%s)' % self.max_length # No model: class MyModel(models.Model): # ... my_field = BetterCharField(25) Finalmente, se sua coluna requer um SQL de instalação verdadeiramente complexo, retorne ``None`` do método :meth:`db_type`. Isso fará o criador de código SQL do Django pular este campo. Você será então responsável por criar a coluna na tabela certa de alguma outra forma, mas isso lhe dá uma forma de de dizer ao Django para sair do caminho. Convertendo valores de banco de dados para objetos do Python ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. method:: to_python(self, value) Converte um valor retornado do seu banco de dados (ou serializer) para um objeto Python. A implementação padrão simplesmente retorna ``value``, para o caso comum em que o backend de banco de dados já retorna o dado no formato correto (como uma string Python, por exemplo). Se sua classe :class:`~django.db.models.Field` personalizada lida com estrutura de dados que snao mais complexas que strings, datas, inteiros ou floats, então você precisará sobrescrever esse métod. Como uma regra geral, o método deve tomar cuidado com qualquer um dos seguintes argumentos: * Uma instância do tipo correto (e.g., ``Hand`` no nosso exemplo em andamento). * Uma string (e.g., de um deserializer). * Qualquer coisa que o banco de dados retorna para o tipo de coluna que você está usando. Na sua classe ``HandField``, nós armazenamos os dados como um campo VARCHAR no banco de dados, então nós precisamos ser capazes de processar strings e instâncias de ``Hand`` no :meth:`to_python`:: import re class HandField(models.Field): # ... def to_python(self, value): if isinstance(value, Hand): return value # O caso de string. p1 = re.compile('.{26}') p2 = re.compile('..') args = [p2.findall(x) for x in p1.findall(value)] return Hand(*args) Perceba que nós sempre retornams uma instância de ``Hand`` deste método. Este é o tipo de objeto Python que desejamos armazenar no atributo do model. **Lembre-se:** Se seu campo personalizado precisa que o método :meth:`to_python` seja chamado quando ele for criado, você deve estar usando `A metaclasse SubfieldBase`_ mencionada anteriomente. Caso contrário :meth:`to_python` não será chamado automaticamente. Convertendo objetos Python para valores de banco de dados ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. method:: get_db_prep_value(self, value) Este é o contrário de :meth:`to_python` quando trabalha com o backend de banco de dados (como o oposto de serialização). O parâmetro ``value`` é o valor atual do atributo do model (um campo não tem referência para o model que o armazena, então ele não pode receber o valor por si só), e o método deve retornar dados no formato que possa ser usado como um parâmetro numa consulta ao banco de dados. Por exemplo:: class HandField(models.Field): # ... def get_db_prep_value(self, value): return ''.join([''.join(l) for l in (value.north, value.east, value.south, value.west)]) .. method:: get_db_prep_save(self, value) O mesmo mostrado acima, mas chamado quando o valor do campo deve ser *salvo* no banco de dados. Como a implementação padrão apenas chama ``get_db_prep_value``, você não precisa implementar este método a menos que seu campo personalizad precise de uma conversão especial ao ser salvo, o que não é o mesmo quando a conversão é usada para parâmetros de consultas normais (que é implementada por ``get_db_prep_value``). Processando valores antes de salvar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. method:: pre_save(self, model_instance, add) Este método é chamado pouco antes do :meth:`get_db_prep_save` e deve retornar o valor do atributo apropriado do ``model_instance`` para este campo. O nome do atributo está no ``self.attname`` (ele é configurado pelo :class:`~django.db.models.Field`). Se o model estiver sendo salvo no banco de dados pela primeira vez, o parâmetro ``add`` será ``True``, caso contrário, ele será ``False``. Você somente precisa sobrescrever este método se desejar processar o valor de alguma forma, pouco antes de armazená-lo. Por exemplo, o :class:`~django.db.models.DateTimeField` do Django usa esse método para configurar o atributo corretamente no caso do :attr:`~django.db.models.Field.auto_now` ou :attr:`~django.db.models.Field.auto_now_add`. Se você sovrescrever este método, você deve retornar o valor do atributo no final. Você deve também atualizar o atributo do model se você fizer qualquer alteração no valor, desta forma o código mantem as referências para o model, e ele sempre verá o valor correto. Preparando valores para o uso em pesquisas no banco de dados ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. method:: get_db_prep_lookup(self, lookup_type, value) Prepara o ``value`` passando para o banco de dados quando usado numa pesquisa (um constraint ``WHERE`` no SQL). O ``lookup_type`` será um dos filtros válidos do Django para pesquisa: ``exact``, ``iexact``, ``contains``, ``icontains``, ``gt``, ``gte``, ``lt``, ``lte``, ``in``, ``startswith``, ``istartswith``, ``endswith``, ``iendswith``, ``range``, ``year``, ``month``, ``day``, ``isnull``, ``search``, ``regex``, e ``iregex``. Se método deve estar preparado para lidar com todos estes valores de ``lookup_type`` e deve lançar tanto um ``ValueError`` se o ``value`` tiver algum tipo de erro (uma lista quando você estava esperando um objeto, por exemplo) ou um ``TypeError`` se seu campo não suporta tal tipo de pesquisa. Para muitos campos, você pode começar manipulando os tipos de pesquisa que precisam de tratamento especial para seu campo e passar o resto para o método :meth:`get_db_prep_lookup` da classe pai. Se você precisa implementar o ``get_db_prep_save()``, você normalmente precisará implementar ``get_db_prep_lookup()``. Se você não o fizer, ``get_db_prep_value`` será chamado pela implementação padrnao, para gerenciar as pesquisas ``exact``, ``gt``, ``gte``, ``lt``, ``lte``, ``in`` e ``range``. Você pode também querer implementar este método para limitar os tipos de pesquisa que podem ser usados com seu tipo de campo. Note que, para ``range`` e ``in``, ``get_db_prep_lookup`` receberá uma lista de objetos (presumidamente o tipo certo) e terá de convertê-los em uma lista de coisas do tipo certo para passar para o banco de dados. Na maioria das vezes, você poderá reusar ``get_db_prep_value()``, ou pelo menos um fator comum a algumas partes. Por exemplo, o seguinte código implementa ``get_db_prep_lookup`` para limitar os tipos de pesquisa aceitos para ``exact`` e ``in``:: class HandField(models.Field): # ... def get_db_prep_lookup(self, lookup_type, value): # Nós somente manipulamos 'exact' e 'in'. Todos os outros são erros. if lookup_type == 'exact': return [self.get_db_prep_value(value)] elif lookup_type == 'in': return [self.get_db_prep_value(v) for v in value] else: raise TypeError('Lookup type %r not supported.' % lookup_type) Especificando o campo de formulário para o campo de model ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. method:: formfield(self, form_class=forms.CharField, **kwargs) Retorna o campo de formulário padrão para se usar quando este campo é mostrado num model. Este método é chamado pelo helper :class:`~django.forms.ModelForm`. Tudo no dicionário ``kwargs`` é passado diretamente para o método :meth:`~django.forms.Field__init__` do campo. Normalmente, tudo que você precisa fazer é configurar um bom padrão para o argumento ``form_class`` e então delegar mais manipulação para a classe pai. Isso pode exigir que você escreva um campo de formulário personalizado (ou mesmo um widget de formulário). Veja a :doc:`documentação de formulários ` para mais informação sobre isso, e dê uma olhada no código :mod:`~django.contrib.localflavor` para ter mais exemplos de widgets personalizados. Continuand nosso exemplo, nós podemos escrever o método :meth:`formfield` como:: class HandField(models.Field): # ... def formfield(self, **kwargs): # Esta é uma forma bastante normal para configurar alguns padrões # enquanto deixa o chamador sobrescrever eles. defaults = {'form_class': MyFormField} defaults.update(kwargs) return super(HandField, self).formfield(**defaults) Isso assume que nós imporamos uma classe de campo ``MyFormField`` (que tem seu próprio widget padrão). Este documento não cobre os detalhes de se escrever campos de formulário personalizados. .. _helper functions: ../forms/#generating-forms-for-models .. _forms documentation: ../forms/ Emulando tipos de campos nativo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. method:: get_internal_type(self) Retorna uma string dando o nome da subclasse de :class:`~django.db.models.Field` que nós estamos emulando a nível de banco de dados. Isso é utilizado para determinar o tipo de coluna de banco de dados para casos simples. Se você criou um método :meth:`db_type`, você não precisa se preocupar com o :meth:`get_internal_type` -- não será muito usado. Algumas vezes, embora, o armazenamento de banco de dados é de um tipo semelhante a algum outro campo, assim você pode usar a lógica de outro campo para criar a coluna certa. Por exemplo:: class HandField(models.Field): # ... def get_internal_type(self): return 'CharField' Não importa que backend de banco de dados nós usemos, isso significará que o ``syncdb`` e outros comandos SQL criam o tipo certo de coluna para armazenar uma string. Se :meth:`get_internal_type` retorna uma string que não é conhecida pelo Django para backend do banco de dados que você está usando -- isto é, ele não aparece em ``django.db.backends..creation.DATA_TYPES`` -- a string continuará sendo usada pelo serializer, mas o método padrão :meth:`db_type` retornará ``None``. Veja a documentação de :meth:`db_type` por razões do porquê isso pode ser útil. Colocando uma string descritiva como o tipo de campo para o serializer é uma boa idéia se você estiver sempre usando a saída do serializer em algum outro lugar, fora do Django. Convertendo dados do campo por serialização ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. method:: value_to_string(self, obj) Este método é usado pelo serializer para converter o campo numa string de saída. Chamando :meth:`Field._get_val_from_obj(obj)` é a melhor forma de obter o valor para serializar. Por exemplo, desde que nosso ``HandField`` use strings para seu armazenamento de dados de qualquer forma, nós podemos reusar algumas conversões de código existente:: class HandField(models.Field): # ... def value_to_string(self, obj): value = self._get_val_from_obj(obj) return self.get_db_prep_value(value) Alguns conselhos gerais ----------------------- Escrevendo um campo personalizado pode ser um processo complicado, particularmente se você estiver fazendo uma conversões complexas entre seus tipos Python e seu banco de dados e formatos serializados. Há algumas dicas para tornar as coisas mais suaves: 1. Procure por campos existentes do Django (no :file:`django/db/models/fields/__init__.py`) para inspiração. Tente encontrar um campo que seja similar ao que você deseja fazer e estenda-a um pouco, ao invês de criar uma totalmente do zero. 2. Coloque um método :meth:`__str__` ou :meth:`__unicode__` na classe que está envolvendo como um campo. Há um monte de lugares onde comportamento padrão do código do campo é chamar :func:`~django.utils.encoding.force_unicode` sobre o valor. (Nos nossos exemplos neste documento, ``value`` poderia ser uma intância de ``Hand``, não um ``HandField``). Portanto se seu método :meth:`__unicode__` converte automaticamente para uma string a partir de seu objeto Python, você pode poupar a si mesmo um monte de trabalho. Escrevendo uma extensão de ``FileField`` ======================================== Além dos métodos acima, campos que lidam com arquivos possuem alguns poucos requesitos especiais que deve ser tomado nota. A maioria dos mecanismos fornecidos pelo ``FileField``, como controlador de armazenamento de banco de dados e recebimento, podem permenacer imutáveis, deixando a subclasse para lidar com o desafio de suportar um tipo particular de arquivo. O Django fornece uma classe ``File``, que é usada como um proxy entre o conteúdo do arquivo e as operações. Este pode ser estendido para customizar como o arquivo é acessado, e quais métodos são disponíveis. Ele fica em ``django.db.models.fields.files``, e seu comportamento padrão é explicado na :ref:`documentação de arquivo `. Uma vez que uma subclasse de ``File`` é criada, a nova subclasse de ``FileField`` deve ser instruída a usá-la. Para fazer isso, simplesmente atribua a nova subclasse ``File`` para o atributo especial ``attr_class`` da subclasse ``FileField``. Umas poucas sugestões --------------------- Além dos detalhes acima, há umas poucas linhas guias que podem melhorar muito a eficiência e legibilidade do código dos campos. 1. O fonte dos próprios campos do Django ``ImageField`` (em ``django/db/models/fields/files.py``) é um grande exemplo de como a subclasse ``FileField`` pode suportar um tipo de arquivo em particular, e como incorpora todas as técnicas descritas acima. 2. Cacheie os atributos dos arquivos sempre que possível. Uma vez que arquivos podem ser guardados em sistemas de armazenamento remotos, recebê-los pode custar um tempo extra, ou mesmo dinheiro, o que nem sempre é necessário. Uma vez que o arquivo é recebido para obter algum dado sobre seus conteúdos, cacheie o máximo de dados que for possível para reduzir o número de vezes que o arquivo deve ser recebido em chamadas subsequentes para esta informação.