Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Junte-se a nós no Amazon Web Services re:Invent 2024! Saiba como usar o MongoDB para casos de uso de AI .
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Idiomaschevron-right
Pythonchevron-right

Crie um site de reserva de propriedades com Starlette, MongoDB e Twilio

Ado Kukic17 min read • Published Jan 27, 2022 • Updated Sep 09, 2024
Python
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Alguns recursos mencionados abaixo serão descontinuados em 30, 2025 de setembro. Saiba mais.
Como desenvolvedores, muitas vezes temos a capacidade de escolher nossas próprias ferramentas para realizar o trabalho. Se você é como eu, sempre que uma nova framework constrói uma imagem de alto desempenho, você começa a ver como é a experiência do desenvolvedor. No artigo de hoje, gostaria de ver como criar um aplicativo web com um framework Python ASGI chamado Starlette , que promessa de desempenho rapido e a produtividade do programador. Testaremos a Starlette integrando MongoDB, Stitche Twilio para criar um aplicativo de reserva de propriedade do tipo AirBnB .
Se quiser acompanhar este tutorial, você pode obter o código no repositório do Github. Além disso, certifique-se de se inscrever em uma conta gratuita do MongoDB Atlas para facilitar a conexão ao seu MongoDB database. Neste tutorial, usaremos um conjunto de dados de amostra fornecido pelo MongoDB Atlas.

O que é o Starlette

Starlette é uma estrutura Python ASGI que se destaca. É uma estrutura relativamente nova, mas já chamou a atenção de muitos desenvolvedores Python por seu alto desempenho, suporte para WebSockets, GraphQL, Impressionante cobertura de teste 100% e zero dependências rígidas.
Logotipo Starlette
A framework é muito leve e fácil de usar. O que é realmente importante no Starlette é que ele pode ser tratado como um framework inteiro ou apenas um conjunto de ferramentas, onde os componentes podem ser utilizados de forma independente em seu framework ou aplicativo existente. Para este tutorial, trataremos a Starlette como uma estrutura e construiremos todo o nosso aplicativo com a Starlette. Para este tutorial, presumirei que você está familiarizado com o Python, mas se precisar de uma atualização, não há lugar melhor do que o tutorial oficial do Python.

Projeto de hoje: MongoBnB

Hoje vamos construir um sistema de reserva de aluguel, semelhante ao AirBnB, que nomearemos modalmente de MongoBnB. Nosso aplicativo exibirá uma lista de propriedades em destaque, permitirá que o usuário classifique por vários parâmetros, visualize detalhes adicionais de uma propriedade selecionada e, por fim, reserve e cancele reservas.
MongoBnB
Temos muito o que fazer hoje, então vamos mergulhar de cabeça!

Construindo Nosso Conjunto de Dados

Como mencionei no início deste artigo, vamos utilizar um conjunto de dados de amostra fornecido pelo MongoDB Atlas. Se você ainda não tiver uma conta, inscreva-se gratuitamente aquie crie um novo cluster. Depois de ter um cluster em funcionamento, seja ele novo ou existente, carregue o conjunto de dados de amostra clicando no botão de três pontos para ver opções adicionais e, em seguida, selecione "Carregar conjunto de dados de amostra".
Carregar conjunto de dados de amostra
O conjunto de dados de amostra fornecido pelo MongoDB Atlas criará diversas collection contendo vários conjuntos de dados. Navegue até a abaCollection para ver todas. Todos os conjuntos de dados serão criados como bancos de dados separados prefixados com sample_ e, em seguida, o nome do conjunto de dados. Pode levar alguns minutos para que todos os bancos de dados sejam importados, mas o único que nos importa para nosso aplicativo é chamado sample_airbnb. Abra este banco de dados e você verá uma collection chamada listingsAndReviews. Clique nele para ver os dados com os quais trabalharemos.
Amostra do conjunto de dados AirBnB
Essa coleção terá mais 5,000 documentos, cada um contendo todas as informações que poderíamos desejar para uma listagem específica. Para nosso aplicativo, trabalharemos apenas com um subconjunto dos dados, mas você terá muitos dados existentes para expandir caso deseje adicionar recursos adicionais além do escopo do tutorial. Dê uma olhada no conjunto de dados e familiarize-se com ele um pouco. Execute algumas queries de filtro, como {"price": {"$lt":10}} ou {"review_scores.review_scores_rating":100} para encontrar algumas propriedades realmente acessíveis ou algumas das mais bem classificadas, respectivamente.
Agora que temos nosso conjunto de dados pronto, vamos escrever um pouco de Python.

