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
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')),
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')),
)
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
# 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
# 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
if request.method == 'POST':
form = AuthenticationForm(data=request.POST) # Veja a documentacao desta funcao
#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
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()})
# 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()})
# 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