O Django Wars foi idealizado e desenvolvido no Django 1.4. Algumas funcionalidades aqui descritas podem não funcionar ou funcionar de forma diferente em outras versões do Django
Em algumas das views do projeto, utilizamos a função redirect().
Enquanto estivemos descrevendo todas as views em um único arquivo views.py, estivemos passando como parâmetros nas chamadas da função redirect() os métodos das views para as quais desejavamos redirecionar.
Neste modo, o Django pega a view, procura a url dela no arquivo urls.py e redireciona.
Porém, como mudamos tudo e agora temos várias views em vários arquivos diferentes, manter essa tática pode quebrar o projeto.
Estamos correndo o perido de sofrer de Circular Imports (imports circulares).
Isso ocorre quando um módulo A importa o módulo B, e o módulo B importa o módulo A.
No processamento Python, ocorre mais ou menos assim:
Pega o arquivo do moduloA.py e processa-o.
Neste arquivo encontra o import do moduloB.py.
Para o processamento de moduloA.py para carregar e processar o moduloB.py.
Ao processar o moduloB.py percebe que este carrega o moduloA.py.
E ai, o Python poderia entrar em loop infinito e explodir o mundo! (não tão grave assim)
Mas o que o Python faz é ver se moduloA está na memória antes de importá-lo.
Como ele está na memória, retorna para o moduloB.py o que está lá.
A bronca é que o que o Python tem naquela hora é só um pedaço do carregamento do moduloA.py.
E ai, se dentro do funcionamento de moduloB.py fizer uma chamada para algo de moduloA.py que ainda não foi carregado, PAU!
Para fugir disso, a coisa mais fácil a se fazer é alterar um pouco o funcionamento do urls.py.
O que vamos fazer é dar nomes as urls.
Na descrição do módulo django.conf.urls vemos como escrever urls bem supimpas.
Mas, para ficar de fácil entendimento como devemos proceder, vou colocar aqui o urls.py modificado.
from django.conf.urls import patterns, include, url import djangowars.views.crimes import djangowars.views.inventario import djangowars.views.loja import djangowars.views.player import djangowars.views.site # Uncomment the next two lines to enable the admin: from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', url(r'^$', djangowars.views.site.index), url(r'^registrar/$', djangowars.views.player.registrar, name='pagina_de_registro'), # pagina de cadastro url(r'^login/$', djangowars.views.player.logar, name='pagina_de_login'), # pagina de login url(r'^crimes/$', djangowars.views.crimes.crimes, name='pagina_de_crimes'), url(r'^crimes/cometer/1/$', djangowars.views.crimes.cometer_crime1), url(r'^crimes/cometer/2/$', djangowars.views.crimes.cometer_crime2), url(r'^loja/$', djangowars.views.loja.loja, name='pagina_da_loja'), # pagina de loja url(r'^loja/comprar/armadura/(\d+)/$', djangowars.views.loja.comprar_armadura), # pagina de loja url(r'^loja/vender/armadura/(\d+)/$', djangowars.views.loja.vender_armadura), # pagina de loja url(r'^loja/comprar/arma/(\d+)/$', djangowars.views.loja.comprar_arma), # pagina de loja url(r'^loja/vender/arma/(\d+)/$', djangowars.views.loja.vender_arma), # pagina de loja url(r'^inventario/$', djangowars.views.inventario.inventario, name='pagina_do_inventario'), url(r'^inventario/equipar/armadura/(\d+)/$', djangowars.views.inventario.equipar_armadura), url(r'^inventario/equipar/arma/(\d+)/$', djangowars.views.inventario.equipar_arma), # Uncomment the next line to enable the admin: url(r'^admin/', include(admin.site.urls)), # Uncomment the admin/doc line below to enable admin documentation: # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), )
Notem que não dei nomes a todas as urls, apenas as urls principais (linhas 17, 18, 20, 24, 30).
Agora, para ser feliz, basta alterar as chamadas da função redirect nas views que a utilizam para, ao invés de se referenciarem através do método da view, utilizarem o nome da url.
Para elucidar o que deve ser feito, vou alterar o arquivo views/player.py
# Create your views here. from django.shortcuts import render # funcoes de renderizacao dos templates from django.shortcuts import redirect # Funcao para executar um http-redirect from django.contrib.auth.forms import UserCreationForm # Formulario de criacao de usuarios from django.contrib.auth.forms import AuthenticationForm # Formulario de autenticacao de usuarios from django.contrib.auth import login # funcao que salva o usuario na sessao # pagina de cadastro de jogador def registrar(request): # Se dados forem passados via POST if request.method == 'POST': form = UserCreationForm(request.POST) if form.is_valid(): # se o formulario for valido form.save() # cria um novo usuario a partir dos dados enviados return redirect(logar) # redireciona para a tela de login else: # mostra novamente o formulario de cadastro com os erros do formulario atual return render(request, "registrar.html", {"form": form}) # se nenhuma informacao for passada, exibe a pagina de cadastro com o formulario return render(request, "registrar.html", {"form": UserCreationForm() }) # pagina de login do jogador def logar(request): if request.method == 'POST': form = AuthenticationForm(data=request.POST) # Veja a documentacao desta funcao if form.is_valid(): #se o formulario for valido significa que o Django conseguiu encontrar o usuario no banco de dados #agora, basta logar o usuario e ser feliz. login(request, form.get_user()) return redirect("pagina_de_crimes") # redireciona o usuario logado para a pagina inicial else: return render(request, "logar.html", {"form": form}) #se nenhuma informacao for passada, exibe a pagina de login com o formulario return render(request, "logar.html", {"form": AuthenticationForm()})
Primeiro, na parte dos imports, removi todos os imports para qualquer outra view.
Na linha 38, alterei a chamada de redirect() para receber o nome da url e não o método que recebia antes.
Notem que na linha 20 não alterei a chamada de redirect().
Como o método chamado, logar, está neste mesmo arquivo, optei por não mudar para ficar de aprendizado que o redirect() possui mais de uma forma de funcionar.
Por fim, farei as alterações em todos os outros arquivos dentro da pasta views.
Espero que vocês façam as alterações nos arquivos de vocês, ou baixem o código pronto direto de:
https://github.com/frenetic/django-wars