Configurando nosso aplicativo Starlette

Para começar a usar o Starlette, precisaremos instalá-lo.Ogerenciador de pacotes pipdo Python pode ajudar com isso. Abra seu terminal e execute o comando pip3 install starlette. O Starlette em si não é um servidor, portanto, também precisaremos instalar um servidor ASGI. Há muitas opções como uvicorn, daphneou hypercorne, para nosso tutorial, usaremos uvicorn. Se você ainda não tem o uvicorn instalado, execute o comando pip3 install uvicorn e iniciaremos as corridas.
Enquanto instalamos dependências, vamos instalar uma última necessária para nosso aplicativo, que é oJinja. Jinja é um mecanismo de modelo para Python que usaremos para renderizar nosso aplicativo no navegador. Execute pip3 install jinja2 para instalá-lo. Esta é uma dependência opcional para a estrutura do Starlette.

Olá, Starlette

Agora que temos nossas dependências instaladas, estamos prontos para escrever algum código. Crie um novo arquivo python chamado app.py. Esse será o nosso principal ponto de entrada no aplicativo Starlette. Para começar, vamos configurar o aplicativo Starlette mais básico para garantir que todas as nossas dependências foram instaladas corretamente. Escreva o seguinte código:
1from starlette.applications import Starlette
2from starlette.routing import Route
3from starlette.responses import PlainTextResponse
4
5async def homepage(request):
6 return PlainTextResponse("Hello from Starlette")
7
8app = Starlette(debug=True, routes=[
9 Route('/', homepage),
10])
O código acima importa a estrutura do Starlette ou vários componentes do kit de ferramentas, como roteamento e respostas. Em seguida, na linha 8, criamos uma instância do nosso aplicativo Starlette. Para nosso aplicativo, queremos que a depuração esteja ativada para que tenhamos relatórios de erro detalhados e, para o segundo parâmetro, passamos nossas rotas. Para este aplicativo de teste, teremos apenas uma rota e a chamaremos de homepage. Por fim, implementamos essa rota da página inicial e tudo o que ela faz é exibir a mensagem "Hello from Starlette" no navegador do usuário.
Vamos garantir que nosso aplicativo funcione. Como instalamos o uvicorn como nosso servidor ASGI, o usaremos para iniciar nosso aplicativo. No terminal, execute o comando uvicorn app:app no diretório onde reside seu arquivo app.py . Isso iniciará o servidor padrão nolocalhost:8000. Você receberá uma mensagem no terminal informando que o servidor Uvicorn está em execução se tudo correr bem. Se você tiver problemas neste ponto, certifique-se de que todos os pacotes pip acima estejam instalados. Confira a Docs do uvicorn para solução de problemas.
Se tudo correu bem e o servidor estiver instalado e funcionando, navegue até localhost:8000 no seu navegador e você verá a mensagem "Olá da Starlette." Parabéns! Você acabou de criar seu primeiro aplicativo Starlette. Agora vamos construir algo real.

Arquitetura do MongoBnB

Temos um aplicativo Starlette básico em funcionamento, agora vamos expandi-lo para o nosso aplicativo tutorial. Embora certamente pudéssemos adicionar todo o nosso código nesse único arquivoapp.py, essa não seria a experiência ideal para o desenvolvedor. Portanto, vamos definir nossos requisitos e dividir nosso aplicativo em vários arquivos.
Sabemos que teremos várias rotas, então vamos criar um arquivoroutes.py para abrigá-las. Nossas rotas se comunicarão com nosso banco de dados e, em vez de criar uma conexão com nosso cluster em cada rota, criaremos um pool de conexões e o passaremos como middleware, então vamos criar também um arquivomiddleware.py. Em seguida, como vimos em nosso conjunto de dados, não trabalharemos com todo o documento, então criaremos também um arquivomodels.py que conterá nossos modelos. Finalmente, parece que estamos construindo um aplicativo do tipoMVC onde temos modelos, nossas rotas são nossos drivers, então vamos adicionar um diretóriotemplates, que manterá nossas visualizações.
Agora que criamos nosso diretório de modelos, vamos decidir o que nosso aplicativo fará. Nosso aplicativo terá três visualizações diferentes:
  • Uma página inicial que exibe listagens
  • Uma página de anúncios que exibe detalhes adicionais sobre uma propriedade específica
  • Uma página de confirmação que é exibida quando um usuário reserva uma propriedade
