Currently I'm running into issues with my models.py and Postgresql. The site is deployed on Heroku using Postgresql and the problem is models.py. Currently, I have models.py as a models.Charfield() and it works fine with sqlite, but when I deployed it to production, Postgresql still reports that it's a models.IntFied(). And because it's an integer field it won't allow for characters for some reason.
Originally, I had it as a integerfield but decided to change to charfield, yet it still won't change to charfield.
Solutions I've tried: resetting the database on heroku, deleting and recreating the database on heroku.
Any help is appreciated,
Thanks
To sync your models to your database relational schema, you have to run the command:
python manage.py makemigrations
python manage.py migrate
I normally follow the steps in this order:
Ensure that your database changes have all been committed with git add and commit commands
Reset the heroku database, Run
{heroku pg:reset DATABASE_URL}
Push your current changes to heroku with
{git push heroku master}
Launch the heroku terminal
{heroku run bash}
On the heroku terminal run
{python manage.py migrate}
I changed the database from SQLite3 to PostgreSQL in my Django project. Is it possible to store my new database in the GitHub repository so that after cloning and running by the command
python manage.py runserver
the project has started with the whole database?
You cannot save the database as such, you can instead create fixtures to be run. Whenever someone will clone the project, he/she can simple run those fixtures to populate the database.
I have flask-migrate (version 1.8.0) working well with a sqlite database in a development environment. Now I would like to migrate our data to MySQL and maintain all of our migration history (so it stays in sync with our Flask-SQLAlchemy models in our git repository).
I created an empty MySQL database, and after changing my SQLALCHEMY_DATABASE_URI, I tried running:
python manage.py db upgrade
That resulted in an error about not being able to drop the table migrate_version. (Which makes sense, since this is a new database, although sqlite actually contains the table 'alembic_version' not 'migrate_version'.)
So, I tried to initialize this new database:
python manage.py db init
Now I get an error: "Directory migrations already exists".
I can rename that folder and re-run the command with no problem, but then I lose all of my previous migrations. I think we would have the same issues when we also transition to our test and production environments.
I've seen in the docs Flask-Migrate has multiple database support, but I think that looks to be more for maintaining multiple databases in a single development environment. Is there a way to have Flask-Migrate track changes across multiple development environments?
To address the real issue in the OP's question, you need to use the --directory flag to initiate a migrations directory specific to your each environment's database.
From the flask-migrate documentation:
All commands also take a --directory DIRECTORY option that points to
the directory containing the migration scripts. If this argument is
omitted the directory used is migrations.
So:
flask db init --directory=[DIRECTORY NAME]
Flask-Migrate itself has no memory of your database, so when running migration commands with flask db, it will reference the specified migrations directory (by default, when the --directory flag is not used, this is called 'migrations').
flask db migrate --directory=[DIRECTORY_NAME]
etc.
It goes without saying that the flask command will reference the application context as configured by your config file or environment variables.
I typically create a migration directory for each environment with an explicit reference to the environment: e.g. development and staging, with something like 'migrations_dev' and 'migrations_stg'.
Hope this is helpful.
Here are the steps I took to transition from SQLite to MySQL and maintain all the migration history. I highly suspect there is a better way to do this, but it worked for me.
Initialize the new, blank database using another folder for your "new" migrations
python manage.py db init -d tmp
Create a migration
python manage.py db migrate -d tmp -m "Bring MySQL up to date"
Apply the migration
python maange.py db upgrade -d tmp
Now, you can delete the "tmp" migrations folder. You no longer need it. Find the HEAD migration. Look for 'Rev: your_revision_num (head)'
python manage.py db show
Run an update statement against your MySQL database
update alembic_version set version_num = 'your_revision_num'
Now your MySQL database schema should match your old SQLite schema and you'll have your full migration history as well.
The table migrate_version is used to track migrations by package sqlalchemy-migrate. Alembic, the package used by Flask-Migrate, uses a alembic_version table, as you know.
So my guess, is that this MySQL database that you want to use has been used before by an application that was under sqlalchemy-migrate control.
I recommend that you delete the MySQL database and make a brand new one.
I also had the same need on my side. I wanted to reproduce the command that exists in the laravel framework to make a migration in different environments:
php artisan migrate --env prod
With this kind of command, you can launch a migration in different environments. I have not found a directly equivalent command in flask.
THE "flask db upgrade --env prod" command does not exist. In particular, the --env argument .
As a workaround, I created a command that allows me to change the environment:
flask env --name prod
That command is a custom flask command that will copy the content of the .env.prod file to .env.
This way, the application is in the prod environment. And we can then launch the migration command on the prod environment.
How to use the custom env command to migrate to different environments?
To start the migration in the staging environment, just run these two commands:
flask env --name staging
flask db updgrade
Then if you want to start the migration in the production environment, just run these two commands:
flask env --name prod
flask db updgrade
How to create the custom command flask env?
First, you need to know how to create custom command in flask. Just follow the official falsk documentation
Here is the content of my custom command which allows to change the environment:
from flask.cli import with_appcontext
import shutil
#click.command('env')
#click.option("--name", is_flag=False, flag_value="Flag", default="")
#with_appcontext
def env(name):
if name == '':
print(os.getenv('FLASK_ENV'))
return
if name not in ['dev', 'prod', 'local', 'staging']:
print('That env does not exist')
return
shutil.copyfile('.env.' + name, '.env')
return
In my setup, I have 4 environments: local, dev, staging, prod.
And I have 4 corresponding .env files: .env.local, .env.staging, .env.prod, .env.dev
The custom flask env command also copies the contents of the environment files into the .env file that the flask application loads at start-up.
I used to use manage.py sqlall app to dump the database to sql statements. While, after upgrading to 1.8, it doesn't work any more.
It says:
CommandError: App 'app' has migrations. Only the sqlmigrate and
sqlflush commands can be used when an app has migrations.
It seems there is not a way to solve this.
I need to dump the database to sql file, so I can use it to clone the whole database else where, how can I accomplish this?
You can dump the db directly with mysqldump as allcaps suggested, or run manage.py migrate first and then it should work. It's telling you there are migrations that you have yet to apply to the DB.
Try the following:
python manage.py dumpdata <app_name> > <outputfile>
I'm following this tutorial: http://tutorial.djangogirls.org/en/domain/README.html
When I do python manage.py runserver it works fine. It also works when I run
heroku ps:scale web=1
then
heroku open
with python manage.py runserver it shows my blog posts and everything that I had added. But when I run the server with heroku open there are no posts as if the database is missing or something.
Why is that? Why do the two commands launch the same web page but with different posts/different databases?
Which brings me to my follow up question: how do I know when I need to run migrate or makemigrations again for the server? Would doing so fix the problem? And what exactly do those commands do/why are they necessary?
Thanks
EDIT:
Bonus question: Why do my posts display in descending order of time? The new posts are on the bottom of the page rather than the top. How can I change this?
There is a difference between your local development and your deployed project.
I assume you created your posts local. So they are saved local into your database. Local you use a filebased database defined in the settings 'django.db.backends.sqlite3' that means when you run manage.py syncdb the file is created with all tables inside. When you deploy your code to heroku the code is pushed to the server and runs from this place. This can be everywhere, so it can't connect to your local databasefile. For your project you has to setup a database on heroku as well. I recommend to read this article. When you want to transfer your data you can create a database dump local and load all data to you heroku database. Described here and here.
Another point, you don't run the server with heroku open or by fire python manage.py runserver. The heroku server is automatically started when your git push heroku master is done. It use the configs from your Procfile.
When you want to migrate your heroku database you has to run heroku run python manage.py migrate <app_name> than the migration is done remotely on the heroku server. You have to run this command everytime you changed a model and added a migrationfile with python manage.py makemigration <app_name>. When you did this you has to migrate you database local and remote. That means that you change the database structure to match your models. Remember the models are only a abstraction(orm) of your database.
I don't know your project but the order sees legit. Try to imagine this as rows. first row comes first. So the last entered row is on the bottom. You can change the order of the queryset with something like.order_by('-id'). So you get all entries in reverse order.