Modify

Ticket #182 (closed defect: fixed)

Opened 5 years ago

Last modified 4 years ago

Improper handling of _bases

Reported by: ralf.gerlich@… Owned by: andrew
Priority: major Milestone: 0.7
Component: migrations Version: 0.6-pre
Keywords: meta bases typeerror inheritance Cc:

Description

I have the following model (shortened for better readability):

class Person(models.Model):
    surname = models.CharField(max_length=60);
    firstname = models.CharField(max_length=60);

class Pilot(Person):
    is_instructor = models.BooleanField(default=False);


class Flight(models.Model):
    # ...
    attendants = models.ManyToManyField(Pilot, blank=True, related_name='attended_flights');
    passengers = models.ManyToManyField(Person, blank=True, related_name='passenger_flights');
    # ...

I want to migrate all pilots from the passengers field to the attendants field:

from south.db import db
from django.db import models
from logbook.models import *

class Migration:
    
    no_dry_run = True;
    
    def forwards(self, orm):
        for pilot in orm.Pilot.objects.all():
            for flight in pilot.passenger_flights.all():
                pilot.attended_flights.add(flight);
            pilot.passenger_flights.clear();
            pilot.save();
    
    def backwards(self, orm):
        for pilot in orm.Pilot.objects.all():
            for flight in pilot.attended_flights.all():
                pilot.passenger_flights.add(flight);
            pilot.attended_flights.clear();
            pilot.save();
    
    models = {
        'logbook.flight': {
            'attendants': ('models.ManyToManyField', ["orm['logbook.Pilot']"],
                {'related_name': "'attended_flights'",
                 'blank': 'True'}),
            'passengers': ('models.ManyToManyField', ["orm['logbook.Person']"],
                {'related_name': "'passenger_flights'",
                 'blank': 'True'}),
        },
        'logbook.person': {
            'firstname': ('models.CharField', [], {'max_length': '60'}),
            'id': ('models.AutoField', [], {'primary_key': 'True'}),
            'surname': ('models.CharField', [], {'max_length': '60'})
        },
        'logbook.pilot': {
            'Meta': {'_bases': ["logbook.models.Person"]},
            'is_instructor': ('models.BooleanField', [], {'default': 'False'}),
            'person_ptr': ('models.OneToOneField', ["orm['logbook.Person']"], {})
        }
    }
    
    complete_apps = ['logbook']

The line pilot.attended_flights.add(flight); gives me a TypeError? exception, saying that an object of type 'flight' is expected.

Examining the type of flight I get 'logbook.models.Flight', while the model associated with pilot.attended_flights is 'logbook.models.flight'.

Looking into the code at south/orm.py I find that the base-class for the classes generated by the fake ORM is loaded using ask_for_it_by_name, which resolves the base of Pilot to be logbook.models.Person, i.e. the real instead of the fake base.

As the passenger_flights-relation is defined in Person, the field definitions in the fake Person and the fake Pilot differ.

Fix: Use the fake base class instead.

Is there a way to work around this issue?

Attachments

Change History

comment:1 Changed 5 years ago by andrew

  • Status changed from new to assigned
  • Milestone set to 0.6

Yes, I should be able to use the fake bases, you're right.

comment:2 Changed 5 years ago by andrew

Bumping to 0.7

comment:3 Changed 5 years ago by andrew

  • Milestone changed from 0.6 to 0.7

comment:4 Changed 4 years ago by andrew

  • Status changed from assigned to closed
  • Resolution set to fixed

Fixed in [237ca3bb6d5d]. Finally :)

View

Add a comment

Modify Ticket

Action
as closed
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.