No diretóriotemplates, vamos criar um arquivoindex.html, listing.htmle confirmation.html para nossas três visualizações. Em cada um dos arquivos, vamos apenas criar um esqueleto da página que queremos renderizar.
1<html>
2<head>
3 <title>MongoBnB | Home</title>
4 <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
5</head>
6<body>
7 <h1>Home!</h1>
8</body>
9</html>
Repita para as páginaslisting.html e confirmation.html . Observe que também estamos introduzindo oTailwindCSS. O Tailwind nos permitirá estilo melhor nossas páginas sem escrever um monte de CSS personalizado.
Estrutura de diretório MongoBnB
Já que temos nossas visualizações de esqueleto criadas, vamos abrir o arquivoroutes.py e conectar nossas visualizações aos nossos comandos. No arquivoroutes.py, adicione o seguinte código:
1from starlette.templating import Jinja2Templates
2
3templates = Jinja2Templates(directory='templates')
4
5async def homepage(request):
6 return templates.TemplateResponse('index.html', {'request': request})
7
8async def listing(request):
9 return templates.TemplateResponse('listing.html', {'request': request})
10
11async def confirmation(request):
12 return templates.TemplateResponse('confirmation.html', {'request': request})
No código acima, estamos importando modelos doJinja2 e definindo o diretório padrão onde nossas visualizações residirão. Em seguida, criamos três funções assíncronas para nossos três comandos. No momento, não estamos fazendo nenhuma lógica, estamos apenas servindo conteúdo html estático. A peça final do quebra-cabeça será conectar essas novas rotas ao nosso aplicativo Starlette. Abra o app.py e faça os seguintes ajustes na base de código:
1from starlette.applications import Starlette
2from starlette.routing import Route
3from routes import homepage, listing, confirmation
4
5app = Starlette(debug=True, routes=[
6 Route('/', homepage),
7 Route('/listing/{id}', listing),
8 Route('/confirmation/{id}', confirmation),
9])
Estamos substituindo nosso roteamento padrão pelas novas rotas que criamos no arquivoroutes.py. Reinicie o servidor uvicorn e tente navegar para localhost:8000, localhost:8000/listing/1e localhost:8000/confirmation/1 e todas essas três rotas devem carregar e exibir a mensagem que você criou anteriormente.

Conectando Starlette ao MongoDB

Cite uma dupla mais icônica do que Python e SQLAlchemy. Felizmente, a Starlette não tem dúvidas sobre com qual tecnologia de banco de dados você deve trabalhar e não prefere SQL a NoSQL. Para nosso tutorial, como temos nosso conjunto de dados no MongoDB Atlas, usaremos o Mongo e o ótimo pacote pymongo.
Se você ainda não tem o PyMongo instalado, faça isso agora executando o pip3 install pymongo. Após a instalação do PyMongo , abra o arquivomiddleware.pyque criamos anteriormente. É aqui que instanciaremos nossa conexão com o MongoDB para que possamos interagir com o conjunto de dados e preencher nosso aplicativo com dados reais.
1from starlette.middleware import Middleware
2from starlette.middleware.base import BaseHTTPMiddleware
3import pymongo
4import ssl
5
6class DatabaseMiddleware(BaseHTTPMiddleware):
7 async def dispatch(self, request, call_next):
8 client = pymongo.MongoClient("{YOUR-CONNECTION-STRING}", ssl_cert_reqs=ssl.CERT_NONE)
9 db = client["sample_airbnb"]
10 request.state.db = db
11 response = await call_next(request)
12 return response
13
14middleware = [
15 Middleware(DatabaseMiddleware)
16]
O código acima criará uma nova função de middleware chamada DatabaseMiddleware. Esta função usará o PyMongo para estabelecer uma conexão com nosso cluster MongoDB Atlas . Em seguida, queremos nos conectar apenas ao nosso banco de dadossample_airbnb. Antes que o resultado dessa função seja passado para o controlador individual, adicionaremos uma nova variável de estado chamada db à nossa solicitação e a enviaremos para o próximo middleware ou a função final do controlador. Em nosso caso, só teremos esta função de middleware que será executada.
Agora que temos nossa função de middleware definida, criaremos uma nova instância de Middleware, passaremos em nosso DatabaseMiddlewarerecém-criado e o armazenaremos em uma variável de middleware. Para usar esse middleware em todas as nossas rotas, abriremos o app.py e fará os seguintes ajustes em nossa instanciação Starlette:
1from starlette.applications import Starlette
2from starlette.routing import Route
3from middleware import middleware
4from routes import homepage, listing, confirmation
5
6app = Starlette(debug=True, routes=[
7 Route('/', homepage),
8 Route('/listing/{id}', listing),
9 Route('/confirmation/{id}', confirmation),
10], middleware=middleware)
Com o middleware instalado, estamos prontos para começar a implementar nossas funções de controlador. Esse middleware agora será executado em todas as nossas funções. Poderíamos ser granulares e passá-lo apenas para rotas específicas, mas, como todas as nossas rotas se comunicarão com o banco de dados, faz sentido aplicar esse middleware globalmente. Poderemos acessar nosso banco de dados em cada rota por meio de request.state.db.

