फ्लास्क-SQLAlchemy आयात / संदर्भ मुद्दा


117

मैं अपने फ्लास्क ऐप को कुछ संरचना देना चाहता हूं जैसे:

./site.py
./apps/members/__init__.py
./apps/members/models.py

apps.members एक फ्लास्क ब्लूप्रिंट है।

अब, मॉडल वर्गों को बनाने के लिए मुझे ऐप की पकड़ होनी चाहिए, कुछ इस तरह से:

# apps.members.models
from flask import current_app
from flaskext.sqlalchemy import SQLAlchemy

db = SQLAlchemy(current_app)

class Member(db.Model):
    # fields here
    pass

लेकिन अगर मैं अपने ब्लूप्रिंट ऐप में उस मॉडल को आज़माता हूँ और आयात करता हूँ, तो मुझे डर लगता है RuntimeError: working outside of request context। मैं अपने ऐप को सही तरीके से यहां कैसे पकड़ सकता हूं? रिश्तेदार आयात काम कर सकते हैं, लेकिन वे बहुत बदसूरत हैं और उनके स्वयं के संदर्भ मुद्दे हैं, जैसे:

from ...site import app

# ValueError: Attempted relative import beyond toplevel package

जवाबों:


295

flask_sqlalchemyमॉड्यूल तुरंत अनुप्रयोग के साथ प्रारंभ होने की जरूरत नहीं है - आप इस के बजाय कर सकते हैं:

# apps.members.models
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class Member(db.Model):
    # fields here
    pass

और फिर अपने एप्लिकेशन सेटअप में आप कॉल कर सकते हैं init_app:

# apps.application.py
from flask import Flask
from apps.members.models import db

app = Flask(__name__)
# later on
db.init_app(app)

इस तरह आप चक्रीय आयात से बच सकते हैं।

यह पैटर्न करता नहीं की जरूरत आप एक फ़ाइल में अपने सभी मॉडलों के जगह। बस dbअपने प्रत्येक मॉडल मॉड्यूल में चर आयात करें ।

उदाहरण

# apps.shared.models
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

# apps.members.models
from apps.shared.models import db

class Member(db.Model):
    # TODO: Implement this.
    pass

# apps.reporting.members
from flask import render_template
from apps.members.models import Member

def report_on_members():
    # TODO: Actually use arguments
    members = Member.filter(1==1).all()
    return render_template("report.html", members=members)

# apps.reporting.routes
from flask import Blueprint
from apps.reporting.members import report_on_members

reporting = Blueprint("reporting", __name__)

reporting.route("/member-report", methods=["GET","POST"])(report_on_members)

# apps.application
from flask import Flask
from apps.shared import db
from apps.reporting.routes import reporting

app = Flask(__name__)
db.init_app(app)
app.register_blueprint(reporting)

नोट: यह आपके द्वारा दी जाने वाली कुछ शक्ति का एक स्केच है - स्पष्ट रूप से थोड़ा अधिक है कि आप विकास को और भी आसान बनाने के लिए कर सकते हैं (एक create_appपैटर्न का उपयोग करके , कुछ फ़ोल्डरों में ऑटो-रजिस्टरिंग ब्लूप्रिंट, आदि)


2
क्या आप ऐसा कई बार कर सकते हैं? उदाहरण के लिए यदि मेरे पास एक से अधिक मॉडल के लिए फ़ाइल है?
ब्रैड राइट

@ ब्रैडराइट - यह आसान बनाता है यदि आप dbप्रत्येक डेटाबेस के लिए केवल उदाहरण बनाते हैं जो आपके पास है। यदि आपके पास मॉडल का एक पैकेज है, तो आप इसे अंदर रख सकते हैं __init__.py। हालाँकि आप इसे करने के लिए चुनते हैं, आप बस dbउस स्थान से चर को अपनी अन्य मॉडल फ़ाइलों में आयात करते हैं और इसे सामान्य रूप में उपयोग करते हैं। जब वे लोड होते हैं तो सब कुछ सही ढंग से हल हो जाता है।
सीन विएरा

1
क्या आप इस तरह से स्थापित की गई परियोजना के लिए एक लिंक है?
म्बेवड़ा

4
@Mbrevda - आप इस पद्धति का एक उदाहरण देख सकते हैं github.com/svieira/Budget-Manager
शॉन विएरा

1
.ext.नाम स्थान अब मान्य नहीं है - यह असली नाम स्थान से आयात करने के लिए बेहतर है ( flask_sqlalchemy)।
सीन विएरा

25

एक मूल app.py : https://flask-sqlalchemy.palletsprojects.com/en/2.x/quickstart/

...

app = flask.Flask(__name__)
app.config['DEBUG'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = flask.ext.sqlalchemy.SQLAlchemy(app)

class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
...

class Computer(db.Model):
    id = db.Column(db.Integer, primary_key=True)
...

# Create the database tables.
db.create_all()

...

# start the flask loop
app.run()

मैंने ब्लूप्रिंट का उपयोग किए बिना सिर्फ एक app.py to app.py और model.py को विभाजित किया। उस स्थिति में, उपरोक्त उत्तर काम नहीं करेगा। काम करने के लिए एक लाइन कोड की आवश्यकता होती है।

पहले :

db.init_app(app)

के बाद :

db.app = app
db.init_app(app)

और, निम्न लिंक बहुत उपयोगी है।

http://piotr.banaszkiewicz.org/blog/2012/06/29/flask-sqlalchemy-init_app/


2
db.app = appक्योंकि रनटाइमर हो रहा था क्योंकि init_app doesnt सेट ऐप। +1
अमित त्रिपाठी

3
db.app = app(उसके बाद db.init_app(app)) मेरे लिए गायब था। उस लाइन को जोड़ने के बाद पूरी तरह से काम करता है (सीन विएरा के जवाब के साथ संयुक्त)
डॉट

पहला लिंक पुराना है।
राहुल केपी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.