質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
cURL

cURLはHTTP, FTPやTelnetなど複数のプロトコルを用いてデータを転送するライブラリとコマンドラインツールを提供します。

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

1回答

1787閲覧

Django Restful API curlコマンドによる既存外部DBのUPDATEをしたい。

dendenmushi

総合スコア98

cURL

cURLはHTTP, FTPやTelnetなど複数のプロトコルを用いてデータを転送するライブラリとコマンドラインツールを提供します。

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

1グッド

0クリップ

投稿2021/06/07 20:00

前提・実現したいこと

Django Restful API curlコマンドによる既存外部DBのUPDATEをしたいと考えております。
イメージとしては以下です。

ユーザースマートフォン→curl→APIサーバ→別サーバDB

curl ~コマンドをユーザーのスマートフォンなりPCなりで実行(ajaxなど)をし、別途立てているAPIサーバーに通信が行われ、さらに別途立てている既存のDBのテーブルを更新するというものです。

シンプルに以下既存外部DBのテーブルイメージです。

ユーザーIDとBlog記事の格納

ユーザーIDblog記事内容
1きのう、公園へ花を摘みにでかけました。
2これからTDLにでかけます。
3近所の野良猫がお腹を大きくしていました。

ユーザー2が投稿したblog文章を編集し、『これからTDLにでかけます。』を『これからTDSにでかけます。』に変更など。

環境

今はまだテスト環境ですが以下です。
OS:win10(今後linux)
言語:python
Framework:Django
DB:sqlite3(今後はpostgresqlかmysql)

行ったこと

参考にしたURL:Django REST Frameworkを使って爆速でAPIを実装する
Win10のAnacondaインストール
conda仮想環境構築
以下、(mysite_env) C:\work\last_django> のディレクトリにてスタート

cmd

1pip install django 2pip install djangorestframework 3pip install django-filter 4# プロジェクト作成 5django-admin startproject django_rest_framework_test 6cd django_rest_framework_test/ 7# アプリ作成 8python manage.py startapp blog

blog/models.py

python

1from django.db import models 2 3 4class User(models.Model): 5 name = models.CharField(max_length=32) 6 mail = models.EmailField() 7 8 9class Entry(models.Model): 10 STATUS_DRAFT = "draft" 11 STATUS_PUBLIC = "public" 12 STATUS_SET = ( 13 (STATUS_DRAFT, "下書き"), 14 (STATUS_PUBLIC, "公開中"), 15 ) 16 title = models.CharField(max_length=128) 17 body = models.TextField() 18 created_at = models.DateTimeField(auto_now_add=True) 19 updated_at = models.DateTimeField(auto_now=True) 20 status = models.CharField(choices=STATUS_SET, default=STATUS_DRAFT, max_length=8) 21 author = models.ForeignKey(User, related_name='entries', on_delete=models.CASCADE)

django_rest_framework_test/settings.py

python

1# blogを追記 2# Django Framework組み込みのため 'rest_framework'追記 3INSTALLED_APPS = [ 4 'django.contrib.admin', 5 'django.contrib.auth', 6 'django.contrib.contenttypes', 7 'django.contrib.sessions', 8 'django.contrib.messages', 9 'django.contrib.staticfiles', 10 'blog', 11 'rest_framework', 12]

cmd

1# migrationファイルを作る 2python manage.py makemigrations 3# migrationファイルを元にDBに反映する 4python manage.py migrate

cmd

1# admin用のユーザー作成 2python manage.py createsuperuser 3 Username (leave blank to use 'user'): dev 4 Email address: 5 Password: 6 Password (again): 7 Superuser created successfully.

blog/admin.py

python

1from django.contrib import admin 2 3from .models import User, Entry 4 5 6@admin.register(User) 7class UserAdmin(admin.ModelAdmin): 8 pass 9 10@admin.register(Entry) 11class Entry(admin.ModelAdmin): 12 pass

blog/serializer.py

python

1# coding: utf-8 2 3from rest_framework import serializers 4 5from .models import User, Entry 6 7 8class UserSerializer(serializers.ModelSerializer): 9 class Meta: 10 model = User 11 fields = ('name', 'mail') 12 13 14class EntrySerializer(serializers.ModelSerializer): 15 class Meta: 16 model = Entry 17 fields = ('title', 'body', 'created_at', 'status', 'author') 18

blog/views.py

python

1# coding: utf-8 2 3import django_filters 4from rest_framework import viewsets, filters 5 6from .models import User, Entry 7from .serializer import UserSerializer, EntrySerializer 8 9 10class UserViewSet(viewsets.ModelViewSet): 11 queryset = User.objects.all() 12 serializer_class = UserSerializer 13 14 15class EntryViewSet(viewsets.ModelViewSet): 16 queryset = Entry.objects.all() 17 serializer_class = EntrySerializer