Definindo nosso modelo de dados

Sabemos como é o nosso modelo de dados no MongoDB, mas o nosso aplicativo Starlette não sabe. Para este aplicativo, teremos apenas um modelo, mas precisamos defini-lo. Abra models.py e adicione o seguinte código:
1class Property():
2 def __init__(self, id, name, summary, address, price, cleaning_fee, guests, image, amenities):
3 self.id = id
4 self.name = name
5 self.summary = summary
6 self.address = address
7 self.price = price
8 self.cleaning_fee = cleaning_fee
9 self.guests = guests
10 self.image = image
11 self.amenities = amenities
Este código nos permitirá criar instâncias de uma propriedade que contenham apenas um subconjunto de todos os dados que recebermos de nosso MongoDB database.

Implementação da página inicial

Temos todo o trabalho de base feito, agora podemos implementar nossos controladores. O primeiro que abordaremos é a página inicial. Abra routes.py e adicione o seguinte código:
1from starlette.templating import Jinja2Templates
2from models import Property
3
4async def homepage(request):
5 data = request.state.db.listingsAndReviews.find({'cleaning_fee':{'$exists': True}}, limit=15)
6
7 response = []
8
9 for doc in data:
10 response.append(
11 Property(
12 doc['_id'],
13 doc['name'],
14 doc['summary'],
15 doc['address']['street'],
16 str(doc['price']),
17 str(doc['cleaning_fee']),
18 str(doc['accommodates']),
19 doc['images']['picture_url'],
20 doc['amenities']
21 )
22 )
23
24 return templates.TemplateResponse('index.html', {'request': request, 'response': response})
Vamos detalhar o código que adicionamos para a página inicial até agora. Na primeira linha, estamos usando a propriedaderequest.state.db passada do middleware que contém nossa conexão do MongoDB. Estamos acessando a collectionlistingsAndReviews e executando uma operação find(). Queremos retornar propriedades 15 e o único filtro que estamos aplicando é que uma propriedadecleaning_fee deve existir no documento.
Quando isso for executado, receberemos um cursor que contém nossos dados. Em seguida, iteraremos sobre esse Cursor e criaremos novas instâncias da classe Property para cada documento no cursor. Cada propriedade será anexada a uma lista de respostas, e essa lista de respostas será enviada junto com nossa solicitação para nosso modelo Jinja, onde teremos acesso a todos os dados.
Vamos retornar ao nosso arquivoindex.html agora e atualizá-lo com a interface do usuário real que queremos construir.
1<html>
2<head>
3 <title>MongoBnB | Home</title>
4 <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
5</head>
6<body>
7
8 <div class="container mx-auto">
9 <div class="flex">
10 <div class="row w-full text-center my-4">
11 <h1 class="text-4xl font-bold mb-5">MongoBnB</h1>
12 </div>
13 </div>
14 <div class="flex flex-row flex-wrap">
15 {% for property in response %}
16 <div class="flex-auto w-1/4 rounded overflow-hidden shadow-lg m-2">
17 <img class="w-full" src="{{ property.image }}">
18 <div class="px-6 py-4">
19 <div class="font-bold text-xl mb-2">{{ property.name }} (Up to {{ property.guests }} guests)</div>
20 <p>{{ property.address }}</p>
21 <p class="text-gray-700 text-base">
22 {{ property.summary }}
23 </p>
24 </div>
25
26 <div class="text-center py-2 my-2 font-bold">
27 <span class="text-green-500">${{ property.price }}</span>/night (+<span class="text-green-500">${{ property.cleaning_fee }} </span>Cleaning Fee)
28 </div>
29
30 <div class="text-center py-2 my-2">
31 <a href="/listing/{{property.id}}" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Details</a>
32 <a href="/confirmation/{{property.id}}" class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">Book</a>
33 </div>
34 </div>
35 {% endfor %}
36 </div>
37 </div>
38</body>
39</html>
Salve o arquivoindex.html e o arquivo routes.py. Reinicie o servidor uvicorn e navegue até localhost:8000. O resultado exibido deve ficar como a imagem abaixo:
Página inicial do MongoBnB
Excelente! Nossa página inicial está com boa aparência. Ela está mostrando 15 resultados que vêm do MongoDB database. Clicar em Details (Detalhes ) ou Booking (Reserva) apenas leva você a uma página HTML vazia por enquanto, mas tudo bem, ainda não chegamos lá. Antes de implementá-los, vamos também adicionar alguns filtros à nossa página inicial para ajudar nossos visitantes a descobrir propriedades adicionais.
Na página index.html, adicione o seguinte código abaixo da tag<h1 class="text-4xl font-bold mb-5">MongoBnB</h1> :
1<div class="inline-flex">
2 <a href="/" class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-l">
3 Featured
4 </a>
5 <a href="/?filter=under-100" class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-r">
6 Under 100
7 </a>
8 <a href="/?filter=highly-rated" class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-r">
9 Highly Rated and Cheap
10 </a>
11 <a href="/?filter=surprise" class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-r">
12 Surprise Me
13 </a>
14</div>
O que isso fará é passar um parâmetro de query chamado filter com um filtro predefinido. Os filtros serão para propriedades abaixo de $100, propriedades muito bem avaliadas e uma surpreendente que você mesmo pode implementar. Vamos abrir nosso filtroroutes.py e editar a rotahomepage para suportar esses filtros.
1async def homepage(request):
2 try:
3 filter = request.query_params['filter']
4
5 if filter == 'under-100':
6 data = request.state.db.listingsAndReviews.find({'$and':[{'cleaning_fee':{'$exists': True}},{'price': {'$lt': 100}}]}, limit=15)
7 elif filter == 'highly-rated':
8 data = request.state.db.listingsAndReviews.find({'$and':[{'cleaning_fee':{'$exists': True}},{'price': {'$lt': 100}},{'review_scores.review_scores_rating': {'$gt': 90}}]}, limit=15)
9 elif filter == 'surprise':
10 data = request.state.db.listingsAndReviews.find({'cleaning_fee':{'$exists': True},'amenities': {'$in': ["Pets allowed", "Patio or balcony", "Self check-in"]}}, limit=15)
11 except KeyError:
12 data = request.state.db.listingsAndReviews.find({'cleaning_fee':{'$exists': True}}, limit=15)
13
14 response = []
15
16 for doc in data:
17 response.append(
18 Property(
19 doc['_id'],
20 doc['name'],
21 doc['summary'],
22 doc['address']['street'],
23 str(doc['price']),
24 str(doc['cleaning_fee']),
25 str(doc['accommodates']),
26 doc['images']['picture_url'],
27 doc['amenities']
28 )
29 )
30
31 return templates.TemplateResponse('index.html', {'request': request, 'response': response})
Nossa página inicial agora suporta vários filtros diferentes. Se um usuário visitar apenas a página inicial, ele verá os resultados originais, mas clicar nos botões do filtro retornará um conjunto diferente de resultados, dependendo do tipo de filtro selecionado. O Pymongo suporta todas as funcionalidades de filtragem do MongoDB na sintaxe familiar. Confira os exemplos acima para ver várias maneiras de escrever filtros.
Página inicial do MongoBnB com filtros
Faça as alterações acima, reinicie seu servidor uvicorn e navegue até localhost:8000 para ver os resultados.

