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 .

Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Produtoschevron-right
MongoDBchevron-right

Construa uma plataforma de boletim de notícias com Flask e MongoDB

Mercy Bassey11 min read • Published Jun 27, 2024 • Updated Sep 04, 2024
MongoDBPython
APLICATIVO COMPLETO
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Uma newsletter é uma ferramenta poderosa para manter uma comunicação regular com seu público. Ele conecta você com seus assinantes, permitindo que você compartilhe atualizações, notícias e outros conteúdos valiosos diretamente em suas caixas de entrada. Neste artigo, você aprenderá como criar uma plataforma de newsletter dinâmica e interativa onde os assinantes podem assinar facilmente sua newsletter e você, como administrador, pode gerenciar e enviar e-mails em lote com eficiência para todos os usuários inscritos. Ao final deste guia, você terá uma plataforma de boletim informativo totalmente funcional que utiliza o JavaScript para interatividade, o Flask no lado do servidor e o MongoDB para armazenamento eficiente de dados.

Pré-requisitos

Para acompanhar este artigo, você deve atender aos seguintes requisitos:
  • MongoDB instalado em sua máquina — seja Linux, Mac OSou Windows
  • Mongosh para interagir com sua instância do MongoDB — veja as instruções de instalação
  • RabbitMQ instalado em sua máquina para intermediação de mensagens — veja as instruções de instalação para Debian e Ubuntu, depois Windows e macOS usando Homebrew
  • Gmail como servidor SMTP para enviar e-mails — nesse caso, gere uma senha de aplicativo para autenticar seu aplicativo com segurança sem usar a senha primária da sua conta do Gmail
Os comandos usados neste tutorial são demonstrados em uma máquina Linux com um Ubuntu 22.04Distribuição LTS. O código usado neste tutorial pode ser encontrado no repositório GitHub.

Configuração do ambiente

