Crie um aplicativo com Python, Flask e MongoDB para rastrear OVNIs
Avalie esse Tutorial
Você já olhou para o céu noturno e se perguntou o que está lá fora? Mesmo com a expansão do nosso conhecimento do cosmos - especialmente com o lançamento do Telescópio EspacialJames Webb e o fluxo espetacular de fotos que ele envia de volta - muitos mistérios permanecem. Uma questão perpétua e existencial é se existe outra vida inteligente lá fora.
Embora essa pergunta permaneça sem resposta, há uma variedade de documentarizadores de consumidores por fora rastreando aparições de objetos flutuantes não identificados (OVNIs). O Centro Nacional de Relatórios de OVNIs (NUFORC) coleta relatórios de aparições de OVNIs e os armazena em um banco de dados acessível ao público.
Para explorar os recursos do MongoDB e do driver Pymongo usado com Python e Piper, criei um aplicativo da web completo que permite aos usuários procurar relatórios de aparições de OVNIs com base em dados do NUFORC, bem como enviar um relatório para um banco de dados central em a nuvem com o MongoDB Atlas.
Você pode acessar a base de código completa do aplicativo, mas acompanhe o restante do tutorial para aprender como criar isso por conta própria!
Para ser bem-sucedido com este tutorial, você já deve ter o seguinte pronto para uso:
- MongoDB Atlas, camada gratuita ou superior
Para começar, você precisará ter os dados do NUFORC carregados no MongoDB Atlas. Para fazer isso, baixe um arquivo CSV limpo gratuito desses dados disponíveis no Kaggle.
Inicie sessão no Atlas e copie sua connection string. Em seguida, abra o MongoDB Compass no seu computador e clique no botão "New Connection " para inserir sua connection string do Atlas e conectar-se ao seu banco de dados do Atlas. A partir daqui, crie um banco de dados denominado "ufos " e uma collection nesse banco de dados, também chamada de "ufos ". Ao clicar na collection “ufos, você será direcionado para uma tela onde fará o upload do arquivo CSV dos relatórios de OVNIs baixados do Kaggle.
Agora você tem uma coleção de relatórios de OVNIs na nuvem com o Atlas que pode ser usada como parte do seu aplicativo.
Independentemente do IDE escolhido e se você está trabalhando em um ambiente virtual ou em sua máquina local, siga as melhores práticas do Flask para organizar seu espaço de trabalho para criar este aplicativo.
Há algum tempo , tenho pesquisado oGitHub Codespaces e começado a construir a partir de um aplicativo de amostra do Flusk por lá. Mas você pode ter a melhor experiência usando o VS Code e a extensão MongoDB VS Code.
Crie uma pasta para tudo do seu aplicativo chamada “ufo-spotter-app”. Dentro dessa pasta, crie uma pasta chamada
static
que eventualmente conterá os ativos usados pelos seus modelos. Crie uma segunda pasta chamada templates
dentro da pasta principalufo-spotter-app
onde suas páginas de modelo.html
ficarão.Agora que tudo está configurado em seu ambiente de desenvolvimento e seus dados foram carregados no MongoDB, você está pronto para começar a codificar! Você começará construindo seus modelos. No Flask, os modelos contêm dados estáticos, bem como dados dinâmicos que podem ser transmitidos com a ajuda da biblioteca Jinja no Flask. Você pode aprender mais sobre os modelos do Flask na documentação do Flask.
O primeiro modelo que você construirá é
layout.html
. Este modelo servirá como base para os outros modelos, com o Jingja facilitando a criação a partir do layout.html
sem ter que escrever o mesmo código indefinidamente. Veja abaixo o código para layout.html
, que estabelece o tipo de documento como html, o idioma como inglês, o estilo CSS padrão proveniente do Bootstrap , mas com um link para um segundo arquivomain.css
que criaremos a seguir e a barra de navegação seus usuários confiarão para navegar no website.1 <!DOCTYPE html> 2 3 <html lang="en"> 4 5 <head> 6 7 <meta charset="utf-8"> 8 <meta name="viewport" content="initial-scale=1, width=device-width"> 9 10 <!-- http://getbootstrap.com/docs/5.1/ --> 11 <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous"> 12 <link href="/static/main.css" rel="stylesheet"> 13 14 <title> {% block title %} UFO Spotter {% endblock %}</title> 15 16 </head> 17 18 <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> 19 <div class="container-fluid"> 20 <a href="/" class="navbar-brand"> UFO Spotter 21 </a> 22 <button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#navbarCollapse"> 23 <span class="navbar-toggler-icon"></span> 24 </button> 25 <div class="collapse navbar-collapse" id="navbarCollapse"> 26 <div class="navbar-nav"> 27 <a href="/" class="nav-item nav-link active">Sightings by City</a> 28 29 <div class="collapse navbar-collapse" id="navbarCollapse"> 30 <a class="nav-item nav-link active">|</a> 31 <div class="navbar-nav"> 32 <div class="collapse navbar-collapse" id="navbarCollapse"> 33 <div class="navbar-nav"> 34 <a href="/submit.html" class="nav-item nav-link active">Report a Sighting </a> 35 </div> 36 </div> 37 </nav> 38 39 40 <main class="container-fluid py-5 text-center"> 41 {% block main %} 42 {% endblock %} 43 44 </main> 45 </html>
O html nessa seção cria a barra de navegação com seções clicáveis no canto superior esquerdo que serão consistentes em todas as páginas:
Agora, vamos adicionar um pouco de estilo ao estilo CSS padrão que já temos do Bootstrap. Crie um arquivo chamado
Main.css
na pasta "static " com o seguinte código:1 body { 2 margin: 0; 3 font-family: American Typewriter, serif 4 } 5 6 .small { 7 font-size: 0.75rem; 8 } 9 10 .h3 { 11 margin-bottom: 10px; 12 13 } 14 15 footer { 16 position: absolute; 17 bottom: 0; 18 width: 100%; 19 height: 2.5rem; 20 }
A escolha da fonte da American Typewriter tem como objetivo dar uma atmosfera minimalista e assustadora, de acordo com o tema OVNI, ao mesmo tempo em que é fácil de ler.
Agora estamos realmente entrando no cerne do aplicativo. A próxima coisa que faremos é configurar nosso aplicativo web para permitir que os usuários entrem em uma cidade e estado dos EUA e obtenham estatísticas sobre avistamentos de OVNIs, bem como uma lista dos 10 avistamentos mais recentes. Dessa forma, eles saberão o que devem estar atentos.
Vamos criar o modelo html que renderizaremos para permitir que os usuários insiram uma cidade e um estado dos EUA. Primeiro, você precisa inserir
{% extends "layout.html" %}
na parte superior para basear esse arquivo em layout.html. Em seguida, temos uma imagem interessantes (proveniente de flaticon), algum texto para informar aos visitantes do site como usar a página e um formulário. A primeira seção do formulário permite que o usuário insira texto para o nome da cidade. O próximo usa um loop Minja for para fornecer uma caixa de seleção para os estados dos EUA com base em uma lista do Python de abreviações de estado no app.py file
. Depois disso, só temos o botão "Submit" para trigger o preenchimento do formulário e um rodapé na parte inferior para fornecer a atribuição apropriada para a imagem do OVNI.1 {% extends "layout.html" %} 2 3 {% block title %} 4 Get UFO Reports 5 {% endblock %} 6 7 {% block main %} 8 9 <img src="/static/ufo_icons/ufo7.png" width="100" height="100" alt=""> 10 11 <h5>Enter City and State:</h5> 12 <form action="/" method="post"> 13 <p> 14 <input autocomplete="off" autofocus name="city" placeholder="City" type="text" required> 15 </p> 16 <p> 17 <select class="mx-auto" name="state" placeholder="State" style="width:auto;"> 18 19 {% for state in states %} 20 21 <option value="{{ state }}">{{ state }}</option> 22 23 {% endfor %} 24 </select> 25 26 27 </p> 28 <p> 29 <button type="submit" class="btn btn-primary">Submit</button> 30 </p> 31 </form> 32 33 <footer class="page-footer font-small blue"> 34 35 <div class="footer-attribution text-center"> 36 <a href="https://www.flaticon.com/free-icons/alien" title="alien icons">Alien icons created by Freepik - Flaticon</a> 37 38 </div> 39 40 </footer> 41 {% endblock %}
Veja como a página fica quando renderizada:
Um dos grandes recursos do MongoDB é o document model, que oferece a flexibilidade de modelar seus dados como documentos do tipo JSON que são facilmente mapeados para objetos em seu código. Pessoalmente, achei isso muito mais fácil do que uma abordagem relacional usando uma infinidade de tabelas diferentes e gerenciando uniões de tabelas para diferentes projetos.
Para oferecer suporte ao arquivo
app.py
principal desse aplicativo, criaremos um arquivohelpers.py
com duas funções auxiliares que extraem dados do MongoDB Atlas usando a MongoDB Query API.A primeira função,
get_count()
, usa os estágios de agregação$match
e $count
na API de query para encontrar relatórios de OVNIs com a mesma cidade e estado dos EUA, conforme inserido pelo usuário e retorna o número total de relatórios de OVNIs correspondentes a essa cidade /state combinação.A segunda função,
get_ufos()
, utiliza os estágios de agregação$match
e $sort
. Essa função também encontra relatórios de OVNIs com a mesma cidade e estado dos EUA inseridos pelo usuário e, em seguida, retorna todos esses relatórios classificados pela data do avisamento, do mais recente para o mais antigo.1 import requests 2 3 4 from flask import redirect, render_template, request 5 from pymongo import MongoClient 6 7 8 client = MongoClient('YOUR_CONNECTION_STRING') 9 10 11 def get_count(city, state): 12 """Count the UFO sightings for that city and state""" 13 14 15 city_count = client['ufos']['ufos'].aggregate([ 16 { 17 '$match': { 18 'city': city 19 } 20 }, { 21 '$match': { 22 'state': state 23 } 24 }, { 25 '$count': 'ufo_count' 26 } 27 ]) 28 29 30 return city_count 31 32 33 def get_ufos(city, state): 34 """Gets report of UFO sightings for that city and state""" 35 36 37 recent_ufos = client['ufos']['ufos'].aggregate([ 38 { 39 '$match': { 40 'city': city 41 } 42 }, { 43 '$match': { 44 'state': state 45 } 46 }, { 47 '$sort': { 48 'datetime': -1 49 } 50 }, 51 ]) 52 53 54 return recent_ufos
Agora vamos dar uma olhada na primeira parte do arquivo
app.py
. Primeiro, você precisa importar re
para permitir expressões regulares. Você também precisará importar date
do datetime
para ajudar no processamento das datas relacionadas aos avistamentos. Você receberá o Flask para criar seu aplicativo Flask, bem como render_template
para ajudar na exibição de modelos e request
para receber entradas do usuário de formulários em seus modelos html. Por fim, você precisará importar as funções que criamos no helpers.py
.Depois de mais algumas linhas de código para configurar seu aplicativo, você configurará sua variável
client
para se conectar ao MongoDB Atlas com sua string de conexão (certifique-se de substituir a string de conexão real pelo espaço reservado no código). E você desejará declarar uma matriz de abreviações de estados dos EUA a ser exibida em city.html.1 import re 2 from datetime import date 3 import datetime 4 5 from flask import Flask, render_template, request 6 from pymongo import MongoClient 7 from helpers import get_count, get_ufos 8 9 app = Flask(__name__) 10 11 if __name__ == "__main__": 12 app.run() 13 14 client = MongoClient('YOUR_CONNECTION_STRING') 15 db = client['ufos'] 16 ufos = db.ufos 17 18 # Declare array of U.S. states to use in later functions 19 states = ["AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"]
Agora que você definiu esse arquivo Python como o arquivo principal no centro do seu aplicativo Flask, você criará sua função
city()
com um decorador que atribui o URL e permite que essa função receba solicitações HTTP GET e POST.Ao receber uma solicitação GET do usuário, esta função exibirá o arquivo city.html que criamos anteriormente, passando o array states para nós nesse arquivo.
Se a função for chamada com uma solicitação HTTP POST, processaremos a cidade e o estado dos EUA inseridos pelo usuário assim que ele pressionar o botão "Submit " em
city.html
. Essa função também inclui algum tratamento de erros e retorna uma mensagem de erro apropriada para o usuário se o nome da cidade que ele enviar incluir um número ou um caractere especial, o que nunca deve ser.Usando o método .lower() no Python, convertemos a abreviação em maiúsculas do estado dos EUA em minúsculas para corresponder ao formato do conjunto de dados dos relatórios OVNI .
Podemos obter o número de relatórios de OVNIs no estado especificado pelo usuário com o método .count_documents() no PyMongo. Esse é um método útil para quando você só precisa contar o número de documentos correspondentes a um campo específico, em vez de ter que criar um aggregation pipeline completo com $match e $count para obter esse resultado.
Em seguida, obtemos o número de relatos de OVNIs para essa combinação de cidade/estado usando nosso método auxiliar
get_count()
e uma lista de avistamentos de OVNIs para essa área com a função auxiliarget_ufos()
. Em seguida, o número de avistamentos nesse estado é atribuído à variável state_count
.O número de aparições nessa combinação de cidade/estado é retornado como um cursor com PyMongo, que podemos iterar posteriormente usando um loop for doJinja. E, finalmente, obtemos um cursor que nomeamos
recent_ufos
(que também podemos usar para iterar sobre o grupo de aparições para o qual o cursor aponta) que aponta para uma lista de aparições para essa cidade/estado. Em seguida , state_count
, city_count
e recent_ufos
são passados para o modeloresults.html
para serem exibidos ao usuário.1 @app.route("/", methods=["GET", "POST"]) 2 def city(): 3 4 # Let user submit city and state to look up UFO sightings 5 if request.method == "GET": 6 7 return render_template("city.html", states=states) 8 9 # Return and display results 10 if request.method == "POST": 11 12 # Get city and state from user 13 city = request.form.get("city") 14 state = request.form.get("state") 15 16 # Define error message 17 message = "the name of a valid U.S. city" 18 19 # Return error message if user enters number in city name 20 if request.form.get("city").isnumeric() is True: 21 return render_template("error.html", message=message) 22 23 # Return error message if user enters special character in city name 24 # Attribution: Found way to check for special characters with regex here: https://www.geeksforgeeks.org/python-program-check-string-contains-special-character/ 25 regex = re.compile('[@_!#$%^&*()<>?/\|}{~:]') 26 if regex.search(city) is not None: 27 message = "the name of a valid U.S. city" 28 return render_template("error.html", message=message) 29 30 # Convert city and state to lower case 31 state = state.lower() 32 33 # Count number of UFO sightings in state 34 state_count = ufos.count_documents({"state": state}) 35 36 # Get number of UFO sightings in city and state as a list 37 city_count = get_count(city, state) 38 39 # Get list of recent UFO sightings 40 recent_ufos = get_ufos(city, state) 41 42 return render_template("results.html", state_count=state_count, city_count=city_count, recent_ufos=recent_ufos)
Agora que temos nossa página html onde os usuários podem inserir sua cidade e estado, uma função em nosso arquivo app.py para processar essas informações do usuário e algumas funções auxiliares para apoiar a procura dos dados relevantes, estamos prontos para exibir resultados para o usuário. A página
results.html
é exibida como resultado de uma solicitação de POST bem-sucedida para a funçãocity()
em app.py
. Esta página estende o modelolayout.html
e mostra estatísticas e informações sobre aparições da cidade e estado dos EUA inseridas pelo usuário.Exibiremos o valor de
state_count
passado da função de visualizaçãocity
para o total de aparições no estado inseridos pelo usuário nesta página. Em seguida, usaremos um loop Minja for para percorrer nossa lista de dicionários apontados pelo cursorcity_count
e extrairemos o valor "ufo_count" do dicionário da cidade para exibir na página.Também usaremos um loop for do Jinja para percorrer a lista de dicionários apontados pelo cursor
recent_ufos
. À medida que percorremos o loop, podemos extrair os valores específicos que desejamos exibir para os avistamentos usando a sintaxe usual do Python para procurar um valor em um dicionário.1 {% extends "layout.html" %} 2 3 {% block title %} 4 5 UFOs in Your City and State 6 7 {% endblock %} 8 9 {% block main %} 10 11 <h3>Local Stats:</h3> 12 <p> 13 <b>Total sightings in your state:</b> {{state_count}} 14 </p> 15 <p> 16 <b>Total sightings in your city:</b> 17 {% for city in city_count %} 18 {{city["ufo_count"]}} 19 {% endfor %} 20 </p> 21 22 23 <br> 24 25 <h3>Recent UFO Sightings:</h3> 26 27 <div class="row mx-auto"> 28 29 {% for ufo in recent_ufos %} 30 31 <div class="col-sm-6 mx-auto"> 32 <div class="card text-white bg-secondary mb-3"> 33 <div class="card-body"> 34 <p> 35 <b>Date of Sighting: </b>{{ufo['datetime']}} 36 </p> 37 <p> 38 <b>Date Reported </b>{{ufo['date posted']}} 39 </p> 40 <p> 41 <b>Shape: </b>{{ufo['shape']}} 42 </p> 43 <p> 44 <b>Duration (hours/minutes): </b>{{ufo['duration (hours/min)']}} 45 </p> 46 <p> 47 <b>Description: </b>{{ufo['comments']}} 48 </p> 49 </div> 50 </div> 51 </div> 52 53 {% endfor %} 54 55 {% endblock %}
Esta é a aparência desta página após a busca por relatos de OVNIs em Birmingham, Alabama:
A última coisa que precisaremos fazer nesta seção é criar nosso arquivo error.html, que o usuário verá se não inserir nenhum texto para o nome da cidade ou um caractere numérico ou especial. Esse é um arquivo html muito simples com a mensagem de erro passada para ele a partir de
app.py
.1 {% extends "layout.html" %} 2 3 {% block title %} 4 Error 5 {% endblock %} 6 7 {% block main %} 8 <body> 9 You must submit {{message}}. 10 </body> 11 {% endblock %}
O próximo passo que daremos para desenvolver isso ainda mais é adicionar a funcionalidade para que os usuários insiram seus próprios avistamentos de OVNIs no banco de dados para que outros possam consultar no futuro.
Neste momento, temos um aplicativo web Flask totalmente funcional, no qual os usuários podem enviar uma cidade e um estado, ler o banco de dados do MongoDB Atlas e obter estatísticas e uma lista de avistamentos. Agora, vamos adicionar a funcionalidade de gravação no banco de dados com uma função e páginas html de suporte que permitem aos usuários adicionar suas próprias observações de OVNIs.
Semelhante à nossa função
city()
que já criamos em app.py, nossa nova funçãosubmit()
receberá solicitações GET e POST.A primeira coisa que configuraremos nessa função é o processamento da nossa solicitação GET. Uma solicitação GET aqui leva à exibição da página
submit.html
, que exibirá um formulário com os campos relevantes para que o usuário envie sua observação. Passaremos a matriz de estados dos EUA que usamos anteriormente para o campo de seleção de estado no formulário.Para nossa solicitação POST, a primeira coisa que vamos fazer é criar um dicionário Python vazio chamado
ufo_report
para armazenar o relatório que o usuário está enviando.Em seguida, usaremos a função
request.form.get()
para extrair os valores que o usuário adicionou ao formulário e atribuí-los a variáveis. Usando date.today()
, podemos extrair o mês, dia e ano de hoje para obter a data do envio do relatório sem que o usuário precise inseri-lo manualmente. Em seguida, usando today.strftime()
, nós o colocamos no formato correto para corresponder ao restante do conjunto de dados.Uma coisa importante a se observar é que, geralmente, é prática recomendada armazenar dados de data e hora com objetos Python datetime.datetime (o PyMongo os salvará como tipos de data nativos do MongoDB) em vez de uma string como usamos aqui. No entanto, para simplificar o trabalho com o conjunto de dados públicos da NUFORC, armazenaremos essas informações como strings. Dessa forma, você não precisará baixar os dados do NUFORC e converter todas as strings do conjunto de dados para o tipo de objeto adequado para uso neste tutorial.
Semelhante à nossa função que permite que nossos usuários procurem aparições por cidade e estado, queremos verificar se há entradas incorretas no campo estado no formulário. Usaremos
isnumeric()
para verificar se algum número foi inserido no nome da cidade e uma expressão regular para verificar caracteres especiais. Em seguida, exibiremos uma mensagem de erro se algo estiver errado.Agora que retiramos nossas variáveis do formulário, vamos combiná-las em nosso dicionário python vazio com o operador de atribuição e especificar as chaves apropriadas para cada valor. Como esse aplicativo só analisa aparições de OVNIs nos EUA (por enquanto), definiremos manualmente a abreviação do país como "us ". Quando nosso dicionário para o relatório OVNI estiver completo, nós o inserimos em nossa coleção ufos em nosso banco de dados MongoDB Atlas com
ufos.insert_one(ufo_report)
.Depois que nosso relatório for adicionado, exibiremos uma simples mensagem de obrigado para o usuário no
thank_you.html
.1 @app.route("/submit.html", methods=["GET", "POST"]) 2 def submit(): 3 4 # Display form for user to submit report of UFO sighting 5 if request.method == "GET": 6 7 return render_template("submit.html", states=states) 8 9 # Get data on UFO sighting from form and add to MongoDB 10 if request.method == "POST": 11 12 # Create empty Python dictionary to hold UFO report submitted by form 13 ufo_report = {} 14 15 # Get UFO report information from user form submission 16 city = request.form.get("city") 17 state = request.form.get("state").lower() 18 shape = request.form.get("shape") 19 duration_seconds = request.form.get("duration_seconds") 20 duration_minutes = request.form.get("duration_minutes") 21 comments = request.form.get("comments") 22 sighting_date = request.form.get("datetime") 23 latitude = request.form.get("latitude") 24 longitude = request.form.get("longitude") 25 26 # convert string style date into datetime format 27 sighting_date = datetime.datetime.strptime(sighting_date, "%Y-%m-%dT%H:%M") 28 29 # Get date that user submitted the form 30 # Attribution: Found this way to convert time of form submission here: https://www.programiz.com/python-programming/datetime/current-datetime 31 today = date.today() 32 today = today.strftime("%m/%d/%y") 33 34 # Return error message if user enters number in city name 35 if request.form.get("city").isnumeric() is True: 36 return render_template("error.html", message=message) 37 38 # Return error message if user enters special character in city name 39 # Attribution: Found way to check for special characters with regex here: https://www.geeksforgeeks.org/python-program-check-string-contains-special-character/ 40 regex = re.compile('[@_!#$%^&*()<>?/\|}{~:]') 41 if regex.search(city) is not None: 42 message = "the name of a valid U.S. city" 43 return render_template("error.html", message=message) 44 45 # Compile report details into Python dictionary 46 ufo_report["datetime"] = sighting_date 47 ufo_report["city"] = city 48 ufo_report["state"] = state 49 ufo_report["shape"] = shape 50 ufo_report["duration (seconds)"] = duration_seconds 51 ufo_report["duration (hours/min)"] = duration_minutes 52 ufo_report["comments"] = comments 53 ufo_report["country"] = "us" 54 ufo_report["date posted"] = today 55 ufo_report["latitude"] = latitude 56 ufo_report["longitude"] = longitude 57 58 # Add UFO sighting report to MongoDB Atlas database 59 ufos.insert_one(ufo_report) 60 61 # Return thank-you message after report submission 62 return render_template("thank_you.html")
Se você quisesse fazer algum crédito extra, também poderia modelar os valores de latitude e longitude como um tipo de ponto GeoJSON e indexá-lo para queries do GIS. Veja como na documentação do MongoDB.
Em seguida, criaremos a página html que é exibida quando o usuário envia uma solicitação GET para a função
submit()
. Esta página exibe um formulário onde os usuários podem enviar um registro de seu próprio avistamento de OVNIs. O design do formulário é amplamente extraído do Bootstrap. Assim como fizemos na páginacity.html
, passaremos a matriz de estados e criaremos um loop Jinja para permitir que os usuários selecionem um estado dessa matriz.1 {% extends "layout.html" %} 2 3 {% block title %} 4 Submit UFO Sighting Report 5 {% endblock %} 6 7 {% block main %} 8 <h5>Report a UFO Sighting</h5> 9 10 <br> 11 12 <form action="/submit.html" method="post"> 13 <div class="form-group"> 14 <b>City:</b> <input autocomplete="off" autofocus name="city" id="city" type="text" required> 15 </div> 16 17 <br> 18 19 <div class="form-group"> 20 21 <b>State:</b> 22 <select class="mx-auto" name="state" id="state" placeholder="State" style="width:auto;"> 23 24 {% for state in states %} 25 26 <option value="{{ state }}">{{ state }}</option> 27 28 {% endfor %} 29 </select> 30 </div> 31 32 <br> 33 34 <div class="form-group"> 35 <b>Latitude:</b> <input autocomplete="off" autofocus id="latitude" name="latitude" type="numeric" required> 36 <b>Longitude:</b> <input autocomplete="off" autofocus id="longitude" name="longitude" type="numeric" required> 37 </div> 38 <p> 39 Don't know your latitude and longitude? <a href="https://www.latlong.net/">Look it up here.</a> 40 </p> 41 42 <br> 43 44 <div class="form-group"> 45 <b>Duration (seconds):</b> <input autocomplete="off" autofocus id="duration_seconds" name="duration_seconds" type="numeric"> 46 </div> 47 48 <br> 49 50 <div class="form-group"> 51 <b>Duration (hours/minutes):</b> <input autocomplete="off" autofocus id="duration_minutes" name="duration_minutes" type="text" required> 52 </div> 53 54 <br> 55 56 <div class="form-group"> 57 <b>Shape:</b> <input autocomplete="off" autofocus id="shape" name="shape" type="text" required> 58 </div> 59 60 <br> 61 62 <div class="form-group"> 63 <label><b>Date and Time:</b></label> 64 <input placeholder="datetime" name="datetime" type="datetime-local" required> 65 </div> 66 67 <br> 68 69 <div class="row d-flex justify-content-center"> 70 <div class="form-group" style="width:50%"> 71 <label><b>Comments:</b></label> 72 <textarea class="form-control" rows="2" name="comments" id="comments"></textarea> 73 </div> 74 </div> 75 76 <br> 77 78 <button type="submit" class="btn btn-primary">Submit</button> 79 </form> 80 {% endblock %}
Veja como esta página fica quando renderizada:
Esta página usa Jinja para estender o modelo
layout.html
e exibir uma mensagem de agradecimento de texto simples (e divertida) depois que o usuário envia com sucesso um relatório de avistamento de OVNIs.1 {% extends "layout.html" %} 2 3 {% block title %} 4 Thank You 5 {% endblock %} 6 7 {% block main %} 8 9 <p> 10 Thank you for submitting your report. Live long and prosper. 🖖 11 </p> 12 {% endblock %}
Podemos não conseguir verificar se os extraterrestres estão no espaço. Mas podemos rastrear OVNIs no ciberespaço com MongoDB, Python e Piper.
Com a facilidade de uso do Python e do Flask e a flexibilidade do document model do MongoDB, agora construímos um aplicativo para permitir que os usuários encontrem estatísticas sobre avistamentos de OVNIs em sua área, obtenham relatórios recentes de avistamentos de OVNIs e enviem um avistamento, se estiverem sorte (ou azar) o suficiente para ter seu próprio encontro alienígena.
Consulte a base de código completa para este tutorial no GitHub. Se você acha que este material é válido, não deixe de classificar este tutorial abaixo e compartilhar um link nas redes sociais!
Graças a Shubham Ranjan por contribuir com edições e correções de bugs para este tutorial e código de suporte.