Flask Migrate "ValueError: Constraint must have a name" - flask

I have created a flask migrate script ,however, when I running the upgrade function, I get the following error:
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 6378428b838a, empty message
Traceback (most recent call last):
File "migrate.py", line 22, in <module>
manager.run()
File "/Users/slatifi/git/StaffTrainingLog/venv/lib/python3.7/site-packages/flask_script/__init__.py", line 417, in run
result = self.handle(argv[0], argv[1:])
File "/Users/slatifi/git/StaffTrainingLog/venv/lib/python3.7/site-packages/flask_script/__init__.py", line 386, in handle
res = handle(*args, **config)
File "/Users/slatifi/git/StaffTrainingLog/venv/lib/python3.7/site-packages/flask_script/commands.py", line 216, in __call__
return self.run(*args, **kwargs)
File "/Users/slatifi/git/StaffTrainingLog/venv/lib/python3.7/site-packages/flask_migrate/__init__.py", line 95, in wrapped
f(*args, **kwargs)
File "/Users/slatifi/git/StaffTrainingLog/venv/lib/python3.7/site-packages/flask_migrate/__init__.py", line 280, in upgrade
command.upgrade(config, revision, sql=sql, tag=tag)
File "/Users/slatifi/git/StaffTrainingLog/venv/lib/python3.7/site-packages/alembic/command.py", line 298, in upgrade
script.run_env()
File "/Users/slatifi/git/StaffTrainingLog/venv/lib/python3.7/site-packages/alembic/script/base.py", line 489, in run_env
util.load_python_file(self.dir, "env.py")
File "/Users/slatifi/git/StaffTrainingLog/venv/lib/python3.7/site-packages/alembic/util/pyfiles.py", line 98, in load_python_file
module = load_module_py(module_id, path)
File "/Users/slatifi/git/StaffTrainingLog/venv/lib/python3.7/site-packages/alembic/util/compat.py", line 173, in load_module_py
spec.loader.exec_module(module)
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "migrations/env.py", line 96, in <module>
run_migrations_online()
File "migrations/env.py", line 90, in run_migrations_online
context.run_migrations()
File "<string>", line 8, in run_migrations
File "/Users/slatifi/git/StaffTrainingLog/venv/lib/python3.7/site-packages/alembic/runtime/environment.py", line 846, in run_migrations
self.get_context().run_migrations(**kw)
File "/Users/slatifi/git/StaffTrainingLog/venv/lib/python3.7/site-packages/alembic/runtime/migration.py", line 518, in run_migrations
step.migration_fn(**kw)
File "/Users/slatifi/git/StaffTrainingLog/migrations/versions/6378428b838a_.py", line 23, in upgrade
batch_op.create_foreign_key(None, 'organisation', ['organisation'], ['id'])
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/contextlib.py", line 119, in __exit__
next(self.gen)
File "/Users/slatifi/git/StaffTrainingLog/venv/lib/python3.7/site-packages/alembic/operations/base.py", line 325, in batch_alter_table
impl.flush()
File "/Users/slatifi/git/StaffTrainingLog/venv/lib/python3.7/site-packages/alembic/operations/batch.py", line 106, in flush
fn(*arg, **kw)
File "/Users/slatifi/git/StaffTrainingLog/venv/lib/python3.7/site-packages/alembic/operations/batch.py", line 390, in add_constraint
raise ValueError("Constraint must have a name")
ValueError: Constraint must have a name
I have seen other people with the same error and they simply added render_as_batch to the env.py file. I did this but I still get the same error. Any thoughts?
Note: This is the modification I made in the env.py file:
with connectable.connect() as connection:
context.configure(
connection=connection,
target_metadata=target_metadata,
process_revision_directives=process_revision_directives,
**current_app.extensions['migrate'].configure_args,
render_as_batch=True
)
This is the upgrade script created by the migration
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '2838e3e96536'
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('user', schema=None) as batch_op:
batch_op.add_column(sa.Column('organisation', sa.String(length=5), nullable=False))
batch_op.create_foreign_key(None, 'organisation', ['organisation'], ['id'])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('user', schema=None) as batch_op:
batch_op.drop_constraint(None, type_='foreignkey')
batch_op.drop_column('organisation')
# ### en
d Alembic commands ###

