سؤال

I manually created some tables in Postgre for a Django project. I manually created the model too. When I try to syncdb, it throws a database error and says the table already exists.

If syncdb creates the table previously, this won't happen. How does syncdb know whether it created the table or if I created the table?

هل كانت مفيدة؟

المحلول

It seems django maintains an internal cache of apps and their models. It is from here that it knows if it has already created a table for a model or not. I suppose this is why there is support for introspection, so that the models are created from existing schemas and the cache is properly populated.

From the syncdb source it is clear what the process is, for figuring out what needs to be done on syncdb:

    # Get a list of already installed *models* so that references work right.
    tables = connection.introspection.table_names()
    seen_models = connection.introspection.installed_models(tables)
    created_models = set()
    pending_references = {}

    # Build the manifest of apps and models that are to be synchronized
    all_models = [
        (app.__name__.split('.')[-2],
            [m for m in models.get_models(app, include_auto_created=True)
            if router.allow_syncdb(db, m)])
        for app in models.get_apps()
    ]

    def model_installed(model):
        opts = model._meta
        converter = connection.introspection.table_name_converter
        return not ((converter(opts.db_table) in tables) or
            (opts.auto_created and converter(opts.auto_created._meta.db_table) in tables))

    manifest = SortedDict(
        (app_name, list(filter(model_installed, model_list)))
        for app_name, model_list in all_models
    )

At each database driver, there is code to fetch the table names. This is for postgresql:

def get_table_list(self, cursor):
        "Returns a list of table names in the current database."
        cursor.execute("""
            SELECT c.relname
            FROM pg_catalog.pg_class c
            LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
            WHERE c.relkind IN ('r', 'v', '')
                AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
                AND pg_catalog.pg_table_is_visible(c.oid)""")
        return [row[0] for row in cursor.fetchall()]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top