Para começar, você deve garantir que o MongoDB, Mongosh e seu servidor RubyMQ estejam em execução. Para atingir isso, execute os seguintes comandos sequencialmente:
1sudo systemctl status mongod
2sudo systemctl status rabbitmq-server
3mongosh
Se você tiver a seguinte saída, você está configurado:
1● mongod.service - MongoDB Database Server
2 Loaded: loaded (/lib/systemd/system/mongod.service; enabled; vendor preset: enabled)
3 Active: active (running) since Tue 2024-06-04 16:47:23 WAT; 13h ago
4 Docs: https://docs.mongodb.org/manual
5 Main PID: 1305 (mongod)
6 Memory: 259.0M
7 CPU: 2min 8.508s
8 CGroup: /system.slice/mongod.service
9 └─1305 /usr/bin/mongod --config /etc/mongod.conf
10
11Jun 04 16:47:23 mercy systemd[1]: Started MongoDB Database Server.
12Jun 04 16:47:24 mercy mongod[1305]: {"t":{"$date":"2024-06-04T15:47:24.620Z"},"s":"I", "c":"CONTROL", "id":7484500, "ctx":"main","msg":"Environment variabl>
13
14● rabbitmq-server.service - RabbitMQ Messaging Server
15 Loaded: loaded (/lib/systemd/system/rabbitmq-server.service; enabled; vendor preset: enabled)
16 Active: active (running) since Tue 2024-06-04 16:47:28 WAT; 13h ago
17 Main PID: 781 (beam.smp)
18 Tasks: 27 (limit: 9003)
19 Memory: 125.1M
20 CPU: 1min 55.438s
21 CGroup: /system.slice/rabbitmq-server.service
22 ├─ 781 /usr/lib/erlang/erts-12.2.1/bin/beam.smp -W w -MBas ageffcbf -MHas ageffcbf -MBlmbcs 512 -MHlmbcs 512 -MMmcs 30 -P 1048576 -t 5000000 -st>
23 ├─ 866 erl_child_setup 65536
24 ├─1204 inet_gethost 4
25 └─1205 inet_gethost 4
26
27Jun 04 16:47:19 mercy systemd[1]: Starting RabbitMQ Messaging Server...
28Jun 04 16:47:28 mercy systemd[1]: Started RabbitMQ Messaging Server.
29
30Current Mongosh Log ID: 665ff402cc42191d77a26a12
31Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.2.6
32Using MongoDB: 7.0.11
33Using Mongosh: 2.2.6
34
35For mongosh info see: https://docs.mongodb.com/mongodb-shell/
36
37------
38 The server generated these startup warnings when booting
39 2024-06-04T16:47:24.825+01:00: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See http://dochub.mongodb.org/core/prodnotes-filesystem
40 2024-06-04T16:47:26.247+01:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
41 2024-06-04T16:47:26.247+01:00: vm.max_map_count is too low
42------
43
44test>
Em seguida, crie um diretório de trabalho e um ambiente virtual e, depois, ative o ambiente virtual usando os seguintes comandos:
1mkdir newsletter
2cd newsletter
3code .
4python3 -m venv .venv
5. .venv/bin/activate # For Mac/Linux OS
6.venv\Scripts\activate # For Windows OS
Com o ambiente virtual ativado, agora você está pronto para instalar as bibliotecas necessárias para desenvolver sua plataforma de boletins informativos. Para continuar, você precisará instalar as seguintes bibliotecas:
  • Flask para lidar com o servidor web e roteamento
  • Flask Mail para enviar e-mails a partir do seu aplicativo
  • PyMongo para interface com o MongoDB, que você pode usar para gerenciar dados de assinantes e armazenamento persistente de conteúdo de boletins informativos
  • Celery para gerenciar tarefas assíncronas, como envio de e-mails em lote
Usando o seguinte comando, você os instalará em seu ambiente virtual:
1pip install Flask Flask-Mail pymongo celery
Finalmente, em seu diretório de trabalho, crie dois diretórios chamados static e templates. Eles servirão como locais para arquivos estáticos, como modelos CSS e HTML, essenciais para renderizar a parte frontend do seu aplicativo da web. Após isso, crie os seguintes arquivos:
  • app.py: Isso servirá como o principal ponto de entrada para seu aplicativo Flask, onde você inicializa seu aplicativo e une os outros componentes.
  • config.py: Esse arquivo conterá todas as configurações do seu aplicativo, como detalhes da conexão do MongoDB, configuração do servidor de e-mail e conexão do Celery Broker, além de outras variáveis específicas do ambiente.
  • routes.py: Aqui você definirá as rotas (URL) que sua aplicação responderá. Ele incluirá funções para lidar com solicitações e respostas, conectando URLs a funções Python.
  • tasks.py: Esse arquivo será usado para definir tarefas em segundo plano que podem ser processadas de forma assíncrona, ou seja, neste caso, para enviar e-mails.

Criando o modelo

Com seu ambiente configurado, a próxima coisa a fazer é desenvolver a aparência da plataforma de boletim informativo. No diretório de modelos, crie dois arquivos HTML - admin.html e subscrbe.html. Emadmin.html, adicione a seguinte marcação HTML:
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Admin - Send Newsletter</title>
7 <link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
8</head>
9<body>
10 <h1>Send Newsletter</h1>
11 <form id="admin-form">
12 <label for="title">Title:</label>
13 <input type="text" id="title" name="title" required>
14 <br>
15 <label for="body">Body:</label>
16 <textarea id="body" name="body" required></textarea>
17 <br>
18 <button type="submit">Send</button>
19 </form>
20 <div id="response"></div>
21</body>
22</html>
E então adicione o seguinte código no subscribe.html arquivo :
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Subscribe to Newsletter</title>
7 <link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
8</head>
9<body>
10 <h1>Subscribe to our Newsletter</h1>
11 <form id="subscribe-form">
12 <label for="firstname">First Name:</label>
13 <input type="text" id="firstname" name="firstname" required>
14 <br>
15 <label for="lastname">Last Name:</label>
16 <input type="text" id="lastname" name="lastname" required>
17 <br>
18 <label for="email">Email:</label>
19 <input type="email" id="email" name="email" required>
20 <br>
21 <button type="submit">Subscribe</button>
22 </form>
23 <div id="response"></div>
24
25 <footer>
26 Made with ❤️ &copy; 2024 Mercy
27 </footer>
28</body>
29</html>
Nos modelosadmin.html e subscribe.html, adicione os seguintes scripts, respectivamente, na tag body:
1<script>
2 document.getElementById('admin-form').addEventListener('submit', function(event) {
3 event.preventDefault();
4 var formData = new FormData(event.target);
5 fetch('/send-newsletters', {
6 method: 'POST',
7 body: formData
8 })
9 .then(response => response.json())
10 .then(() => {
11 document.getElementById('response').innerText = 'Emails are being sent!';
12 setTimeout(() => {
13 document.getElementById('response').innerText = '';
14 }, 3000);
15 document.getElementById('admin-form').reset();
16 })
17 .catch(error => {
18 document.getElementById('response').innerText = 'Error sending emails.';
19 setTimeout(() => {
20 document.getElementById('response').innerText = '';
21 }, 3000);
22 console.error('Error:', error);
23 });
24 });
25 </script>
1<script>
2 document.getElementById('subscribe-form').addEventListener('submit', function(event) {
3 event.preventDefault();
4 var formData = new FormData(event.target);
5 fetch('/subscribe', {
6 method: 'POST',
7 body: formData
8 }).then(response => {
9 if (!response.ok) {
10 throw response;
11 }
12 return response.text();
13 }).then(data => {
14 document.getElementById('response').innerHTML = data;
15 document.getElementById('subscribe-form').reset();
16 setTimeout(() => {
17 document.getElementById('response').innerHTML = '';
18 }, 3000);
19 }).catch(error => {
20 error.text().then(errorMessage => {
21 document.getElementById('response').innerHTML = errorMessage;
22 setTimeout(() => {
23 document.getElementById('response').innerHTML = '';
24 }, 3000);
25 });
26 });
27 });
28 </script>
Para o modeloadmin.html, o bloco de script garante que o envio do formulário para o envio de boletins informativos seja tratado de forma assíncrona. Quando o formulário de administração é enviado, o JavaScript intercepta esse evento para evitar o recarregamento da página. Em seguida, ele envia os dados do formulário para o servidor usando a API Fetch. Em caso de sucesso, ele exibe uma mensagem informando que os e-mails estão sendo enviados, e essa mensagem é apagada após alguns segundos. Em caso de erro durante o envio do formulário, ele captura o erro e exibe uma mensagem apropriada para o administrador.
Para o modelosubscribe.html, o bloco de script garante que o processo de assinatura seja tratado de forma semelhante e assíncrona. Quando um usuário envia os detalhes da assinatura, o script impede o envio do formulário padrão para o servidor e, em vez disso, envia os dados usando Fetch. A resposta do servidor é então exibida diretamente no HTML. Se a resposta indicar sucesso, será exibida uma mensagem de confirmação e, se houver um erro (como o fato de o servidor responder que o e-mail já existe no banco de dados), será exibida a mensagem de erro.
Por fim, crie um arquivostyles.cssem sua pasta estática e adicione os seguintes estilos:
1@import url('https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap');
2
3body {
4 font-family: "Nunito", sans-serif;
5 font-optical-sizing: auto;
6 font-weight: 300;
7 font-style: normal;
8 margin: 0;
9 padding: 0;
10 display: flex;
11 flex-direction: column;
12 align-items: center;
13 justify-content: center;
14 height: 100vh;
15 background-color: #040100;
16}
17
18h1 {
19 color: white;
20}
21
22form {
23 background: #DB4918;
24 padding: 30px 40px;
25 border-radius: 8px;
26 box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
27 width: 100%;
28 max-width: 400px;
29 margin: 20px 0;
30}
31
32label {
33 display: block;
34 margin-bottom: 8px;
35 font-weight: bold;
36 color: white;
37}
38
39input[type="text"],
40input[type="email"],
41textarea {
42 width: 100%;
43 padding: 10px;
44 margin-bottom: 10px;
45 border: 1px solid #ccc;
46 border-radius: 4px;
47 font-size: 16px;
48}
49
50button {
51 background: #DB8218;
52 color: white;
53 padding: 10px 20px;
54 border: none;
55 border-radius: 4px;
56 cursor: pointer;
57 font-size: 16px;
58 font-family: "Nunito", sans-serif;
59}
60
61button:hover {
62 background: #DB6B18;
63}
64
65#response {
66 margin-top: 20px;
67 font-size: 16px;
68 color: #28a745;
69}
70
71footer {
72 text-align: center;
73 padding: 20px;
74 margin-top: 20px;
75 font-size: 16px;
76 color: #666;
77}