Construindo a página de listagem

Nossa página inicial contém muitas informações sobre várias propriedades. A página do anúncio conterá informações adicionais sobre a propriedade selecionada. Abra o arquivoroutes.pye atualize a definição de listagem da seguinte forma:
1async def listing(request):
2 id = request.path_params['id']
3
4 doc = request.state.db.listingsAndReviews.find_one({'_id': id})
5
6 response = Property(
7 doc['_id'],
8 doc['name'],
9 doc['summary'],
10 doc['address']['street'],
11 str(doc['price']),
12 str(doc['cleaning_fee']),
13 str(doc['accommodates']),
14 doc['images']['picture_url'],
15 doc['amenities']
16 )
17
18 return templates.TemplateResponse('listing.html', {'request': request, 'property': response})
Aqui estamos utilizando o objeto requestpara obter oid da propriedade para a qual desejamos ver detalhes adicionais. A partir daí, executamos um método find_oneque retorna apenas um único documento do nosso MongoDB database. Por fim, pegamos nosso documento e o transformamos em uma nova classe Property e o enviamos ao nosso modelo por meio da variávelproperty.
Abra listing.html e atualize o conteúdo para:
1<html>
2<head>
3 <title>MongoBnB | Property - {{ request.path_params['id'] }}</title>
4 <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
5 <style>
6 img {
7 width: 500px !important;
8 margin: 0 auto;
9 }
10 </style>
11</head>
12<body>
13
14 <div class="container mx-auto">
15 <div class="flex">
16 <div class="row w-full text-center my-4">
17 <h1 class="text-4xl font-bold">MongoBnB</h1>
18 <a href="/">Back</a>
19 </div>
20 </div>
21 <div class="flex flex-row flex-wrap">
22
23 <div class="flex-auto w-1/4 rounded overflow-hidden shadow-lg m-2">
24 <img class="w-full" src="{{ property.image }}">
25 <div class="px-6 py-4">
26 <div class="font-bold text-xl mb-2">{{ property.name }} (Up to {{ property.guests }} guests)</div>
27 <p>{{ property.address }}</p>
28 <p class="text-gray-700 text-base">
29 {{ property.summary }}
30 </p>
31
32 </div>
33 <div class="px-6 py-4">
34 {% for amenity in property.amenities %}
35 <span class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 m-1">{{ amenity }}</span>
36 {% endfor %}
37 </div>
38
39 <div class="text-center py-2 my-2 font-bold">
40 <span class="text-green-500">${{ property.price }}</span>/night (+<span class="text-green-500">${{ property.cleaning_fee }} </span>Cleaning Fee)
41 </div>
42
43 <div class="text-center py-2 my-2">
44 <a href="/confirmation/{{property.id}}" class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">Book</a>
45 </div>
46 </div>
47 </div>
48 </div>
49</body>
50</html>
Salve ambos os arquivos, reinicie seu servidor e navegue até localhost:8000. Clique no botãoDetalhes de qualquer propriedade sobre a qual você deseja ver informações expandidas. A página deve ficar assim:
Página de detalhes da listagem do MongoBnB

