はじめに
こんにちは。今回は、FlaskとSQLAlchemyを使用して開発中の「DailyBeat」というWebアプリケーションについて、コードの詳細な解説を交えながら紹介します。このアプリは、ユーザーが毎日1曲を共有し、音楽を通じて他のユーザーとつながることができる音楽特化型のSNSプラットフォームです。
アプリケーションの概要
「DailyBeat」は以下の主要機能を持っています:
- ユーザー登録・ログイン
- 毎日の楽曲投稿
- タイムライン表示
- ユーザーフォロー機能
- 楽曲再生機能(部分的に実装)
それでは、各機能の実装について詳しく見ていきましょう。
1. ユーザー登録とログイン
ユーザー登録とログイン機能は、Flask-Loginを使用して実装しています。
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
if User.query.filter_by(username=username).first():
flash('Username already exists')
else:
new_user = User(username=username,
password=generate_password_hash(password))
db.session.add(new_user)
db.session.commit()
flash('Registration successful')
return redirect(url_for('login'))
return render_template('register.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
user = User.query.filter_by(username=username).first()
if user and check_password_hash(user.password, password):
login_user(user)
return redirect(url_for('mypage'))
flash('Invalid username or password')
return render_template('login.html')
コード解説
-
register
関数:- POSTリクエストの場合、フォームからユーザー名とパスワードを取得します。
- ユーザー名の重複をチェックし、新規の場合はパスワードをハッシュ化して保存します。
-
db.session.add(new_user)
で新しいユーザーをセッションに追加し、db.session.commit()
でデータベースに反映します。
-
login
関数:- POSTリクエストの場合、ユーザー名とパスワードを検証します。
-
check_password_hash
関数でパスワードを照合し、正しい場合はlogin_user
関数でユーザーをログイン状態にします。
2. 毎日の楽曲投稿
ユーザーが毎日1曲を投稿できる機能を実装しています。
@app.route('/post_daily_song', methods=['GET', 'POST'])
@login_required
def post_daily_song():
form = DailySongForm()
if form.validate_on_submit():
today = date.today()
DailySong.query.filter_by(
user_id=current_user.id, date_posted=today, is_current=True).update({'is_current': False})
new_song = DailySong(
user_id=current_user.id,
title=form.title.data,
artist=form.artist.data,
genre=form.genre.data,
music_url=form.music_url.data,
is_current=True
)
db.session.add(new_song)
db.session.commit()
flash('今日の1曲を投稿しました!', 'success')
return redirect(url_for('mypage'))
return render_template('post_daily_song.html', form=form)
コード解説
-
@login_required
デコレータにより、ログインユーザーのみがアクセスできるようになっています。 -
form.validate_on_submit()
でフォームのバリデーションを行います。 - 既存の今日の投稿がある場合、
is_current
フラグをFalseに更新します。 - 新しい
DailySong
オブジェクトを作成し、データベースに追加します。 -
flash
関数で成功メッセージを設定し、マイページにリダイレクトします。
3. タイムライン表示
ユーザーの投稿を時系列順に表示するタイムライン機能を実装しています。
@app.route('/all_posts')
def all_posts():
sort_order = request.args.get('sort', 'desc')
if sort_order == 'asc':
posts = DailySong.query.order_by(DailySong.date_posted.asc()).all()
else:
posts = DailySong.query.order_by(DailySong.date_posted.desc()).all()
followed_posts = []
if current_user.is_authenticated:
followed_users = [user.id for user in current_user.followed]
if sort_order == 'asc':
followed_posts = DailySong.query.filter(DailySong.user_id.in_(
followed_users)).order_by(DailySong.date_posted.asc()).all()
else:
followed_posts = DailySong.query.filter(DailySong.user_id.in_(
followed_users)).order_by(DailySong.date_posted.desc()).all()
return render_template('all_posts.html', posts=posts, followed_posts=followed_posts, current_sort=sort_order)
コード解説
-
request.args.get('sort', 'desc')
でURLパラメータから並び順を取得します。デフォルトは降順です。 -
DailySong.query.order_by()
で投稿を日付順にソートします。 - ログインユーザーの場合、フォローしているユーザーの投稿も取得します。
-
DailySong.user_id.in_(followed_users)
で、フォローしているユーザーの投稿をフィルタリングします。
4. ユーザーフォロー機能
ユーザー同士のつながりを強化するためのフォロー機能を実装しています。
@app.route('/follow/<username>')
@login_required
def follow(username):
user = User.query.filter_by(username=username).first()
if user is None:
flash('ユーザーが見つかりません。')
return redirect(url_for('index'))
if user == current_user:
flash('自分自身をフォローすることはできません。')
return redirect(url_for('user', username=username))
current_user.follow(user)
db.session.commit()
flash(f'{username} をフォローしました。')
return redirect(url_for('user', username=username))
@app.route('/unfollow/<username>')
@login_required
def unfollow(username):
user = User.query.filter_by(username=username).first()
if user is None:
flash('ユーザーが見つかりません。')
return redirect(url_for('index'))
if user == current_user:
flash('自分自身をアンフォローすることはできません。')
return redirect(url_for('user', username=username))
current_user.unfollow(user)
db.session.commit()
flash(f'{username} のフォローを解除しました。')
return redirect(url_for('user', username=username))
コード解説
-
@login_required
デコレータで、ログインユーザーのみがアクセスできるようにしています。 -
User.query.filter_by(username=username).first()
で対象ユーザーを取得します。 - 自分自身をフォロー/アンフォローしようとした場合はエラーメッセージを表示します。
-
current_user.follow(user)
とcurrent_user.unfollow(user)
メソッドで、フォロー関係を更新します。 - 変更をデータベースに反映するために
db.session.commit()
を呼び出しています。
5. 楽曲再生機能(部分的に実装)
現在、楽曲再生機能は部分的に実装されています。Spotify APIを使用してアルバムアートを取得する機能が実装されていますが、実際の楽曲再生機能は未実装です。
def get_album_art(artist, title):
client_id = 'your_spotify_client_id'
client_secret = 'your_spotify_client_secret'
auth_response = requests.post('https://accounts.spotify.com/api/token', {
'grant_type': 'client_credentials',
'client_id': client_id,
'client_secret': client_secret,
})
auth_response_data = auth_response.json()
access_token = auth_response_data['access_token']
headers = {
'Authorization': f'Bearer {access_token}'
}
params = {
'q': f'artist:{artist} track:{title}',
'type': 'track',
'limit': 1
}
response = requests.get(
'https://api.spotify.com/v1/search', headers=headers, params=params)
response_data = response.json()
if 'tracks' in response_data and response_data['tracks']['items']:
return response_data['tracks']['items'][0]['album']['images'][0]['url']
else:
return None
@app.route('/get_album_art/<artist>/<title>')
def get_album_art_api(artist, title):
album_art_url = get_album_art(artist, title)
return jsonify({'album_art_url': album_art_url})
コード解説
-
get_album_art
関数:- Spotify APIの認証トークンを取得します。
- 楽曲の検索クエリを作成し、APIにリクエストを送信します。
- レスポンスから、アルバムアートのURLを抽出して返します。
-
get_album_art_api
関数:- URLパラメータからアーティスト名と曲名を受け取ります。
-
get_album_art
関数を呼び出してアルバムアートのURLを取得します。 - 結果をJSONで返します。
今後の展望
DailyBeatの開発は現在進行中であり、以下の機能の実装や改善を計画しています:
- 楽曲再生機能の完全実装
- ユーザープロフィールページの充実
- 楽曲推薦システムの導入
- モバイルアプリ版の開発
- ソーシャルシェア機能の強化
これらの機能を追加することで、ユーザーエクスペリエンスをさらに向上させ、より魅力的な音楽共有プラットフォームを目指しています。
まとめ
「DailyBeat」は、FlaskとSQLAlchemyを使用して構築された音楽共有SNSです。現在のバージョンでは、ユーザー登録、ログイン、楽曲投稿、タイムライン表示、フォロー機能が実装されており、部分的な楽曲情報取得機能も含まれています。
このプロジェクトでは、以下のような技術的なポイントが特徴的です:
- Flask-Loginを使用した安全なユーザー認証
- SQLAlchemyを活用した効率的なデータベース操作
- フォーム処理とバリデーション(WTFormsを使用)
- 外部API(Spotify)との連携
今後は、楽曲再生機能の完全実装や新機能の追加を通じて、ユーザーにとってより魅力的なプラットフォームを目指して開発を続けていきます。
このプロジェクトは、Pythonの強力な機能やFlaskのシンプルさを活かしつつ、SQLAlchemyを使用した効率的なデータベース操作を実現しています。特に、日々の楽曲投稿やフォロー機能の実装は、実際のSNSの基本的な機能を網羅しており、学習教材としても有用です。
皆さんも、自分のプロジェクトでFlaskとSQLAlchemyを使ってこのような機能豊富なWebアプリケーションを構築する際の参考にしていただければ幸いです。