Flask, SQLAlchemy, Alembic ve Flask (Flask-SQLAlchemy ve Flask-Migrate) için ambalajları üzerinde bir proje üzerinde çalışıyorum. Dört göçler vardır: Bir yeni ve temiz bir veritabanı başlayıp bir hata alıyorum göçler çalıştırmayıFlask-Migrate neden 2 adımlı geçişi yapıyor?
1c5f54d4aa34 -> 4250dfa822a4 (head), Feed: Countries
312c1d408043 -> 1c5f54d4aa34, Feed: Continents
41984a51dbb2 -> 312c1d408043, Basic Structure
<base> -> 41984a51dbb2, Init Alembic
:
[email protected]:/vagrant$ python manage.py db upgrade
...
sqlalchemy.exc.ProgrammingError: (ProgrammingError) relation "continent" does not exist
...
Ben Flask-geçirme Tüm taşıma işlemlerini çalıştırmak için sorarsanız ancak Son, işe yarıyor. Ondan sonra tekrar yükseltme komutunu çalıştırırsanız, çalışır - yani, tam kodda tek değişiklik olmadan benim veritabanı yükseltir:
[email protected]:/vagrant$ python manage.py db upgrade 312c1d408043
INFO [alembic.migration] Context impl PostgresqlImpl.
INFO [alembic.migration] Will assume transactional DDL.
INFO [alembic.migration] Running upgrade -> 41984a51dbb2, Init Alembic
INFO [alembic.migration] Running upgrade 41984a51dbb2 -> 312c1d408043, Basic Structure
[email protected]:/vagrant$ python manage.py db upgrade
INFO [alembic.migration] Context impl PostgresqlImpl.
INFO [alembic.migration] Will assume transactional DDL.
INFO [alembic.migration] Running upgrade 312c1d408043 -> 1c5f54d4aa34, Feed: Continents
INFO [alembic.migration] Running upgrade 1c5f54d4aa34 -> 4250dfa822a4, Feed: Countries
TL; DR
son göç (Besleme: Ülkeler), bir öncekiyle beslenen tabloda sorgulama yapar (Feed: Continents). Kıtalar tablosunu oluşturup beslediğimde, betikler çalışmalıdır. Ama öyle değil. Neden başka bir komutta yeniden başlatmak için geçiş işlemini durdurmam gerekiyor? Bunu gerçekten anlamadım. Alembic, bir dizi göçten sonra yürüten bir komut mu? Herhangi bir fikir?
Benim modeller olarak tanımlanır Her ihtimale karşı
aşağıdaki gibidir:
class Country(db.Model):
__tablename__ = 'country'
id = db.Column(db.Integer, primary_key=True)
alpha2 = db.Column(db.String(2), index=True, unique=True)
title = db.Column(db.String(140))
continent_id = db.Column(db.Integer, db.ForeignKey('continent.id'))
continent = db.relationship('Continent', backref='countries')
def __repr__(self):
return '<Country #{}: {}>'.format(self.id, self.title)
class Continent(db.Model):
__tablename__ = 'continent'
id = db.Column(db.Integer, primary_key=True)
alpha2 = db.Column(db.String(2), index=True, unique=True)
title = db.Column(db.String(140))
def __repr__(self):
return '<Continent #{}: {}>'.format(self.id, self.title)
çok teşekkür ederiz,
UPDATE 1: son iki göçlerden geçiş yöntemini
@Miguel bir yorumda sordu, burada yükseltme m var Son iki göçler edilmesinin yöntemlerine:
Feed: Kıtalar
def upgrade():
csv_path = app.config['BASEDIR'].child('migrations', 'csv', 'en')
csv_file = csv_path.child('continents.csv')
with open(csv_file) as file_handler:
csv = list(reader(file_handler))
csv.pop(0)
data = [{'alpha2': c[0].lower(), 'title': c[1]} for c in csv]
op.bulk_insert(Continent.__table__, data)
Feed:
def upgrade():
# load countries iso3166.csv and build a dictionary
csv_path = app.config['BASEDIR'].child('migrations', 'csv', 'en')
csv_file = csv_path.child('iso3166.csv')
countries = dict()
with open(csv_file) as file_handler:
csv = list(reader(file_handler))
for c in csv:
countries[c[0]] = c[1]
# load countries-continents from country_continent.csv
csv_file = csv_path.child('country_continent.csv')
with open(csv_file) as file_handler:
csv = list(reader(file_handler))
country_continent = [{'country': c[0], 'continent': c[1]} for c in csv]
# loop
data = list()
for item in country_continent:
# get continent id
continent_guess = item['continent'].lower()
continent = Continent.query.filter_by(alpha2=continent_guess).first()
# include country
if continent is not None:
country_name = countries.get(item['country'], False)
if country_name:
data.append({'alpha2': item['country'].lower(),
'title': country_name,
'continent_id': continent.id})
CSV I (son göç beslenen masaya bağlıdır) Ülkeler kullanıyorum temelde şu kalıpları izliyor:
con tinents.csv
...
AS, "Asia"
EU, "Europe"
NA, "North America"
...
iso3166.csv
...
CL,"Chile"
CM,"Cameroon"
CN,"China"
...
_country_continent.csv_
...
US,NA
UY,SA
UZ,AS
...
Yani Feed: Kıtalar kıta tablosunu yayınları ve Feed: Ülkeler ülke tablosunu besler. Ancak, kıta ile ülke arasında doğru bağlantıyı kurmak için kıta tablosunu sorgulamak zorunda.
GÜNCELLEME 2: Reddit bazı biri zaten bir açıklama ve
Ben the same question on Reddit sorulan bir çözüm sundu ve themathemagician söyledi: reddit'te @themathemagician tarafından belirtildiği gibi
I've run into this before, and the issue is that the migrations don't execute individually, but instead alembic batches all of them (or all of them that need to be run) and then executes the SQL. This means that by the time the last migration is trying to run, the tables don't actually exist yet so you can't actually make queries. Doing
from alembic import op def upgrade(): #migration stuff op.execute('COMMIT') #run queries
This isn't the most elegant solution (and that was for Postgres, the command may be different for other dbs), but it worked for me. Also, this isn't actually an issue with Flask-Migrate as much as an issue with alembic, so if you want to Google for more info, search for alembic. Flask-Migrate is just a wrapper around alembic that works with Flask-Script easily.
Son iki geçişin 'upgrade()' yöntemlerini ekleyebilir misiniz? – Miguel
@Miguel, teşekkürler, sadece yazıyı düzenledim ve yöntemleri ekledim. BTW, [başka bir yerde] (https://github.com/cuducos/whiskyton#thanks) Sana “teşekkür ederim” dedim ama belki de görmedin - yani, bir kez daha haha… – cuducos