Criação de rotas e tarefas

Com o modelo configurado, agora você está pronto para definir as rotas específicas e as tarefas em segundo plano que impulsionarão a funcionalidade de sua plataforma de newsletter. Isso envolve o mapeamento de URLs para funções Python no seu aplicativo Flask, que tratará de envios de formulários, interações de usuários e quaisquer outros processos necessários. Além disso, você configurará tarefas do Celery para lidar com operações assíncronas, como o envio de e-mails em lotes.
Para começar, adicione o seguinte em seu config.py:
1import os
2
3class Config:
4 CELERY_BROKER_URL = 'amqp://guest:guest@localhost//'
5 RESULT_BACKEND = 'mongodb://localhost:27017/celery_results'
6 MAIL_SERVER = 'smtp.gmail.com'
7 MAIL_PORT = 587
8 MAIL_USE_TLS = True
9 MAIL_USERNAME = '<username>' # Your email address without the '@gmail.com'
10 MAIL_PASSWORD = '<app password>'
11 MAIL_DEFAULT_SENDER = '<email address>'
12 ALLOWED_IPS = ['127.0.0.1']
13 MONGO_URI = 'mongodb://localhost:27017/newsletter'
Aqui você está definindo a configuração para seu aplicativo Flask. Essa configuração inclui as configurações para que o Celery se conecte ao seu agente de mensagens (RabbitMQ neste caso, indicado pela URL do AMQP) e MongoDB para o back-end de resultados. Você também está configurando o Flask-Mail com o Gmail como o servidor SMTP para lidar com e-mails enviados, o que requer os detalhes do servidor de e-mail, a porta e as preferências de conexão segura, juntamente com suas credenciais do Gmail. O MAIL_DEFAULT_SENDER é usado como o endereço de e-mail do remetente padrão para seus e-mails enviados. Além disso, ALLOWED_IPS é especificado para uma camada extra de segurança, limitando o acesso a determinadas funcionalidades com base no IP do solicitante. Por fim, o MONGO_URI define a string de conexão para o MongoDB database, onde as informações do assinante e outros dados relevantes para o sistema de newsletter serão armazenados.
Em seguida, no seu routes.py arquivo, adicione os seguintes trechos de código:
1from flask import render_template, request, abort, jsonify
2from app import app, db
3from tasks import send_emails
4
5@app.before_request
6def limit_remote_addr():
7 if 'X-Forwarded-For' in request.headers:
8 remote_addr = request.headers['X-Forwarded-For'].split(',')[0]
9 else:
10 remote_addr = request.remote_addr
11
12 if request.endpoint == 'admin' and remote_addr not in app.config['ALLOWED_IPS']:
13 abort(403)
14
15@app.route('/')
16def home():
17 return render_template('subscribe.html')
18
19@app.route('/admin')
20def admin():
21 return render_template('admin.html')
22
23@app.route('/subscribe', methods=['POST'])
24def subscribe():
25 first_name = request.form['firstname']
26 last_name = request.form['lastname']
27 email = request.form['email']
28
29 if db.users.find_one({'email': email}):
30 return """
31 <div class="response error">
32 <span class="icon">&#x2716;</span> This email is already subscribed!
33 </div>
34 """, 409
35
36 db.users.insert_one({'firstname': first_name, 'lastname': last_name, 'email': email, 'subscribed': True})
37 return """
38 <div class="response success">
39 <span class="icon">&#x2714;</span> Subscribed successfully!
40 </div>
41 """, 200
42
43@app.route('/send-newsletters', methods=['POST'])
44def send_newsletters():
45 title = request.form['title']
46 body = request.form['body']
47 subscribers = list(db.users.find({'subscribed': True}))
48
49 for subscriber in subscribers:
50 subscriber['_id'] = str(subscriber['_id'])
51
52 send_emails.apply_async(args=[subscribers, title, body])
53 return jsonify({'message': 'Emails are being sent!'}), 202
O trecho de código acima estabelece as rotas e as funcionalidades essenciais para sua plataforma de boletim informativo. A função limit_remote_addrrestringe o acesso à interface de administração com base no IP para aumentar a segurança. O endpoint /subscribelida com as assinaturas dos usuários verificando se há entradas duplicadas antes de salvar os dados dos novos assinantes no MongoDB. A rota/send-newsletters aciona o envio assíncrono de e-mails para os assinantes usando o Celery, permitindo operações sem bloqueio e feedback imediato para o usuário de que os e-mails estão sendo enviados.
No seu tasks.py, adicione os seguintes trechos de código:
1from flask_mail import Message
2from app import app, mail, db, celery
3from datetime import datetime
4
5@celery.task(bind=True)
6def send_emails(self, subscribers, title, body):
7 with app.app_context():
8 for subscriber in subscribers:
9 try:
10 print(f"Sending email to {subscriber['email']}")
11 msg = Message(title, recipients=[subscriber['email']])
12 msg.body = body
13 mail.send(msg)
14 db.deliveries.insert_one({
15 'email': subscriber['email'],
16 'title': title,
17 'body': body,
18 'delivered_at': datetime.utcnow()
19 })
20 print("Email sent")
21
22 except Exception as e:
23 print(f"Failed to send email to {subscriber['email']}: {str(e)}")
24
25 return {'result': 'All emails sent'}
Isso configurará uma tarefa do Celery que trata do envio de e-mails de forma assíncrona. Quando a send_emails tarefa é chamada, ela percorre cada assinante, compondo e enviando um e-mail usando Flask-Mail. Para cada e-mail enviado com sucesso, os detalhes são registrados na collection do MongoDB deliveries com o e-mail do destinatário, o título do e-mail, o corpo e o carimbo de data/hora de quando foi enviado. Se ocorrer um erro durante o processo de envio de e-mail, ele será capturado e registrado, o que garante que o Celery lide com as falhas e mantenha um registro de todas as tentativas de transmissão de e-mail.
Por fim, em seu app.py, adicione os seguintes trechos de código:
1from flask import Flask
2from flask_mail import Mail
3from pymongo import MongoClient
4from celery import Celery
5
6app = Flask(__name__)
7app.config.from_object('config.Config')
8
9mail = Mail(app)
10client = MongoClient(app.config['MONGO_URI'])
11db = client.get_database()
12
13celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
14celery.conf.update(app.config)
15
16from routes import *
17from tasks import *
18
19if __name__ == '__main__':
20 app.run(debug=True)
Isso inicializará seu aplicativo Flask usando configurações carregadas do seu arquivo de configuração. Ele configura o Flusk-Mail para a funcionalidade de e-mail, conecta-se ao MongoDB usando o PyMongo e configura o Celory com o operador especificado no arquivo de configuração. Em seguida, as rotas e tarefas são importadas para integrar definições de endpoints e funções de tarefas em segundo plano no aplicativo. Além disso, ele executa o aplicativo no modo de depuração para permitir a depuração e o desenvolvimento em tempo real, facilitando o rastreamento de problemas à medida que eles surgem.

