Ticket #3390: serializer.diff

File serializer.diff, 9.0 KB (added by russellm, 9 years ago)

Fix for circular/forward deserializer references

  • django/db/backends/ado_mssql/base.py

     
    125125def get_random_function_sql():
    126126    return "RAND()"
    127127
     128def get_deferrable_sql():
     129    return " DEFERRABLE INITIALLY DEFERRED"
     130
    128131def get_fulltext_search_sql(field_name):
    129132    raise NotImplementedError
    130133
  • django/db/backends/postgresql/base.py

     
    136136def get_random_function_sql():
    137137    return "RANDOM()"
    138138
     139def get_deferrable_sql():
     140    return " DEFERRABLE INITIALLY DEFERRED"
     141   
    139142def get_fulltext_search_sql(field_name):
    140143    raise NotImplementedError
    141144
  • django/db/backends/sqlite3/base.py

     
    139139def get_random_function_sql():
    140140    return "RANDOM()"
    141141
     142def get_deferrable_sql():
     143    return ""
     144
    142145def get_fulltext_search_sql(field_name):
    143146    raise NotImplementedError
    144147
  • django/db/backends/mysql/base.py

     
    174174def get_random_function_sql():
    175175    return "RAND()"
    176176
     177def get_deferrable_sql():
     178    return ""
     179
    177180def get_fulltext_search_sql(field_name):
    178181    return 'MATCH (%s) AGAINST (%%s IN BOOLEAN MODE)' % field_name
    179182
  • django/db/backends/oracle/base.py

     
    108108def get_random_function_sql():
    109109    return "DBMS_RANDOM.RANDOM"
    110110
     111def get_deferrable_sql():
     112    return " DEFERRABLE INITIALLY DEFERRED"
     113
    111114def get_fulltext_search_sql(field_name):
    112115    raise NotImplementedError
    113116
  • django/db/backends/postgresql_psycopg2/base.py

     
    9696def get_random_function_sql():
    9797    return "RANDOM()"
    9898
     99def get_deferrable_sql():
     100    return " DEFERRABLE INITIALLY DEFERRED"
     101
    99102def get_fulltext_search_sql(field_name):
    100103    raise NotImplementedError
    101104
  • django/db/backends/dummy/base.py

     
    3636get_date_trunc_sql = complain
    3737get_limit_offset_sql = complain
    3838get_random_function_sql = complain
     39get_deferrable_sql = complain
    3940get_fulltext_search_sql = complain
    4041get_drop_foreignkey_sql = complain
    4142OPERATOR_MAPPING = {}
  • django/core/serializers/python.py

     
    7272                pks = []
    7373                for pk in field_value:
    7474                    if isinstance(pk, unicode):
    75                         pk = pk.encode(options.get("encoding", settings.DEFAULT_CHARSET))
    76                 m2m_data[field.name] = field.rel.to._default_manager.in_bulk(field_value).values()
     75                        pks.append(pk.encode(options.get("encoding", settings.DEFAULT_CHARSET)))
     76                    else:
     77                        pks.append(pk)
     78                m2m_data[field.name] = pks
    7779               
    7880            # Handle FK fields
    79             elif field.rel and isinstance(field.rel, models.ManyToOneRel) and field_value is not None:
    80                 try:
    81                     data[field.name] = field.rel.to._default_manager.get(pk=field_value)
    82                 except field.rel.to.DoesNotExist:
    83                     data[field.name] = None
     81            elif field.rel and isinstance(field.rel, models.ManyToOneRel):
     82                data[field.attname] = field_value
    8483                   
    8584            # Handle all other fields
    8685            else:
  • django/core/management.py

     
    167167                if f.rel.to in known_models:
    168168                    field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \
    169169                        style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)) + ' (' + \
    170                         style.SQL_FIELD(backend.quote_name(f.rel.to._meta.get_field(f.rel.field_name).column)) + ')'
     170                        style.SQL_FIELD(backend.quote_name(f.rel.to._meta.get_field(f.rel.field_name).column)) + ')' +
     171                        backend.get_deferrable_sql()
    171172                    )
    172173                else:
    173174                    # We haven't yet created the table to which this field
     
    210211                # For MySQL, r_name must be unique in the first 64 characters.
    211212                # So we are careful with character usage here.
    212213                r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table))))
    213                 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \
     214                final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \
    214215                    (backend.quote_name(r_table), r_name,
    215                     backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col)))
     216                    backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col),
     217                    backend.get_deferrable_sql()))
    216218            del pending_references[model]
    217219    return final_output
    218220
     
    232234                (style.SQL_FIELD(backend.quote_name('id')),
    233235                style.SQL_COLTYPE(data_types['AutoField']),
    234236                style.SQL_KEYWORD('NOT NULL PRIMARY KEY')))
    235             table_output.append('    %s %s %s %s (%s),' % \
     237            table_output.append('    %s %s %s %s (%s)%s,' % \
    236238                (style.SQL_FIELD(backend.quote_name(f.m2m_column_name())),
    237239                style.SQL_COLTYPE(data_types[get_rel_data_type(opts.pk)] % opts.pk.__dict__),
    238240                style.SQL_KEYWORD('NOT NULL REFERENCES'),
    239241                style.SQL_TABLE(backend.quote_name(opts.db_table)),
    240                 style.SQL_FIELD(backend.quote_name(opts.pk.column))))
    241             table_output.append('    %s %s %s %s (%s),' % \
     242                style.SQL_FIELD(backend.quote_name(opts.pk.column)),
     243                backend.get_deferrable_sql()))
     244            table_output.append('    %s %s %s %s (%s)%s,' % \
    242245                (style.SQL_FIELD(backend.quote_name(f.m2m_reverse_name())),
    243246                style.SQL_COLTYPE(data_types[get_rel_data_type(f.rel.to._meta.pk)] % f.rel.to._meta.pk.__dict__),
    244247                style.SQL_KEYWORD('NOT NULL REFERENCES'),
    245248                style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)),
    246                 style.SQL_FIELD(backend.quote_name(f.rel.to._meta.pk.column))))
     249                style.SQL_FIELD(backend.quote_name(f.rel.to._meta.pk.column)),
     250                backend.get_deferrable_sql()))
    247251            table_output.append('    %s (%s, %s)' % \
    248252                (style.SQL_KEYWORD('UNIQUE'),
    249253                style.SQL_FIELD(backend.quote_name(f.m2m_column_name())),
  • tests/modeltests/serializers/models.py

     
    139139...     print obj
    140140<DeserializedObject: Profile of Joe>
    141141
     142# Objects ids can be referenced before they are defined in the serialization data
     143# However, the deserialization process will need to be contained within a transaction
     144>>> json = '[{"pk": "3", "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00", "categories": [4, 1], "author": 4}}, {"pk": "4", "model": "serializers.category", "fields": {"name": "Reference"}}, {"pk": "4", "model": "serializers.author", "fields": {"name": "Agnes"}}]'
     145>>> from django.db import transaction
     146>>> transaction.enter_transaction_management()
     147>>> transaction.managed(True)
     148>>> for obj in serializers.deserialize("json", json):
     149...     obj.save()
     150
     151>>> transaction.commit()
     152>>> transaction.leave_transaction_management()
     153
     154>>> article = Article.objects.get(pk=3)
     155>>> article
     156<Article: Forward references pose no problem>
     157>>> article.categories.all()
     158[<Category: Reference>, <Category: Sports>]
     159>>> article.author
     160<Author: Agnes>
     161
    142162"""}
Back to Top