django_rest_framework_test/urls.py

python

1# coding: utf-8 2 3from django.conf.urls import url, include 4from django.contrib import admin 5 6from blog.urls import router as blog_router 7 8urlpatterns = [ 9 url(r'^admin/', admin.site.urls), 10 # blog.urlsをincludeする 11 url(r'^api/', include(blog_router.urls)), 12]

blog/urls.py

python

1# coding: utf-8 2 3from rest_framework import routers 4from .views import UserViewSet, EntryViewSet 5 6 7router = routers.DefaultRouter() 8router.register(r'users', UserViewSet) 9router.register(r'entries', EntryViewSet)

cmd

1python manage.py runserver

blog投稿をGUIによる行い、
http://localhost:8000/api/entries/
実行で
イメージ説明

行き詰っているところ 質問

このAPIはあくまでdjangoによるDB作成(今回はsqlite3)をしているものに対してUPDATEやSELECTを行っているのですが、既存にすでにある別サーバのDBのテーブルをUPDATEする場合、そのサーバの接続情報とDBのIDPWを用意した場合、常にAPIサーバ側に同じDBを作成(migrate)しリアルタイム同期することで当初の要望が実現するのでしょうか。

Django REST frameworkでトランザクションしたい
この方が行っている事と同じようなものなのかと考えていますが、その場合、非常に多くのユーザーのアクセスやUPDATEがある場合、リアルタイムに整合性を保つことができるのか悩んでおります。

そもそも、外部のDBを操作する場合、このdjangoの同期の方法ではなく、DB情報さえあれば他の方法でAPIにより操作できる最良最速の方法などご存じあれば教えて頂けないでしょうか。よろしくお願い致します。

teamikl👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

サーバー・クライアント方式をサポートしているデータベースであれば可能です。

sqlite は組み込み用途向けなので、外部サーバーに指定するような運用は、通常はできません。
(ネットワーク・ファイルシステム越しならできますが、多くの更新がある場合は不向きです)

リアルタイムに整合性を保つ

「ミグレーション」や「トランザクション」よりも「レプリケーション」が近いと思いますが、
用途にとって、その方法が適切かどうかはよく検討してください。

目的が単純に外部のDBを更新したいだけなら、mysql か postgresql を導入する、が正着です。

投稿2021/06/09 00:32

teamikl

総合スコア8664

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dendenmushi

2021/06/10 01:24

お返事遅くなり申し訳ありません。回答ありがとうございます。 >サーバー・クライアント方式 postgresqlですと調べたところ問題ありませんでした。レプリケーションであれば、確かに望みにかなっていると思っています。ただ、こちらでリアルタイムのやりとりができる方法を考えております。何かdjangoにそのような参考となるサイトや資料などご存知であれば教えて頂けないでしょうか。
teamikl

2021/06/10 06:49 編集

ちなみにどのようなユースケースを想定されてるのでしょう ローカルのDBとは「別に」外部DBをアップデートしたいという事ですか? 普通に(レプリケーション関係なく) mysql や postgresql を指定すればよいだけだと思うのですが、 同期~の目的が良く解りません。 複数のデータベースを使う https://docs.djangoproject.com/ja/3.2/topics/db/multi-db/ レプリケーションの場合は、障害対策や負荷分散を目的とします。 ビジネスロジック内で外部のDBの更新が要求される場合は適切ではないかもしれません。 (レプリケーションなしでも完結しているかどうかが目安) 但し、質問で説明されてる「同じDBを作成し同期」はこちらの方が近いように感じます。 外部DBは、完全なDBの同期なのでしょうか?→レプリケーション それとも一部のデータが外部DBにあるのでしょうか?→複数のデータベースを使う
dendenmushi

2021/06/11 09:06 編集

回答頂きありがとうございます。 >ローカルのDBとは「別に」外部DBをアップデートしたいという事ですか? はい。例えばユーザー様がajaxでcurl https://~実行でアクセス制限されているDjangoサーバー(以下、α)に接続し、そこから、パラメーターにあるIDやPWを付加したqueryで、さらに外部のサーバー(以下、β)のDBにSELECTするケースになります。 通常これだけですと、初めからβにdjango実装でよいのではと思うと思うのですが、今私が作りたいのは、βをいじらず、αに(IDPWを付加)APIを設置したいと思っております。 結論としましてはAPIサーバーを別に設けたいという意味です。 >外部DBは、完全なDBの同期なのでしょうか?→レプリケーション 私の勝手な予想で、上記を達成するには、Django側に同じDBを常に用意しなければ、APIが作れないと思っていました。そもそもここが間違っていれば訂正いたします。 >それとも一部のデータが外部DBにあるのでしょうか?→複数のデータベースを使う αサーバーは、完全なβサーバーにあるDBのコピーという認識です。でもそれがそもそも上記を達成するのに不要なのであれば、αサーバー側に複製DBは不要となります。 (もし、Aという人物がA権限のデータをSELECTする分にはよいのですが、A権限以外のデータをSELECTは不可にしたいなどの権限上の問題も今考えております。)
teamikl