This is normal because SQLite3 doesn't support ALTER tables.
You can pass the render_as_batch=True during the instantiation of Flask-Migrate like this :
migrate = Migrate(app,db,render_as_batch=True)
Don't need to modify the env file of Flask-Migrate.
In addition, to totally avoid the problem for your futures migrations, you can create a constraint naming templates for all types of constraints to the SQLAlchemy metadata, and then I think you will get consistent names.
See how to do this in the Flask-SQLAlchemy documentation. I'm copying the code example from the docs below for your convenience:
from sqlalchemy import MetaData
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
convention = {
"ix": 'ix_%(column_0_label)s',
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(constraint_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s"
}
metadata = MetaData(naming_convention=convention)
db = SQLAlchemy(app, metadata=metadata)

The other answers show how to configure Flask to use named constraints in the future, but that doesn't solve the problem of dropping existing unnamed constraints in Alembic migrations. To handle any existing unnamed constraints, you need to also define the naming convention in the migration script, as explained in the Alembic docs.
For example, suppose you're trying to do a migration that adds ON DELETE CASCADE to an existing foreign key in your test table. If you've followed one of the other answers (e.g. https://stackoverflow.com/a/62651160/470844) and added the naming_convention to the Flask init script, then flask db upgrade will generate something like this:
def upgrade():
with op.batch_alter_table('test', schema=None) as batch_op:
batch_op.drop_constraint(None, type_='foreignkey')
batch_op.create_foreign_key(batch_op.f('fk_test_user_id_user'), 'user', ['user_id'], ['id'], ondelete='CASCADE')
Note that while the create_foreign_key call uses a constraint name (i.e. fk_test_user_id_user), the drop_constraint call still uses None as the constraint name, which will cause ValueError: Constraint must have a name error in this question's title.
To fix that, you need to edit the migration to use the naming_convention, and replace the None with the generated constraint name. For example, you'd change the above upgrade to:
naming_convention = {
"ix": 'ix_%(column_0_label)s',
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(column_0_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s"
}
def upgrade():
with op.batch_alter_table('test', schema=None, naming_convention=naming_convention) as batch_op:
batch_op.drop_constraint('fk_test_user_id_user', type_='foreignkey')
batch_op.create_foreign_key(batch_op.f('fk_test_user_id_user'), 'user', ['user_id'], ['id'], ondelete='CASCADE')
(In this example, you'd also need to disable SQLite foreign key support while running the migration script, e.g. using the technique here, to avoid the batch migration itself triggering a cacading delete. The problem is documented here.)

Installing Flask-Migrate helps to avoid code references to declarative_base or modifying the env.py file.
For apps with app factory, split the metadata assignment and the db initiation between the extensions.py and __init__.py files.
extensions.py:
from sqlalchemy import MetaData
from flask_sqlalchemy import SQLAlchemy
metadata = MetaData(
naming_convention={
"ix": 'ix_%(column_0_label)s',
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(constraint_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s"
}
)
db=SQLAlchemy(metadata=metadata)
__init__.py:
from flask import Flask, Blueprint
from config import ...
from flask_migrate import Migrate
from extensions import db
...
def create_app():
app = Flask(__name__,
template_folder='../app/templates')
app.config.from_object(config[...])
config[...].init_app(app)
db.init_app(app)
with app.app_context():
db.create_all()
migrate = Migrate(app, db)
...
from .templates.main import main
app.register_blueprint(main)
return app

Related

Flask Security - Send confirmation email?

I am trying to create a flask boilerplate app and I am running into an error when I try to run a flask-script. I am getting an error that I don't fully understand, the code is broken up into several modules so it may be best to post the link to the repository. The two parts in the traceback that are my code are an import from the app and the creation of the security object.
The two files that are causing conflict are:
manage.py
app/__init__.py
What caused the problem is that I set several security variables to true:
SECURITY_REGISTERABLE = True
SECURITY_SEND_REGISTER_EMAIL = True
SECURITY_CONFIRMABLE = True
SECURITY_CONFIRM_URL = True
SECURITY_EMAIL_SENDER = 'some_email_account'
SECURITY_CONFIRM_LOGIN_WITHOUT_CONFIRMATION = False
SECURITY_TRACKABLE = True
SECURITY_CHANGEABLE = True
The project can be found here:
github link
Traceback (most recent call last):
File "manage.py", line 4, in <module>
from app import app, db, Role, user_datastore
File "C:\Users\...\dev\flask-boilerplate\app\__init__.py", line 22, in <module>
security = Security(app, user_datastore)
File "C:\Users\...\dev\flask-boilerplate\venv\lib\site-packages\flask_security\core.py", line 469, in __init__
self._state = self.init_app(app, datastore, **kwargs)
File "C:\Users\...\dev\flask-boilerplate\venv\lib\site-packages\flask_security\core.py", line 507, in init_app
app.register_blueprint(create_blueprint(state, __name__))
File "C:\Users\...\dev\flask-boilerplate\venv\lib\site-packages\flask_security\views.py", line 383, in create_blueprint
'<token>'),
File "C:\Users\...\dev\flask-boilerplate\venv\lib\site-packages\flask_security\utils.py", line 249, in slash_url_suffix
return url.endswith('/') and ('%s/' % suffix) or ('/%s' % suffix)
AttributeError: 'bool' object has no attribute 'endswith'
SECURITY_CONFIRM_URL must be a string (i.e. SECURITY_CONFIRM_URL='https://google.com)

Django: conflicting models in (third-party) application

I integrated a third party app into my Django project, and only when I import it will I get this error message.
RuntimeError: Conflicting 'task' models in application 'django_q': <class 'django_q.models.Task'> and <class 'models.Task'>.
I'm puzzled because my app runs well withouth it so I wonder how it could be an error on my side. I'm only using the app in its most simple use case. My general question is then: how can I investigate ?
So the app is django-q, a task queue (github). I installed it and called it in its most simple usage, following the good documentation.
CACHE = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'cache_table',
}
}
Q_CLUSTER = {
'name': 'DjangORM_queue',
'workers': 4,
'timeout': 3600,
'retry': 4000,
# 'queue_limit': 50,
# 'bulk': 10,
'orm': 'default'
}
api.py:
# api.py
# not putting all imports or __init__.py
def myhook(task):
print task.result
import ipdb; ipdb.set_trace()
def mymethod(request, pk, **kwargs):
from django_q.tasks import async, result
async('models.MyModel.method', pk, hook='myhook', sync=True)
Now manage.py runserver is ok, until I call my api and it reaches tasks.async. Full stacktrace:
Traceback (most recent call last):
File "/home/[...]/django/core/handlers/base.py", line 132, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/.../my-project/searchapp/models/api.py", line 965, in mymethod
tasks.async('models.MyModel.mymethod', pk, hook='myhook', sync=True)
File "/home/[...]/django_q/tasks.py", line 43, in async
return _sync(pack)
File "/home/[...]/django_q/tasks.py", line 176, in _sync
cluster.worker(task_queue, result_queue, Value('f', -1))
File "/home/[...]/django_q/cluster.py", line 369, in worker
m = importlib.import_module(module)
File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "/home/[...]/django_q/models.py", line 15, in <module>
class Task(models.Model):
File "/home/[...]/django/db/models/base.py", line 309, in __new__
new_class._meta.apps.register_model(new_class._meta.app_label, new_class)
File "/home/[...]/django/apps/registry.py", line 221, in register_model
(model_name, app_label, app_models[model_name], model))
RuntimeError: Conflicting 'task' models in application 'django_q': <class 'django_q.models.Task'> and <class 'models.Task'>.
I first checked I don't have a model named Task, nor do my django installed apps. We don't.
I searched for a similar pb and found this SO answer, so I tried to tweak the imports of django-q, with no success (it doesn't mean I did it right though).
Is it a circular import (SO hint) ?
A Django bug report (which wasn't) is interesting also, I found comment 13 particarly (about double entries in sys.path and ways of import). My sys.path has [ my_project, …/site_packages/django_q, …/site_packages/] so I don't feel impacted by comment 13's description;
I couldn't reproduce the issue on a fresh django project;
I feel like trying another queuing system :/
Any hints on what could be wrong ?
Thanks !
ps: I could also point to my full repo
Too bad, I went with huey. It's simple and complete.
django-rq looks like a good solution too, with a django dashboard integration.

Django + heroku - import error on line that doesn't exist

I'm new to django (using python 2.7) and I was just trying to use heroku for the first time but I always get the following error:
remote: -----> Preparing static assets
remote: Collectstatic configuration error. To debug, run:
remote: $ heroku run python manage.py collectstatic --noinput
When I run that command, an import error regarding the django registration redux library shows up. I've had this problem before in Django and I fixed it by placing RequestSite under 'requests' and Site under 'models'. That solved the problem but the error still shows up in Heroku.
(venv) C:\Users\Carolina\Desktop\Coding\venv\project1>heroku run python manage.p
y collectstatic --noinput
Running python manage.py collectstatic --noinput on acla-acla... up, run.3645
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/_
_init__.py", line 350, in execute_from_command_line
utility.execute()
File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/_
_init__.py", line 324, in execute
django.setup()
File "/app/.heroku/python/lib/python2.7/site-packages/django/__init__.py", lin
e 18, in setup
apps.populate(settings.INSTALLED_APPS)
File "/app/.heroku/python/lib/python2.7/site-packages/django/apps/registry.py"
, line 115, in populate
app_config.ready()
File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/admin/app
s.py", line 22, in ready
self.module.autodiscover()
File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/admin/__i
nit__.py", line 26, in autodiscover
autodiscover_modules('admin', register_to=site)
File "/app/.heroku/python/lib/python2.7/site-packages/django/utils/module_load
ing.py", line 50, in autodiscover_modules
import_module('%s.%s' % (app_config.name, module_to_search))
File "/app/.heroku/python/lib/python2.7/importlib/__init__.py", line 37, in im
port_module
__import__(name)
File "/app/.heroku/python/lib/python2.7/site-packages/registration/admin.py",
line 2, in <module>
from django.contrib.sites.models import RequestSite
ImportError: cannot import name RequestSite
The thing is - that line doesn't exist. I went to venv/lib/site-packages/registration/admin.py and line 2 is this one:
from django.contrib import admin
from django.contrib.sites.requests import RequestSite # HERE
from django.contrib.sites.models import Site
from django.utils.translation import ugettext_lazy as _
from registration.models import RegistrationProfile
from registration.users import UsernameField
class RegistrationAdmin(admin.ModelAdmin):
actions = ['activate_users', 'resend_activation_email']
list_display = ('user', 'activation_key_expired')
raw_id_fields = ['user']
search_fields = ('user__{0}'.format(UsernameField()), 'user__first_name', 'user__last_name')
def activate_users(self, request, queryset):
"""
Activates the selected users, if they are not already
activated.
"""
for profile in queryset:
RegistrationProfile.objects.activate_user(profile.activation_key)
activate_users.short_description = _("Activate users")
def resend_activation_email(self, request, queryset):
"""
Re-sends activation emails for the selected users.
Note that this will *only* send activation emails for users
who are eligible to activate; emails will not be sent to users
whose activation keys have expired or who have already
activated.
"""
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
for profile in queryset:
if not profile.activation_key_expired():
profile.send_activation_email(site)
resend_activation_email.short_description = _("Re-send activation emails")
admin.site.register(RegistrationProfile, RegistrationAdmin)
This is what I get with pip freeze, just in case:
Django==1.9
django-crispy-forms==1.5.2
django-registration==2.0.3
django-registration-redux==1.2
django-tinymce==2.2.0
Pillow==3.0.0
requests==2.9.0
South==1.0.2
stripe==1.27.1
wheel==0.24.0
Anyone knows why this is happening? Thanks in advance!
EDIT ----
Ok, so the problem was the one mentioned by Daniel Roseman. The library is broken in pypi and I had to tell heroku to install it from github (where the package is fixed).
So, I went to my requirements.txt file and replaced this line:
django-registration-redux==1.2
with this one:
-e git://github.com/macropin/django-registration.git#egg=django-registration==1.2
(I also removed 'django-registration==2.0.3' because it is an old version of django-registration-redux and was creating problems).
Hope this helps people with the same issue!
It sounds like you edited the code for your locally installed copy of django-registration-redux. But that won't have any effect on Heroku, since the library will be installed directly from PyPI, according to the version in your requirements.txt.
If the library is really broken, you will need to fork it and point your requirements.txt to your fixed version. However, looking at the code on GitHub, it doesn't actually seem to be broken; you just need to update the version you are pointing to.

Django syncdb exception after updating to 1.4

So I was developing an app in Django and needed a function from the 1.4 version so I decided to update.
But then a weird error appeared when I wanted to do syncdb
I am using the new manage.py and as You can see it makes some of the tables but then fails :
./manage.py syncdb
Creating tables ...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_user_permissions
Creating table auth_user_groups
Creating table auth_user
Creating table django_content_type
Creating table django_session
Creating table django_site
Traceback (most recent call last):
File "./manage.py", line 9, in <module>
execute_from_command_line(sys.argv)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/django/core/management/__init__.py", line 443, in execute_from_command_line
utility.execute()
File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/django/core/management/__init__.py", line 382, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/django/core/management/base.py", line 196, in run_from_argv
self.execute(*args, **options.__dict__)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/django/core/management/base.py", line 232, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/django/core/management/base.py", line 371, in handle
return self.handle_noargs(**options)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/django/core/management/commands/syncdb.py", line 91, in handle_noargs
sql, references = connection.creation.sql_create_model(model, self.style, seen_models)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/django/db/backends/creation.py", line 44, in sql_create_model
col_type = f.db_type(connection=self.connection)
TypeError: db_type() got an unexpected keyword argument 'connection'
I had the same issue, the definition for my custom field was missing the connection parameter.
from django.db import models
class BigIntegerField(models.IntegerField):
def db_type(self, connection):
return "bigint"
Although already old, answered and accepted question but I am adding my understanding I have added it because I am not using customized type and it is a Django Evolution error (but not syncdb)evolve --hint --execute. I think it may be helpful for someone in future. .
I am average in Python and new to Django. I also encounter same issue when I added some new features to my existing project. To add new feature I had to add some new fields of models.CharField() type,as follows.
included_domains = models.CharField(
"set of comma(,) seprated list of domains in target emails",
default="",
max_length=it_len.EMAIL_LEN*5)
excluded_domains = models.CharField(
"set of comma(,) seprated list of domains NOT in target emails",
default="",
max_length=it_len.EMAIL_LEN*5)
The Django version I am using is 1.3.1:
$ python -c "import django; print django.get_version()"
1.3.1 <--------# version
$python manage.py syncdb
Project signature has changed - an evolution is required
Django Evolution: Django Evolution is an extension to Django that allows you to track changes in your models over time, and to update the database to reflect those changes.
$ python manage.py evolve --hint
#----- Evolution for messagingframework
from django_evolution.mutations import AddField
from django.db import models
MUTATIONS = [
AddField('MessageConfiguration', 'excluded_domains', models.CharField, initial=u'', max_length=300),
AddField('MessageConfiguration', 'included_domains', models.CharField, initial=u'', max_length=300)
]
#----------------------
Trial evolution successful.
Run './manage.py evolve --hint --execute' to apply evolution.
The trial was susses and when I tried to apply changes in DB
$ python manage.py evolve --hint --execute
Traceback (most recent call last):
File "manage.py", line 25, in <module>
execute_manager(settings)
File "/var/www/sites/www.taxspanner.com/django/core/management/__init__.py", line 362, in execute_manager
utility.execute()
File "/var/www/sites/www.taxspanner.com/django/core/management/__init__.py", line 303, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/var/www/sites/www.taxspanner.com/django/core/management/base.py", line 195, in run_from_argv
self.execute(*args, **options.__dict__)
File "/var/www/sites/www.taxspanner.com/django/core/management/base.py", line 222, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/python2.7/dist-packages/django_evolution-0.6.9.dev_r225-py2.7.egg/django_evolution/management/commands/evolve.py", line 60, in handle
self.evolve(*app_labels, **options)
File "/usr/local/lib/python2.7/dist-packages/django_evolution-0.6.9.dev_r225-py2.7.egg/django_evolution/management/commands/evolve.py", line 140, in evolve
database))
File "/usr/local/lib/python2.7/dist-packages/django_evolution-0.6.9.dev_r225-py2.7.egg/django_evolution/mutations.py", line 426, in mutate
return self.add_column(app_label, proj_sig, database)
File "/usr/local/lib/python2.7/dist-packages/django_evolution-0.6.9.dev_r225-py2.7.egg/django_evolution/mutations.py", line 438, in add_column
sql_statements = evolver.add_column(model, field, self.initial)
File "/usr/local/lib/python2.7/dist-packages/django_evolution-0.6.9.dev_r225-py2.7.egg/django_evolution/db/common.py", line 142, in add_column
f.db_type(connection=self.connection), # <=== here f is field class object
TypeError: db_type() got an unexpected keyword argument 'connection'
To understand this exception I check that this exception is something similar to:
>>> def f(a):
... print a
...
>>> f('b', b='a')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() got an unexpected keyword argument 'b'
>>>
So the function signature has been changed.
Because I have not added any new customized or enum fields but only two similar fields that was already in model and char type field is supported by most of database (I am ussing PostgreSQL) even I was getting this error!
Then I read from #: Russell Keith-Magee-4 Reply.
What you've hit here is the end of the deprecation cycle for code that
doesn't support multiple databases.
In Django 1.2, we introduced multiple database support; in order to
support this, the prototype for get_db_preb_lookup() and
get_db_prep_value() was changed.
For backwards compatibility, we added a shim that would transparently
'fix' these methods if they hadn't already been fixed by the
developer.
In Django 1.2, the usage of these shims raised a
PendingDeprecationWarning. In Django 1.3, they raised a
DeprecationWarning.
Under Django 1.4, the shim code was been removed -- so any code that
wasn't updated will now raise errors like the one you describe.
But I am not getting any DeprecationWarning warning assuming because of newer version of Django Evolution.
But from above quote I could understand that to support multiple databases function signature is added and an extra argument connection is needed. I also check the db_type() signature in my installation of Django as follows:
/django$ grep --exclude-dir=".svn" -n 'def db_type(' * -R
contrib/localflavor/us/models.py:8: def db_type(self):
contrib/localflavor/us/models.py:24: def db_type(self):
:
:
Ialso refer of Django documentation
Field.db_type(self, connection):
Returns the database column data type for the Field, taking into account the connection
object, and the settings associated with it.
And Then I could understand that to resolve this issue I have to inherited models.filed class and overwrite def db_type() function. And because I am using PostgreSQL in which to create 300 chars type field I need to return 'char(300)'. In my models.py I added:
class CharMaxlengthN(models.Field):
def db_type(self, connection):
return 'char(%d)' % self.max_length # because I am using postgresql
If you encounter similar problem please check your underline DB's manual that which type of column you need to create and return a string.
And changed the definition of new fields (that I need to add) read comments:
included_domains = CharMaxlengthN( # <--Notice change
"set of comma(,) seprated list of domains in target emails",
default="",
max_length=it_len.EMAIL_LEN*5)
excluded_domains = CharMaxlengthN( # <-- Notice change
"set of comma(,) seprated list of domains NOT in target emails",
default="",
max_length=it_len.EMAIL_LEN*5)
Then I executed same command that was failing previously:
t$ python manage.py evolve --hint --execute
You have requested a database evolution. This will alter tables
and data currently in the None database, and may result in
IRREVERSABLE DATA LOSS. Evolutions should be *thoroughly* reviewed
prior to execution.
Are you sure you want to execute the evolutions?
Type 'yes' to continue, or 'no' to cancel: yes
Evolution successful.
I also check my DB and tested my new added features It is now working perfectly, and no DB problem.
If you wants to create ENUM field read Specifying a mySQL ENUM in a Django model.
Edit: I realized instead of sub classing models.Field I should have inherit more specific subclass that is models.CharField.
Similarly I need to create Decimal DB fields so I added following class in model:
class DecimalField(models.DecimalField):
def db_type(self, connection):
d = {
'max_digits': self.max_digits,
'decimal_places': self.decimal_places,
}
return 'numeric(%(max_digits)s, %(decimal_places)s)' % d

Django unittests: The model is already registered Error

I come across several problems while trying django unittests library. Something strange happens:
I defined the test like this:
from django.core import management
from django.test import TestCase
from django.test.client import Client
from django.core import mail
from django.test.utils import setup_test_environment
from django.contrib.auth.models import User
from django.db import connection
from goserver.models import ActiveList
class GoserverTestCase(TestCase):
#fixtures = ['dat.json']
def setUp(self):
pass
def test_active_list_works(self):
c = Client()
response = c.post('/')
#print response.status_code
self.assertEquals(True, True)
But after the execution of the code it returns following error:
---------------------------------------------------------------------- Unit Test Code Coverage Results
---------------------------------------------------------------------- Traceback (most recent call last): File "manage.py", line 11, in <module>
execute_manager(settings) File "/opt/local/lib/python2.5/site-packages/Django-1.0.2_final-py2.5.egg/django/core/management/__init__.py", line 340, in execute_manager
utility.execute() File "/opt/local/lib/python2.5/site-packages/Django-1.0.2_final-py2.5.egg/django/core/management/__init__.py", line 295, in execute
self.fetch_command(subcommand).run_from_argv(self.argv) File "/opt/local/lib/python2.5/site-packages/Django-1.0.2_final-py2.5.egg/django/core/management/base.py", line 192, in run_from_argv
self.execute(*args, **options.__dict__) File "/opt/local/lib/python2.5/site-packages/Django-1.0.2_final-py2.5.egg/django/core/management/base.py", line 219, in execute
output = self.handle(*args, **options) File "/opt/local/lib/python2.5/site-packages/Django-1.0.2_final-py2.5.egg/django/core/management/commands/test.py", line 33, in handle
failures = test_runner(test_labels, verbosity=verbosity, interactive=interactive) File "/opt/local/lib/python2.5/site-packages/django_test_coverage-0.1-py2.5.egg/django-test-coverage/runner.py", line 58, in run_tests
modules.extend(_package_modules(*pkg)) File "/opt/local/lib/python2.5/site-packages/django_test_coverage-0.1-py2.5.egg/django-test-coverage/runner.py", line 92, in _package_modules
modules.append(__import__(impstr + '.' + name, {}, {}, [''])) File "/Users/oleg/jin/goclub/trunk/jin/goserver/admin.py", line 11, in <module>
admin.site.register(ActiveList, ActiveListAdmin) File "/opt/local/lib/python2.5/site-packages/Django-1.0.2_final-py2.5.egg/django/contrib/admin/sites.py", line 64, in register
raise AlreadyRegistered('The model %s is already registered' % model.__name__) django.contrib.admin.sites.AlreadyRegistered: The model ActiveList is already registered silver:jin oleg$
Admin file looks like this:
from goserver.models import ActiveList, Game
from django.contrib import admin
class ActiveListAdmin(admin.ModelAdmin):
list_display = ('user', "is_Bot", "isActive")
admin.site.register(ActiveList, ActiveListAdmin)
admin.site.register(Game)
I run it all this way:
python manage.py test goserver
Also noticed that if I remove lines
c = Client()
response = c.post('/')
from a test case definition, then no error appears
Looking at the traceback, it looks like you have an app called django_test_coverage-0.1 which is importing your app's admin.py.
It is probably importing it from a different location, such as yourproject.yourapp.admin as opposed to yourapp.admin. Since it's technically seen as a different module, it is re-imported and the admin.site.register calls are made again. This causes the AlreadyRegistered error.
My suggestion would be to remove django_test_coverage app (or fix it).
My questions,
I don't see what is base type/class for TestCase - is it Django Test one, or from Unittest?
it is better to use from Django
How are you runnig test? using Django internal test command, by nose, by unittest? By Traceback I thing test command, but I am not quite sure.
What is you definitions for ActiveAdminList and ActiveList? Have you got maybe class Admin in Meta?
I solve this commenting the admin.autodiscover() line in the proye