Atualizando Django 1.6 para 1.9 ou 1.10

pythondjangoEsses dias atrás recebemos a missão de atualizar o Django em um de nossos projetos para a sua versão mais nova e depois de muito esforço conseguimos. Deixo abaixo, anotado todos os passos que fizemos para conseguir tal resultado, para o caso de alguém também precisar, então vamos lá, :)

O South se foi:

A partir da versão 1.7 do Django, não precisamos mais usar o South, pois este foi “incorporado” dentro do Framework e a sintaxe das novas migrações são um pouco diferentes, por isso não são mais compatíveis com a sintaxe do South, sendo assim temos que gerar “essas novas migrações” e depois aplica-lás como “fakes” para só depois conseguirmos usar o novo módulo de migração.

Primeiro

Tenha certeza que todas suas migrações antigas estejam aplicadas.

- IMPORTANTE: Se você usa controle de versão, faça uma nova branch git checkout -b update_django e comece a trabalhar a partir deste ponto. Caso ocorra algum problema é só voltar para o branch anterior :)

Crie um novo virtualenv, pois muitas apps e bibliotecas serão atualizadas e no caso de precisar voltar tudo, basta mudar para o env antigo.

- Atualize o Django.

- Vamos então fazer um backup das migrações antigas, para isso, cole o comando abaixo no seu terminal sem o $ inicial, :), substituindo o caminho abaixo pelo caminho do diretório que contém suas apps. Rode os comandos abaixo no seu shell.

- Depois do backup feito, criamos novamente as “pastas migrations vazias” dentro de cada app:

- E criamos um arquivo __init__.py dentro de cada pasta migrations:

- Em settings.py retire a app ’south’ de INSTALLED_APPS

Fonte: https://docs.djangoproject.com/en/1.9/topics/migrations/#upgrading-from-south

- IMPORTANTE: Daqui para frente é bem provável que os dois comandos abaixo falharão devido ao fato de que ainda é preciso corrigir os pacotes, erros de importação, e muitos outros que irão surgir devido a atualização do Django. Portanto se preciso, corriga os erros e só depois rode os dois comandos abaixo para finalizar o upgrade das suas migrations

- Rode python manage.py makemigrations. Django verá as pastas migration vazias e criará novas initial migrations no novo formato.

- Rode python manage.py migrate --fake-initial. E pronto, seu projeto está apto a criar novas migrações.

Segundo

Aqui está listado as apps que precisei atualizar, para funcionar com Django 1.10

Abaixo alguns erros que aconteceram comigo :(, mas felizmente deu tudo certo no final :)

Primeiro erro:

Retirar tudo de __init__.py e coloque dentro de um arquivo com o nome de apps.py, pois a partir das novas versões, caso você tente carregar alguma model dentro de __init__.py esta não estará disponível, por isso devemos carregá-la no ready de uma classe que estende AppConfig. O arquivo apps.py deve ficar dentro da app em questão. No exemplo abaixo import integracoes.signals_connectors que estava dentro de __init__.py deve ficar como no exemplo abaixo:

Segundo erro:

Erro: django.core.exceptions.ImproperlyConfigured: Creating a ModelForm without either the ‘fields’ attribute or the ‘exclude’ attribute is prohibited; form CampanhaConfiguracoesGeralAdminForm needs updating.

Em todos os ModelForm coloque o campo fields caso este não exista:

Fonte: https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/#selecting-the-fields-to-use

Terceiro erro:

Remover todos os imports from django.conf.urls import patterns

Erro: TypeError: view must be a callable or a list/tuple in the case of include(). 

Ou em urls.py:

Fonte: http://stackoverflow.com/questions/38744285/django-urls-error-view-must-be-a-callable-or-a-list-tuple-in-the-case-of-includexto

Quarto erro:

Em seu settings, mude a configuração do seus templates para:

Fonte: https://docs.djangoproject.com/en/1.10/ref/templates/upgrading/

Quinto erro:

Erro: <class ‘minha_app.admin.MeuAdmin’>: (admin.E111) The value of ‘list_display_links[0]‘ refers to ‘None’, which is not defined in ‘list_display’.

Se dentro de alguma classe admin.ModelAdmin estiver a propriedade list_display_links setada desta forma:

Fonte: http://stackoverflow.com/questions/35184004/how-to-avoid-admin-e111-error-in-django-1-9-2

Sexto erro:

Erro: (urls.E004) Your URL pattern (‘^’, (<module ‘meu_path.urls’ from ‘/home/meu_user/projetos/meu_path/urls.pyc’>, None, None)) is invalid. Ensure that urlpatterns is a list of url() instances. HINT: Try using url() instead of a tuple.

Mude qualquer tupla dentro de urlpatterns

para url() instâncias:

Fonte: http://stackoverflow.com/questions/38786461/django-error-your-url-pattern-is-invalid-ensure-that-urlpatterns-is-a-list-of

Sétimo erro:

Erro: meu.path.suamodel: (fields.E160) The options auto_now, auto_now_add, and default are mutually exclusive. Only one of these options may be present.

mude:

para:

Fonte: https://code.djangoproject.com/ticket/24678

Oitavo erro:

Erro: AttributeError: ‘Options’ object has no attribute ‘module_name’ 

Mude:

Para:

Fonte: https://docs.djangoproject.com/en/1.8/internals/deprecation/

Nono erro: 

Erro: … object has no attribute ‘get_query_set’ class ConfigManager(models.Manager):

mude:

para:

Fonte: https://docs.djangoproject.com/en/1.8/releases/1.8/#features-removed-in-1-8

Décimo erro: 

Erro: set_autocommit got an unexpected keyword argument ‘force_begin_transaction_with_broken_autocommit’

Deixe de usar django-transaction-hooks e use o listener transaction.on_commit() nativo do novo Django.

Fonte 1: https://stackoverflow.com/questions/34114408/set-autocommit-got-an-unexpected-keyword-argument-force-begin-transaction-with/34114416#34114416
Fonte 2: https://docs.djangoproject.com/en/1.9/topics/db/transactions/#django.db.transaction.on_commit

Décimo primeiro erro:

Erro: ‘future’ is not a registered tag library. Must be one of:

Remova todos os imports {% load url from future %} de seus templates pois foi depreciado.

Décimo segundo erro:

Erro: Django error: render_to_response() got an unexpected keyword argument ‘context_instance’

Décimo Terceiro erro:

Erro: ‘The number of GET/POST parameters exceeded ‘ TooManyFieldsSent: The number of GET/POST parameters exceeded settings.DATA_UPLOAD_MAX_NUMBER_FIELDS.

Em seu settings.py coloque a propriedade acima para None, assim DATA_UPLOAD_MAX_NUMBER_FIELDS = None

Fonte: https://docs.djangoproject.com/en/1.10/ref/settings/#data-upload-max-number-fields

Se você usa DRF (Django Rest Framework), com certeza você obterá erros abaixo:

Erro: ‘GetProdutoDetailView’ should either include a queryset attribute, or override the get_queryset() method.

Erro: request.DATA has been deprecated in favor of request.data since version 3.0, and has been fully removed as of version 3.2.

Basta substituir request.DATA por request.data em suas API Views.

Fonte: http://www.django-rest-framework.org/topics/3.2-announcement/#deprecations