2021/06/11 09:47

>上記を達成するのに不要なのであれば、αサーバー側に複製DBは不要となります。 ここの認識をお互い詰めた方が良さそうですね。 確認: αにアクセスする時とβにアクセスする時で運用するデータは共通ですか? もし、2つのDBを運用して同じデータを同期するなら、 可能であれば、そもそもDBを1つにした方が構成は簡単です。 >Django側に同じDBを常に用意しなければ、APIが作れないと思っていました。 >そもそもここが間違っていれば訂正いたします。 ここは問題ありません。 API 内で一部、外部のDBを参照する必要がある、みたいなのを想定してましたが、 複製自体が目的だったりしないのであれば、直接外部DBを使う設定に出来ます。 提案できる方法としては、 1. データベースはネットワーク対応のものひとつにする。  sqlite を外部DBとして運用は問題がある為。選択肢は mysql postgres どちらか。  なので sqlite 運用中から移行する場合は migration が必要です。 2. α と β で、それぞれ個別の設定 (settings.py)を設ける。 3. 設定で、外部サーバーにあるDBを使う。 設定の切り替えは、以下を参照 https://docs.djangoproject.com/ja/3.2/topics/settings/ もし、どうしても sqlite で運用したいという場合、 質問で行おうとしてるような、独自に同期を取る等の対策が必要になってきます。 但し、レプリケーションを用いないとなると、障害時の同期対応がとても面倒なので、 運用するDBの移行の検討をお勧めします。
dendenmushi

2021/06/11 12:27 編集

ありがとうございます。 >確認: αにアクセスする時とβにアクセスする時で運用するデータは共通ですか? 運用するデータはまったく同じイメージでした。まだαはこれから用意するサーバーでDBも何も入っていない状態です。今後もしAPIからqueryを作りβに発信する際に、α側のサーバー内に同期されたDBなど必要なのであれば用意しようと考えていたのみです。最低限djangoAPIはαに構築予定です。 確かに、初めからαでDBとdjangoAPIを同時に作ってしまえば早いとは思うのですが、今回はβに既にできている状態で、そこにAPIはできるだけ区別するため置かない方法を今は考えています。 スマートフォン(orPC)→curl→djangoAPI(α)→select→DB(β) >ここは問題ありません。API 内で一部、外部のDBを参照する必要がある、みたいなのを想定してましたが、複製自体が目的だったりしないのであれば、直接外部DBを使う設定に出来ます この意味は、αにもβにも同期されたDBデータを用意すべきという意味でしょうか。理想はαにはdjangoAPIのみでβには既存のDBをひとつだけ用意し、APIが発動したらDBに向けてselect文など命令が飛びレスポンスするイメージです。 >sqlite 運用中から移行する場合は migration が必要です。 βはpostgresqlで作られていました。sqliteはαで試しに作ろうとしていただけでまだほとんど作っておりません。 >sqlite で運用したいという場合、質問で行おうとしてるような、独自に同期を取る等の対策が必要に postgresqlですと同期は必要ないということでしょうか。かなり理想に理想に近づきます。ありがとうございます。
teamikl

2021/06/12 06:51 編集

>スマートフォン(orPC)→curl→djangoAPI(α)→select→DB(β) こういった質問では、ソースコードよりも配置図の方が参考になりますね。 αとβを物理的に別のサーバー機だとして、 djangoAPI(α)→select→DB(β) 自体は可能です。 >Django側に同じDBを常に用意しなければ、APIが作れないと思っていました。 という部分で気になった点ですが チュートリアルではどちらも同じデータベース内に作るので、そう思われたのかなと感じました。 django が使うデータベース (admin やセッション情報) と API サーバーが使うデータベースを、別けて考えてみてはどうでしょう。 「複数のデータベースを使う」が解決の足掛かりになるはずです。 > postgresqlですと同期は必要ないということでしょうか。 若干齟齬がありそうなので、確認も含めて説明しておくと、 「postgresql だから同期が必要ない」のではなく 「DBサーバーをひとつで運用するので」、同期が不要になります。 DBサーバーを一つで運用する為には、別サーバーからは外部接続することになり、 外部のサーバーから接続する為に、sqlite ではなく postgresql や mysql を選ぶ、といった理路です。 postgresql でも、複数台でデータを共有して運用する場合は同期が必要になるので、 postgresql だから~というのは成り立ちません。 (意図は伝わってそうなので、細かい点の確認です。  postgresqlにすれば解決という問題ではなく、DBに使うサーバ構成を1台のみにする事が解決策) 尚、外部から接続の場合は、当然ですが権限関連の確認は必須です。 データベースのID:PW だけでなく、ネットワーク的に接続を許可されているか等も含みます。 捕足ですが、「DBサーバーをひとつで」は、API サーバーで使うDBについてです。 django 自身が使う DB を α に置きたい場合は、別途構成します。 - settings に複数のデータベースを設定。 - 特定のクエリのみ外部データベースに接続。  設定で一括して指定したい場合は 「DATABASE_ROUTERS」、もしくは  コード内で「using」でクエリに適応するDB設定を指定。
dendenmushi