Testando o aplicativo

Está tudo configurado para a sua plataforma de newsletter. Agora é hora de ver como funciona. Para iniciar o aplicativo Flask, navegue até o diretório do projeto no terminal e execute o seguinte comando:
1flask --app app run
Em outra janela de terminal, execute o seguinte comando para iniciar o celery worker:
1celery -A app.celery worker --loglevel=info
Para acessar sua plataforma de boletim informativo, navegue até localhost:5000 no seu navegador. Você verá a página de destino inicial, conforme representado abaixo:
Visualizando a página inicial do boletim informativo
Para funções administrativas, visite a página de administração no localhost:5000/admin. A página deve ficar assim:
Visualizando a página de administração do boletim informativo
Para testar seu aplicativo, inscreva-se na página inicial. Você pode adicionar quantos assinantes quiser. Após a assinatura bem-sucedida, você verá uma confirmação semelhante a esta:
Adicionando um assinante
O formulário será apagado e uma mensagem de sucesso será exibida.
Para verificar os dados da assinatura, use os seguintes comandos do MongoDB em seu terminal:
1mongosh
2show dbs
3use newsletter
4show collections
Você verá que um banco de dados chamado newsletter foi criado junto com uma coleção deassinantes que contém as entradas de assinatura:
1Current Mongosh Log ID: 666151bb5bb9f923c2a26a12
2Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.2.6
3Using MongoDB: 7.0.11
4Using Mongosh: 2.2.6
5
6For mongosh info see: https://docs.mongodb.com/mongodb-shell/
7
8------
9 The server generated these startup warnings when booting
10 2024-06-06T06:44:55.413+01:00: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See http://dochub.mongodb.org/core/prodnotes-filesystem
11 2024-06-06T06:44:56.369+01:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
12 2024-06-06T06:44:56.369+01:00: vm.max_map_count is too low
13------
14
15test> show dbs
16admin 40.00 KiB
17config 60.00 KiB
18local 72.00 KiB
19newsletter 40.00 KiB
20test> use newsletter
21switched to db newsletter
22newsletter> show collections
23subscribers
24newsletter> db.subscribers.find().pretty()
25[
26 {
27 _id: ObjectId('66614cf25c0255f4a797fe97'),
28 firstname: 'Mercy',
29 lastname: 'Udoh',
30 email: 'mercybassey683@gmail.com',
31 subscribed: true
32 }
33 ...
34]
35newsletter>
Em seguida, para enviar e-mails em lote, acesse sua página de administração em localhost:5000/admin e envie um boletim informativo. O backend do Celery deve registrar o seguinte após o envio bem-sucedido do e-mail:
1[2024-06-06 13:34:37,304: WARNING/ForkPoolWorker-4] Email sent
2[2024-06-06 13:34:37,305: INFO/ForkPoolWorker-4] Task tasks.send_emails[b119bb9e-b2ef-4c85-b048-ca96e0e60ae1] succeeded in 17.155154566993588s: {'result': 'All emails sent'}
Confirme a criação da collection deliveriesjunto comsubscribers no seu MongoDB database:
1newsletter> show collections
2deliveries
3subscribers
4newsletter>
Para revisar o conteúdo da coleçãodeliveries e verificar os detalhes dos e-mails enviados, use o seguinte comando em seu shell do MongoDB:
1db.deliveries.find().pretty()
Esse comando exibirá os registros na collectionentregas de maneira formatada, permitindo que você analise facilmente cada entrada. Você deverá ver dados semelhantes ao seguinte resultado, que inclui detalhes como endereço de e-mail, título do boletim informativo, conteúdo do corpo e o registro de data e hora de quando cada e-mail foi enviado.
1newsletter> db.deliveries.find().pretty()
2[
3 {
4 _id: ObjectId('6661acdd5d0b93accd9fba1e'),
5 email: 'mercybassey683@gmail.com',
6 title: 'Green Thumbs Monthly: June Garden Tips & Upcoming Events',
7 body: 'Dear Green Thumbs Members,\r\n' +
8 '\r\n' +
9 "Welcome to your June edition of the Green Thumbs Monthly! As the days grow longer and the soil warms, it’s the perfect time to dive deep into the joys of summer gardening. Here's what's inside this issue:\r\n" +
10 '\r\n' +
11 '1. Member Spotlight:\r\n' +
12 'This month, we’re featuring Jane Doe, who has transformed her backyard into a vibrant oasis of native plants and vegetables. ',
13 delivered_at: ISODate('2024-06-06T12:34:37.237Z')
14 }
15]
16newsletter>
Isso garante que você possa acompanhar o sucesso e o conteúdo de cada envio dentro do seu sistema de boletins informativos.