Página de confirmação da reserva

Por fim, implementaremos a página de confirmação da reserva. Esta será uma interface de usuário simples, mas, no backend, vamos fazer algo que ainda não fizemos, que é salvar dados em nosso MongoDB database. Abra o arquivoroutes.py e adicione a seguinte implementação para a rota de confirmação:
1async def confirmation(request):
2 id = request.path_params['id']
3
4 doc = request.state.db.bookings.insert({"property": id})
5
6 return templates.TemplateResponse('confirmation.html', {'request': request, 'confirmation': doc})
Como na rota anterior, estamos utilizando parâmetros de rota para capturar o id da reserva. Em seguida, estamos usando request.state.db para acessar nosso banco de MongoDB database, mas agora estamos acessando a coleçãobookings, que não existe. Tudo bem, o MongoDB criará uma coleção de agendamentos para nós no banco de dadossample_airbnbe, como estamos usando a inserção, adicionaremos um documento com um atributo chamado property e o definiremos como o ID do listagem.
Como não estamos criando um nós mesmos, o MongoDB criará automaticamente um atributo_id para nós, e é isso que será retornado e armazenado na variáveldoc, que passaremos para nosso modelo.
Abra confirmation.html e adicione o seguinte código de interface do usuário:
1<html>
2<head>
3 <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
4 <style>
5 </style>
6</head>
7<body>
8
9 <div class="container mx-auto">
10 <div class="flex">
11 <div class="row w-full text-center my-4">
12 <h1 class="text-4xl font-bold">MongoBnB</h1>
13 <a href="/">Back</a>
14 </div>
15 </div>
16 <div class="flex flex-row flex-wrap">
17
18 <div class="flex-auto w-1/4 rounded overflow-hidden shadow-lg m-2">
19 <div class="px-6 py-4 text-center">
20 <h1 class="text-4xl">Confirmed!</h1>
21 <p>Your booking confirmation for {{request.path_params['id']}} is <span class="font-bold">{{confirmation}}</span></span></p>
22 </div>
23 </div>
24 </div>
25 </div>
26</body>
27</html>
Estamos tratando nossa propriedade exclusiva _id como o código de confirmação da reserva. Reinicie o servidor e vá em frente e agende uma propriedade! Você deve ver a seguinte UI:
Confirmação de reserva do MongoBnB