2021/06/12 14:27 編集

>djangoAPI(α)→select→DB(β) 自体は可能です。 よかったです。 >django が使うデータベース (admin やセッション情報) とAPI サーバーが使うデータベースを、別けて考えてみてはどうでしょう。 adminやセッション情報はα側に、その他のテーブル(本来のDBの内容)はβのDBにということですね。 >postgresql だから~というのは成り立ちません。DBに使うサーバ構成を1台のみにする事が解決策 理解できました。 >データベースのID:PW だけでなく、ネットワーク的に接続を許可されているか等も含みます。 ありがとうございます。 >捕足ですが、「DBサーバーをひとつで」は、API サーバーで使うDBについてです。django 自身が使う DB を α に置きたい場合は、別途構成します。 こちらの補足の確認ですが、上記で言われている結論と同じということで間違えないでしょうか。あくまでαサーバーには『APIで使うadminやセッション情報のためのテーブルDB』、βには本来のデータ(blog本文など)を用意。 django 自身が使う DBをβにする場合→DBサーバーをひとつにするという意味。 django 自身が使う DBをαにする場合→別途構成が必要。 >設定で一括して指定したい場合は 「DATABASE_ROUTERS」、もしくはコード内で「using」でクエリに適応するDB設定を指定。 これらの方法でαにはadmin関係のdjangoDB、β側に目的のデータのあるDBがある、私の目的が達成されるということでしょうか。もしかして、このやり方じたいはAPIの常識的な利用なのでしょうか。チュートリアルでも他のサイトでも例となるコードが見つからず困っていました。外部DBへ接続しSELECTするAPI利用の調べやすいワードなどもしご存じであればそちらも教えて頂けないでしょうか。 本当に感謝しております。ありがとうございます。
teamikl

2021/06/12 22:18

「外部DBへ接続しSELECTする」 の認識が、 ローカルマシン外なのか、django 内部で使うDBに対しての外部という意味なのかで 齟齬が有るかと思います。通常、外部DBといった場合、外部のネットワークにあるDBだと思うので これに対しての回答なら、ネットワーク接続対応である mysql, postgresql 等を使うです。 ⇛ 外部にある既存DBのβは postgres なので、この点はクリア。 次に出来る事としては django は使わず、αから接続できるかの確認。(権限、ネットワーク構成等) django 内部で使うDB とは別の外部DB を使う、に対する回答は、 「複数のデータベースを使う」https://docs.djangoproject.com/ja/3.2/topics/db/multi-db/ ---- 運用方法としては「マルチテナント」が近いと思いますが、構成は少し応用が必要そうですね。 βに αで使うdjango のDBも作れれば、DBを別ける必要がなくなりシンプルな構成になるのですが。 >これらの方法でαにはadmin関係のdjangoDB、β側に目的のデータのあるDBがある、私の目的が達成されるということでしょうか。 に関しては、「djangoのmodelで」「外部DB」を使う方法の提示です。 全容を把握できてないので、実際の状況にどう適合するかは(私の視点からは)不明です。 βにある既存DBが django のモデルで作られているか、αのadminで使えるようしたいか等。 可能かどうかの質問に対する回答としては可能ですが、方法や手間は異なってきます。 (但し、運用上の制限はあります。詳しくは 「複数のデータベースを使う」参照) αとβが別プロジェクトの場合は、 データの同期以外の問題で、データスキーマについても考えないといけないはずです。 既存DBであるβ側のテーブル定義が変わった場合、α側はどうするか、等。 inspectdb で既存DB から models を作り migrate https://docs.djangoproject.com/ja/3.2/howto/legacy-databases/
dendenmushi

2021/06/14 23:37

>ローカルマシン外なのか、django 内部で使うDBに対しての外部という意味なのかで 「外部DBへ接続しSELECTする」 の外部DBは、django内部ではなく、外の別のサーバ内にあるDB(既存)のものでした。 >αとβが別プロジェクトの場合は、データの同期以外の問題で、データスキーマについても考えないといけないはず データ同期以外にその点も注意ですね。ありがとうございます。 非常に参考になるURLです。一度こちらで行ってみます。 見えてきました。本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問