mirror of https://github.com/django/django.git
Removed support for custom SQL per deprecation timeline.
This commit is contained in:
parent
a420f83e7d
commit
4aa089a9a9
|
@ -233,7 +233,7 @@ class ManagementUtility(object):
|
|||
subcommand_cls = self.fetch_command(cwords[0])
|
||||
# special case: add the names of installed apps to options
|
||||
if cwords[0] in ('dumpdata', 'sql', 'sqlall', 'sqlclear',
|
||||
'sqlcustom', 'sqlindexes', 'sqlmigrate', 'sqlsequencereset', 'test'):
|
||||
'sqlindexes', 'sqlmigrate', 'sqlsequencereset', 'test'):
|
||||
try:
|
||||
app_configs = apps.get_app_configs()
|
||||
# Get the last part of the dotted path as the app name.
|
||||
|
|
|
@ -45,9 +45,6 @@ class Command(BaseCommand):
|
|||
"Django to create, modify, and delete the table"
|
||||
)
|
||||
yield "# Feel free to rename the models, but don't rename db_table values or field names."
|
||||
yield "#"
|
||||
yield "# Also note: You'll have to insert the output of 'django-admin sqlcustom [app_label]'"
|
||||
yield "# into your database."
|
||||
yield "from __future__ import unicode_literals"
|
||||
yield ''
|
||||
yield 'from %s import models' % self.db_module
|
||||
|
|
|
@ -4,14 +4,12 @@ from __future__ import unicode_literals
|
|||
from collections import OrderedDict
|
||||
from importlib import import_module
|
||||
import time
|
||||
import traceback
|
||||
import warnings
|
||||
|
||||
from django.apps import apps
|
||||
from django.core.management import call_command
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.core.management.color import no_style
|
||||
from django.core.management.sql import custom_sql_for_model, emit_post_migrate_signal, emit_pre_migrate_signal
|
||||
from django.core.management.sql import emit_post_migrate_signal, emit_pre_migrate_signal
|
||||
from django.db import connections, router, transaction, DEFAULT_DB_ALIAS
|
||||
from django.db.migrations.executor import MigrationExecutor
|
||||
from django.db.migrations.loader import AmbiguityError
|
||||
|
@ -47,7 +45,6 @@ class Command(BaseCommand):
|
|||
|
||||
self.verbosity = options.get('verbosity')
|
||||
self.interactive = options.get('interactive')
|
||||
self.show_traceback = options.get('traceback')
|
||||
|
||||
# Import the 'management' module within each installed app, to register
|
||||
# dispatcher events.
|
||||
|
@ -73,7 +70,7 @@ class Command(BaseCommand):
|
|||
no_color=options.get('no_color'),
|
||||
settings=options.get('settings'),
|
||||
stdout=self.stdout,
|
||||
traceback=self.show_traceback,
|
||||
traceback=options.get('traceback'),
|
||||
verbosity=self.verbosity,
|
||||
)
|
||||
|
||||
|
@ -167,18 +164,6 @@ class Command(BaseCommand):
|
|||
self.stdout.write(self.style.MIGRATE_HEADING("Synchronizing apps without migrations:"))
|
||||
self.sync_apps(connection, executor.loader.unmigrated_apps)
|
||||
|
||||
# The test runner requires us to flush after a syncdb but before migrations,
|
||||
# so do that here.
|
||||
if options.get("test_flush", False):
|
||||
call_command(
|
||||
'flush',
|
||||
verbosity=max(self.verbosity - 1, 0),
|
||||
interactive=False,
|
||||
database=db,
|
||||
reset_sequences=False,
|
||||
inhibit_post_migrate=True,
|
||||
)
|
||||
|
||||
# Migrate!
|
||||
if self.verbosity >= 1:
|
||||
self.stdout.write(self.style.MIGRATE_HEADING("Running migrations:"))
|
||||
|
@ -299,41 +284,4 @@ class Command(BaseCommand):
|
|||
finally:
|
||||
cursor.close()
|
||||
|
||||
# The connection may have been closed by a syncdb handler.
|
||||
cursor = connection.cursor()
|
||||
try:
|
||||
# Install custom SQL for the app (but only if this
|
||||
# is a model we've just created)
|
||||
if self.verbosity >= 1:
|
||||
self.stdout.write(" Installing custom SQL...\n")
|
||||
for app_name, model_list in manifest.items():
|
||||
for model in model_list:
|
||||
if model in created_models:
|
||||
custom_sql = custom_sql_for_model(model, no_style(), connection)
|
||||
if custom_sql:
|
||||
if self.verbosity >= 2:
|
||||
self.stdout.write(
|
||||
" Installing custom SQL for %s.%s model\n" %
|
||||
(app_name, model._meta.object_name)
|
||||
)
|
||||
try:
|
||||
with transaction.atomic(using=connection.alias):
|
||||
for sql in custom_sql:
|
||||
cursor.execute(sql)
|
||||
except Exception as e:
|
||||
self.stderr.write(
|
||||
" Failed to install custom SQL for %s.%s model: %s\n"
|
||||
% (app_name, model._meta.object_name, e)
|
||||
)
|
||||
if self.show_traceback:
|
||||
traceback.print_exc()
|
||||
else:
|
||||
if self.verbosity >= 3:
|
||||
self.stdout.write(
|
||||
" No custom SQL for %s.%s model\n" %
|
||||
(app_name, model._meta.object_name)
|
||||
)
|
||||
finally:
|
||||
cursor.close()
|
||||
|
||||
return created_models
|
||||
|
|
|
@ -6,7 +6,7 @@ from django.db import connections, DEFAULT_DB_ALIAS
|
|||
|
||||
|
||||
class Command(AppCommand):
|
||||
help = "Prints the CREATE TABLE, custom SQL and CREATE INDEX SQL statements for the given model module name(s)."
|
||||
help = "Prints the CREATE TABLE and CREATE INDEX SQL statements for the given model module name(s)."
|
||||
|
||||
output_transaction = True
|
||||
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.core.management.base import AppCommand
|
||||
from django.core.management.sql import sql_custom
|
||||
from django.db import connections, DEFAULT_DB_ALIAS
|
||||
|
||||
|
||||
class Command(AppCommand):
|
||||
help = "Prints the custom table modifying SQL statements for the given app name(s)."
|
||||
|
||||
output_transaction = True
|
||||
|
||||
def add_arguments(self, parser):
|
||||
super(Command, self).add_arguments(parser)
|
||||
parser.add_argument('--database', default=DEFAULT_DB_ALIAS,
|
||||
help='Nominates a database to print the SQL for. Defaults to the '
|
||||
'"default" database.')
|
||||
|
||||
def handle_app_config(self, app_config, **options):
|
||||
if app_config.models_module is None:
|
||||
return
|
||||
connection = connections[options['database']]
|
||||
statements = sql_custom(app_config, self.style, connection)
|
||||
return '\n'.join(statements)
|
|
@ -1,15 +1,10 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import warnings
|
||||
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
from django.core.management.base import CommandError
|
||||
from django.db import models, router
|
||||
from django.utils.deprecation import RemovedInDjango19Warning
|
||||
from django.utils.version import get_docs_version
|
||||
|
||||
|
||||
|
@ -140,21 +135,6 @@ def sql_flush(style, connection, only_django=False, reset_sequences=True, allow_
|
|||
return statements
|
||||
|
||||
|
||||
def sql_custom(app_config, style, connection):
|
||||
"Returns a list of the custom table modifying SQL statements for the given app."
|
||||
|
||||
check_for_migrations(app_config, connection)
|
||||
|
||||
output = []
|
||||
|
||||
app_models = router.get_migratable_models(app_config, connection.alias)
|
||||
|
||||
for model in app_models:
|
||||
output.extend(custom_sql_for_model(model, style, connection))
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def sql_indexes(app_config, style, connection):
|
||||
"Returns a list of the CREATE INDEX SQL statements for all models in the given app."
|
||||
|
||||
|
@ -184,7 +164,6 @@ def sql_all(app_config, style, connection):
|
|||
"Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module."
|
||||
return (
|
||||
sql_create(app_config, style, connection) +
|
||||
sql_custom(app_config, style, connection) +
|
||||
sql_indexes(app_config, style, connection)
|
||||
)
|
||||
|
||||
|
@ -205,43 +184,6 @@ def _split_statements(content):
|
|||
return statements
|
||||
|
||||
|
||||
def custom_sql_for_model(model, style, connection):
|
||||
opts = model._meta
|
||||
app_dirs = []
|
||||
app_dir = apps.get_app_config(model._meta.app_label).path
|
||||
app_dirs.append(os.path.normpath(os.path.join(app_dir, 'sql')))
|
||||
|
||||
# Deprecated location -- remove in Django 1.9
|
||||
old_app_dir = os.path.normpath(os.path.join(app_dir, 'models/sql'))
|
||||
if os.path.exists(old_app_dir):
|
||||
warnings.warn("Custom SQL location '<app_label>/models/sql' is "
|
||||
"deprecated, use '<app_label>/sql' instead.",
|
||||
RemovedInDjango19Warning)
|
||||
app_dirs.append(old_app_dir)
|
||||
|
||||
output = []
|
||||
|
||||
# Post-creation SQL should come before any initial SQL data is loaded.
|
||||
# However, this should not be done for models that are unmanaged or
|
||||
# for fields that are part of a parent model (via model inheritance).
|
||||
if opts.managed:
|
||||
post_sql_fields = [f for f in opts.local_fields if hasattr(f, 'post_create_sql')]
|
||||
for f in post_sql_fields:
|
||||
output.extend(f.post_create_sql(style, model._meta.db_table))
|
||||
|
||||
# Find custom SQL, if it's available.
|
||||
backend_name = connection.settings_dict['ENGINE'].split('.')[-1]
|
||||
sql_files = []
|
||||
for app_dir in app_dirs:
|
||||
sql_files.append(os.path.join(app_dir, "%s.%s.sql" % (opts.model_name, backend_name)))
|
||||
sql_files.append(os.path.join(app_dir, "%s.sql" % opts.model_name))
|
||||
for sql_file in sql_files:
|
||||
if os.path.exists(sql_file):
|
||||
with io.open(sql_file, encoding=settings.FILE_CHARSET) as fp:
|
||||
output.extend(connection.ops.prepare_sql_script(fp.read(), _allow_fallback=True))
|
||||
return output
|
||||
|
||||
|
||||
def emit_pre_migrate_signal(verbosity, interactive, db):
|
||||
# Emit the pre_migrate signal for every application.
|
||||
for app_config in apps.get_app_configs():
|
||||
|
|
|
@ -366,7 +366,6 @@ class BaseDatabaseCreation(object):
|
|||
verbosity=max(verbosity - 1, 0),
|
||||
interactive=False,
|
||||
database=self.connection.alias,
|
||||
test_flush=True,
|
||||
)
|
||||
|
||||
# We then serialize the current state of the database into a string
|
||||
|
|
|
@ -3,15 +3,7 @@ Providing initial data for models
|
|||
=================================
|
||||
|
||||
It's sometimes useful to pre-populate your database with hard-coded data when
|
||||
you're first setting up an app. There's a couple of ways you can have Django
|
||||
automatically create this data: you can provide `initial data via fixtures`_, or
|
||||
you can provide `initial data as SQL`_.
|
||||
|
||||
In general, using a fixture is a cleaner method since it's database-agnostic,
|
||||
but initial SQL is also quite a bit more flexible.
|
||||
|
||||
.. _initial data as sql: `providing initial sql data`_
|
||||
.. _initial data via fixtures: `providing initial data with fixtures`_
|
||||
you're first setting up an app. You can provide initial data via fixtures.
|
||||
|
||||
.. _initial-data-via-fixtures:
|
||||
|
||||
|
@ -91,77 +83,3 @@ directories.
|
|||
|
||||
Fixtures are also used by the :ref:`testing framework
|
||||
<topics-testing-fixtures>` to help set up a consistent test environment.
|
||||
|
||||
.. _initial-sql:
|
||||
|
||||
Providing initial SQL data
|
||||
==========================
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
If an application uses migrations, there is no loading of initial SQL data
|
||||
(including backend-specific SQL data). Since migrations will be required
|
||||
for applications in Django 1.9, this behavior is considered deprecated.
|
||||
If you want to use initial SQL for an app, consider doing it in a
|
||||
:ref:`data migration <data-migrations>`.
|
||||
|
||||
Django provides a hook for passing the database arbitrary SQL that's executed
|
||||
just after the CREATE TABLE statements when you run :djadmin:`migrate`. You can
|
||||
use this hook to populate default records, or you could also create SQL
|
||||
functions, views, triggers, etc.
|
||||
|
||||
The hook is simple: Django just looks for a file called ``sql/<modelname>.sql``,
|
||||
in your app directory, where ``<modelname>`` is the model's name in lowercase.
|
||||
|
||||
So, if you had a ``Person`` model in an app called ``myapp``, you could add
|
||||
arbitrary SQL to the file ``sql/person.sql`` inside your ``myapp`` directory.
|
||||
Here's an example of what the file might contain:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
INSERT INTO myapp_person (first_name, last_name) VALUES ('John', 'Lennon');
|
||||
INSERT INTO myapp_person (first_name, last_name) VALUES ('Paul', 'McCartney');
|
||||
|
||||
Each SQL file, if given, is expected to contain valid SQL statements
|
||||
which will insert the desired data (e.g., properly-formatted
|
||||
``INSERT`` statements separated by semicolons).
|
||||
|
||||
The SQL files are read by the :djadmin:`sqlcustom` and :djadmin:`sqlall`
|
||||
commands in :doc:`manage.py </ref/django-admin>`. Refer to the :doc:`manage.py
|
||||
documentation </ref/django-admin>` for more information.
|
||||
|
||||
Note that if you have multiple SQL data files, there's no guarantee of
|
||||
the order in which they're executed. The only thing you can assume is
|
||||
that, by the time your custom data files are executed, all the
|
||||
database tables already will have been created.
|
||||
|
||||
.. admonition:: Initial SQL data and testing
|
||||
|
||||
This technique *cannot* be used to provide initial data for
|
||||
testing purposes. Django's test framework flushes the contents of
|
||||
the test database after each test; as a result, any data added
|
||||
using the custom SQL hook will be lost.
|
||||
|
||||
If you require data for a test case, you should add it using
|
||||
either a :ref:`test fixture <topics-testing-fixtures>`, or
|
||||
programmatically add it during the ``setUp()`` of your test case.
|
||||
|
||||
Database-backend-specific SQL data
|
||||
----------------------------------
|
||||
|
||||
There's also a hook for backend-specific SQL data. For example, you
|
||||
can have separate initial-data files for PostgreSQL and SQLite. For
|
||||
each app, Django looks for a file called
|
||||
``<app_label>/sql/<modelname>.<backend>.sql``, where ``<app_label>`` is
|
||||
your app directory, ``<modelname>`` is the model's name in lowercase
|
||||
and ``<backend>`` is the last part of the module name provided for the
|
||||
:setting:`ENGINE <DATABASE-ENGINE>` in your settings file (e.g., if you have
|
||||
defined a database with an :setting:`ENGINE <DATABASE-ENGINE>` value of
|
||||
``django.db.backends.sqlite3``, Django will look for
|
||||
``<app_label>/sql/<modelname>.sqlite3.sql``).
|
||||
|
||||
Backend-specific SQL data is executed before non-backend-specific SQL
|
||||
data. For example, if your app contains the files ``sql/person.sql``
|
||||
and ``sql/person.sqlite3.sql`` and you're installing the app on
|
||||
SQLite, Django will execute the contents of
|
||||
``sql/person.sqlite3.sql`` first, then ``sql/person.sql``.
|
||||
|
|
|
@ -543,9 +543,7 @@ Now, run :djadmin:`migrate` again to create those model tables in your database:
|
|||
Apply all migrations: polls
|
||||
Synchronizing apps without migrations:
|
||||
Creating tables...
|
||||
Installing custom SQL...
|
||||
Installing indexes...
|
||||
Installed 0 object(s) from 0 fixture(s)
|
||||
Running migrations:
|
||||
Applying polls.0001_initial... OK
|
||||
|
||||
|
|
|
@ -84,9 +84,6 @@ given model module name(s).
|
|||
.BI "sqlclear [" "app_label ..." "]"
|
||||
Prints the DROP TABLE SQL statements for the given app name(s).
|
||||
.TP
|
||||
.BI "sqlcustom [" "app_label ..." "]"
|
||||
Prints the custom SQL statements for the given app name(s).
|
||||
.TP
|
||||
.BI "sqlflush [" "app_label ..." "]"
|
||||
Prints the SQL statements that would be executed for the "flush" command.
|
||||
.TP
|
||||
|
|
|
@ -989,9 +989,6 @@ sqlall <app_label app_label ...>
|
|||
|
||||
Prints the CREATE TABLE and initial-data SQL statements for the given app name(s).
|
||||
|
||||
Refer to the description of :djadmin:`sqlcustom` for an explanation of how to
|
||||
specify initial data.
|
||||
|
||||
The :djadminopt:`--database` option can be used to specify the database for
|
||||
which to print the SQL.
|
||||
|
||||
|
@ -1012,30 +1009,6 @@ Prints the DROP TABLE SQL statements for the given app name(s).
|
|||
The :djadminopt:`--database` option can be used to specify the database for
|
||||
which to print the SQL.
|
||||
|
||||
sqlcustom <app_label app_label ...>
|
||||
-----------------------------------
|
||||
|
||||
.. django-admin:: sqlcustom
|
||||
|
||||
Prints the custom SQL statements for the given app name(s).
|
||||
|
||||
For each model in each specified app, this command looks for the file
|
||||
``<app_label>/sql/<modelname>.sql``, where ``<app_label>`` is the given app
|
||||
name and ``<modelname>`` is the model's name in lowercase. For example, if you
|
||||
have an app ``news`` that includes a ``Story`` model, ``sqlcustom`` will
|
||||
attempt to read a file ``news/sql/story.sql`` and append it to the output of
|
||||
this command.
|
||||
|
||||
Each of the SQL files, if given, is expected to contain valid SQL. The SQL
|
||||
files are piped directly into the database after all of the models'
|
||||
table-creation statements have been executed. Use this SQL hook to make any
|
||||
table modifications, or insert any SQL functions into the database.
|
||||
|
||||
Note that the order in which the SQL files are processed is undefined.
|
||||
|
||||
The :djadminopt:`--database` option can be used to specify the database for
|
||||
which to print the SQL.
|
||||
|
||||
sqldropindexes <app_label app_label ...>
|
||||
----------------------------------------
|
||||
|
||||
|
|
|
@ -1295,8 +1295,7 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in
|
|||
|
||||
Take no action. If your database backend enforces referential
|
||||
integrity, this will cause an :exc:`~django.db.IntegrityError` unless
|
||||
you manually add an SQL ``ON DELETE`` constraint to the database field
|
||||
(perhaps using :ref:`initial sql<initial-sql>`).
|
||||
you manually add an SQL ``ON DELETE`` constraint to the database field.
|
||||
|
||||
.. attribute:: ForeignKey.swappable
|
||||
|
||||
|
|
|
@ -738,7 +738,7 @@ Management Commands
|
|||
* :djadmin:`collectstatic` command with symlink option is now supported on
|
||||
Windows NT 6 (Windows Vista and newer).
|
||||
|
||||
* :ref:`initial-sql` now works better if the sqlparse_ Python library is
|
||||
* Initial SQL data now works better if the sqlparse_ Python library is
|
||||
installed.
|
||||
|
||||
Note that it's deprecated in favor of the
|
||||
|
@ -1517,8 +1517,8 @@ Custom SQL location for models package
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Previously, if models were organized in a package (``myapp/models/``) rather
|
||||
than simply ``myapp/models.py``, Django would look for :ref:`initial SQL data
|
||||
<initial-sql>` in ``myapp/models/sql/``. This bug has been fixed so that Django
|
||||
than simply ``myapp/models.py``, Django would look for initial SQL data in
|
||||
``myapp/models/sql/``. This bug has been fixed so that Django
|
||||
will search ``myapp/sql/`` as documented. After this issue was fixed, migrations
|
||||
were added which deprecates initial SQL data. Thus, while this change still
|
||||
exists, the deprecation is irrelevant as the entire feature will be removed in
|
||||
|
|
|
@ -585,7 +585,6 @@ Springmeyer
|
|||
sql
|
||||
sqlall
|
||||
sqlclear
|
||||
sqlcustom
|
||||
sqldropindexes
|
||||
sqlflush
|
||||
sqlindexes
|
||||
|
|
|
@ -140,9 +140,7 @@ database to make sure they work as expected::
|
|||
Apply all migrations: books
|
||||
Synchronizing apps without migrations:
|
||||
Creating tables...
|
||||
Installing custom SQL...
|
||||
Installing indexes...
|
||||
Installed 0 object(s) from 0 fixture(s)
|
||||
Running migrations:
|
||||
Applying books.0003_auto... OK
|
||||
|
||||
|
|
|
@ -984,15 +984,6 @@ The most straightforward way of creating a fixture is to use the
|
|||
already have some data in your database. See the :djadmin:`dumpdata
|
||||
documentation<dumpdata>` for more details.
|
||||
|
||||
.. admonition:: Initial SQL data and testing
|
||||
|
||||
Django provides a second way to insert initial data into models --
|
||||
the :ref:`custom SQL hook <initial-sql>`. However, this technique
|
||||
*cannot* be used to provide initial data for testing purposes.
|
||||
Django's test framework flushes the contents of the test database
|
||||
after each test; as a result, any data added using the custom SQL
|
||||
hook will be lost.
|
||||
|
||||
Once you've created a fixture and placed it in a ``fixtures`` directory in one
|
||||
of your :setting:`INSTALLED_APPS`, you can use it in your unit tests by
|
||||
specifying a ``fixtures`` class attribute on your :class:`django.test.TestCase`
|
||||
|
|
|
@ -1386,7 +1386,6 @@ class CommandTypes(AdminScriptTestCase):
|
|||
out, err = self.run_manage(args)
|
||||
self.assertNoOutput(err)
|
||||
self.assertOutput(out, "Checks the entire Django project for potential problems.")
|
||||
self.assertEqual(out.count('optional arguments'), 1)
|
||||
|
||||
def test_color_style(self):
|
||||
style = color.no_style()
|
||||
|
|
|
@ -78,7 +78,7 @@ class BashCompletionTests(unittest.TestCase):
|
|||
"Subcommands can be autocompleted"
|
||||
self._user_input('django-admin sql')
|
||||
output = self._run_autocomplete()
|
||||
self.assertEqual(output, ['sql sqlall sqlclear sqlcustom sqldropindexes sqlflush sqlindexes sqlmigrate sqlsequencereset'])
|
||||
self.assertEqual(output, ['sql sqlall sqlclear sqldropindexes sqlflush sqlindexes sqlmigrate sqlsequencereset'])
|
||||
|
||||
def test_completed_subcommand(self):
|
||||
"Show option flags in case a subcommand is completed"
|
||||
|
|
|
@ -13,10 +13,3 @@ class Article(models.Model):
|
|||
class Meta:
|
||||
app_label = 'fixtures_model_package'
|
||||
ordering = ('-pub_date', 'headline')
|
||||
|
||||
|
||||
class Book(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
|
||||
class Meta:
|
||||
ordering = ('name',)
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
-- Deprecated search path for custom SQL -- remove in Django 1.9
|
||||
INSERT INTO fixtures_model_package_book (name) VALUES ('My Deprecated Book');
|
|
@ -1 +0,0 @@
|
|||
INSERT INTO fixtures_model_package_book (name) VALUES ('My Book');
|
|
@ -4,7 +4,6 @@ import warnings
|
|||
|
||||
from django.core import management
|
||||
from django.test import TestCase
|
||||
from django.utils.six import StringIO
|
||||
|
||||
from .models import Article
|
||||
|
||||
|
@ -66,18 +65,3 @@ class FixtureTestCase(TestCase):
|
|||
],
|
||||
lambda a: a.headline,
|
||||
)
|
||||
|
||||
|
||||
class InitialSQLTests(TestCase):
|
||||
|
||||
def test_custom_sql(self):
|
||||
"""
|
||||
#14300 -- Verify that custom_sql_for_model searches `app/sql` and not
|
||||
`app/models/sql` (the old location will work until Django 1.9)
|
||||
"""
|
||||
out = StringIO()
|
||||
management.call_command("sqlcustom", "fixtures_model_package", stdout=out)
|
||||
output = out.getvalue()
|
||||
self.assertIn("INSERT INTO fixtures_model_package_book (name) VALUES ('My Book')", output)
|
||||
# value from deprecated search path models/sql (remove in Django 1.9)
|
||||
self.assertIn("Deprecated Book", output)
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
"""
|
||||
Regression tests for initial SQL insertion.
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Simple(models.Model):
|
||||
name = models.CharField(max_length=50)
|
|
@ -1,12 +0,0 @@
|
|||
-- a comment
|
||||
INSERT INTO initial_sql_regress_simple (name) VALUES ('John'); -- another comment
|
||||
INSERT INTO initial_sql_regress_simple (name) VALUES ('-- Comment Man');
|
||||
INSERT INTO initial_sql_regress_simple (name) VALUES ('Paul');
|
||||
INSERT INTO
|
||||
initial_sql_regress_simple (name) VALUES ('Ringo');
|
||||
INSERT INTO initial_sql_regress_simple (name) VALUES ('George');
|
||||
INSERT INTO initial_sql_regress_simple (name) VALUES ('Miles O''Brien');
|
||||
INSERT INTO initial_sql_regress_simple (name) VALUES ('Semicolon;Man');
|
||||
INSERT INTO initial_sql_regress_simple (name) VALUES ('"100%" of % are not placeholders');
|
||||
INSERT INTO initial_sql_regress_simple (name) VALUES ('This line has a Windows line ending');
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
from django.core.management.color import no_style
|
||||
from django.core.management.sql import custom_sql_for_model
|
||||
from django.db import connections, DEFAULT_DB_ALIAS
|
||||
from django.test import TestCase, override_settings
|
||||
|
||||
from .models import Simple
|
||||
|
||||
|
||||
class InitialSQLTests(TestCase):
|
||||
"""
|
||||
The format of the included SQL file for this test suite is important.
|
||||
It must end with a trailing newline in order to test the fix for #2161.
|
||||
"""
|
||||
|
||||
def test_initial_sql(self):
|
||||
"""
|
||||
As pointed out by #14661, test data loaded by custom SQL
|
||||
can't be relied upon; as a result, the test framework flushes the
|
||||
data contents before every test. This test validates that this has
|
||||
occurred.
|
||||
"""
|
||||
self.assertEqual(Simple.objects.count(), 0)
|
||||
|
||||
def test_custom_sql(self):
|
||||
"""
|
||||
Simulate the custom SQL loading by migrate.
|
||||
"""
|
||||
connection = connections[DEFAULT_DB_ALIAS]
|
||||
custom_sql = custom_sql_for_model(Simple, no_style(), connection)
|
||||
with connection.cursor() as cursor:
|
||||
for sql in custom_sql:
|
||||
cursor.execute(sql)
|
||||
self.assertEqual(Simple.objects.count(), 9)
|
||||
self.assertEqual(
|
||||
Simple.objects.get(name__contains='placeholders').name,
|
||||
'"100%" of % are not placeholders'
|
||||
)
|
||||
|
||||
@override_settings(DEBUG=True)
|
||||
def test_custom_sql_debug(self):
|
||||
"""
|
||||
Same test, ensure that CursorDebugWrapper doesn't alter sql loading
|
||||
(#3485).
|
||||
"""
|
||||
self.test_custom_sql()
|
Loading…
Reference in New Issue