Lidar com as marcações

Nosso aplicativo Starlette está completo. Mostramos aos nossos usuários propriedades nas quais eles possam estar interessados, permitindo que eles se aprofundem e visualizem mais informações e reservem a propriedade perfeita para sua estadia. Mas e se quiséssemos Go a mais e adicionar mais funcionalidades?
O que estou pensando é o seguinte. Depois que um usuário reserva sua estadia, por que não enviamos uma mensagem de texto confirmando sua reserva? Sabendo que nossos visitantes provavelmente estão em movimento, por que não permitimos que eles cancelem sua reserva respondendo à mensagem de texto inicial caso mudem de ideia? No final das contas, nosso objetivo é oferecer uma ótima experiência aos nossos usuários!
Para fazer isso, usaremos a plataforma MongoDB Stitch . O Stitch é uma plataforma sem servidor que se integra ao MongoDB e nos oferece uma variedade de funções, triggers, 3integrações de serviços de terceiros e muito mais. Já que estamos falando de enviar mensagens de texto para nossos usuários, acha que faz sentido usar a integração do Twilio do Stitch.

Configurando o MongoDB Stitch

Para criar um novo aplicativo MongoDB Stitch, entraremos em nosso painel do MongoDB Atlas. Selecione Stitch no menu à esquerda e clique no botão Novo aplicativo. Dê um nome ao seu aplicativo, vincule-o ao seu cluster que tem o banco de dadossample_airbnb e clique em Criar. O MongoDB Atlas levará alguns segundos para configurar seu aplicativo Stitch e redirecionar você para ele.
Aplicativo Stitch do MongoDB
Quando o painel do MongoDB Stitch carregar, selecione 3Serviços de terceiros no menu e, em seguida,Twilio. Aqui, você será solicitado a nomear seu serviço Twilio para Stitch, bem como fornecer o SID de sua conta Twilio. Você precisará de uma conta ativa do Twilio para obter o SID da conta e, se não tiver um,acesse oTwilio para se inscrever e criar sua conta.
Agora que temos nosso serviço Twilio criado, selecione o item de menuFunções . Clique no botãoCriar nova função, nomeie sua função e, para as configurações, você pode deixar todos os padrões, mas navegue até a abaEditor de função e adicione o seguinte código:
1exports = function(arg){
2 const twilio = context.services.get("Starlette"); //The name of your Twilio service
3 const args = {
4 to: "+19999999999", // The phone number you want the SMS to send to
5 from: "+19999999999", // Your Twilio phone number
6 body: `Greeting from MongoBnB!
7 Your reservation is confirmed. If you need to cancel send a message with your booking id: ${arg.fullDocument._id}`
8 };
9 twilio.send(args);
10 return {arg: arg};
11};
Esta função enviará ao usuário uma mensagem de texto SMS quando uma nova reserva for criada. Para este tutorial, enviaremos apenas a mensagem de texto para um número de telefone predeterminado e deixarei para você como lição de casa descobrir como adicionar um número de telefone definido pelo usuário.
Salve a função. Por padrão, esta função nunca será chamada. Precisamos criar um trigger para ativá-lo. Navegue até a seçãoTriggers do dashboard do Stitch. Pressione o botãoAdicionar um trigger e faça as seguintes seleções:
  • Nome - nomeie a função como quiser
  • Nome do cluster - esse será o padrão para o cluster que você selecionou ao criar o aplicativo Stitch
  • Nome do banco de dados - certifique-se de selecionar sample_airbnb
  • Nome da coleção - certifique-se de selecionar bookings
  • Tipo de operação - certifique-se de selecionar apenas Inserir
  • Documento completo - definido como Ativado
  • Function (Função ) - selecione o nome da função que você criou acima