Conclusão

E aqui está! Você criou uma plataforma de boletim informativo poderosa e interativa. Esse projeto não só permitiu que você aprofundasse sua compreensão de Python, JavaScript, Flask e MongoDB, mas também deu uma ideia de como essas tecnologias se entrelaçam para criar um aplicativo web funcional.
Ao admirar sua criação, lembre-se de que isso é apenas o começo. Você pode continuar aprimorando essa plataforma com mais recursos, como respostas automatizadas, integração analítica para acompanhar o envolvimento do assinante e modelos de e-mail personalizáveis. A vantagem de criar é que ela nunca está realmente terminada. Sempre há algo mais a adicionar, melhorar e renovar. Então, continue explorando, continue aprendendo e, o mais importante, continue criando.
Quer continuar a conversa? Se você tiver dúvidas ou quiser se conectar com outras pessoas que estão construindo coisas legais com o MongoDB, acesse nossa Comunidade de desenvolvedores a seguir.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.
Iniciar a conversa

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

Arrays massivas


Oct 01, 2024 | 4 min read
Tutorial

Planejador de partes favoritas do operador Joe com Playwright, LlamaIndex e MongoDB Atlas Vector Search


Nov 12, 2024 | 11 min read
Tutorial

Zap, tweet e repita! Como usar o Zapier com o MongoDB


Sep 09, 2024 | 7 min read
Artigo

Capture dados de IoT com o MongoDB em 5 minutos


Sep 09, 2024 | 2 min read
Sumário