Depois que essas configurações estiverem em vigor, clique no botãoSalvar.
Stitch trigger
Agora nossa função sem servidor deve estar pronta para funcionar. Pressione o botão Review & Deploy Changes (Revisar Implementar alterações) na barra azul superior. Depois que as alterações forem implementadas, volte ao seu aplicativo Starlette emlocalhost:8000.
Selecione uma reserva que lhe agrade e clique no botãoReservar. Imediatamente você verá a página de confirmação que criamos anteriormente, mas, em alguns segundos, você também receberá uma mensagem de texto informando que a reserva foi criada.
Stitch Twilio SMS

Lidando com o recebimento de SMS do Twilio com o MongoDB Stitch

Nossa última funcionalidade no MongoDB Stitch será permitir que o usuário nos envie o ID de confirmação caso queira cancelar a reserva. Para fazer isso, vamos navegar de volta para 3Serviços de terceiros e clicar no serviço Twilio que criamos anteriormente. A partir daqui, clicaremos no botão Adicionar webhookde entrada.
Stitch Webhook
Podemos deixar todas as configurações padrão como estão, mas o que queremos anotar nesta página é o URL do webhook. Copie e salve, pois precisaremos dele em apenas alguns minutos. Navegue até a abaEditor de funções e adicione o seguinte código:
1exports = function(payload) {
2 const mongodb = context.services.get("main"); // The name of your MongoDB cluster
3 const bookings = mongodb.db("sample_airbnb").collection("bookings");
4
5 bookings.deleteOne({_id: new BSON.ObjectId(payload.Body)})
6
7 const twilio = context.services.get("Starlette"); // The name of your Twilio service
8 const args = {
9 to: "+19999999999", // The number to send the SMS message to
10 from: "+19999999999", // Your Twilio number
11 body: `Reservation ${payload.Body} has been cancelled. See you next time!`
12 };
13 twilio.send(args);
14 return payload.Body
15};
Essa função assumirá o corpo da mensagem SMS, que, para todos os efeitos, assumiremos ser apenas a reserva _ide, se for, entraremos em nossa collectionbookings e excluiremos esse registro. Depois disso, responderemos ao usuário informando que sua reserva foi cancelada.
Configuração do Webhook da Twilio
No entanto, esta função não disparará automaticamente. Para que funcione, precisaremos informar a Twilio sobre nossa função. Faça login no painel do Twilio e navegue até o serviçoNúmeros de telefone. Selecione o número de telefone que deseja usar e role a parte inferior da página para encontrar as configurações deMensagens . Na configuração A ChangesIn, no menu suspenso selecione Webhook e, para o valor, cole a URL do MongoDB Stitch Webhook que salvamos anteriormente. É isso. Agora tudo deve funcionar!
Cancelamento de reserva do MongoBnB

Juntando tudo

No tutorial de hoje, aprenderam sobre o Starlette, um framework ASGI para construir aplicativos Python de alto desempenho. Conectamos nosso aplicativo Starlette a um MongoDB database hospedado pelo MongoDB Atlas. Por fim, aprimoramos nosso aplicativo usando o MongoDB Stitch, uma plataforma sem servidor feita para o MongoDB, adicionando a funcionalidade Twilio SMS. espero que você tenha achado este tutorial útil. Se quiser clonar o código concluído, você pode obtê-lo no Github. Não deixe de se inscrever no MongoDB Atlas, pois ele lhe dará acesso ao conjunto de dados para o tutorial. Boa codificação!

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Artigo

3 Funcionalidades do MongoDB subutilizadas


Sep 11, 2024 | 6 min read
Artigo

Capturando e armazenando óptica do mundo real com o MongoDB Atlas, o GPT-4 da OpenAI e o PyMongo


Sep 04, 2024 | 7 min read
Tutorial

Aprimoramento da precisão do LLM usando o Atlas Vector Search do MongoDB e os metadados Unstructured.io


Dec 04, 2023 | 12 min read
Tutorial

Como criar um sistema RAG avançado com recuperação autoquery


Sep 12, 2024 | 21 min read
Sumário