Hi all,

tl;dr: saving inherited model overwrites fields in parent models with empty 
strings

I have the following models:

class Contact(models.Model):
    comment = models.CharField(max_length=255, blank=True)
    emails = models.ManyToManyField(
        Email,
        blank=True,
        through='ContactEmail',
        through_fields=('contact', 'email'),
    )

    # couple of more manytomanys, to addresses, phones, etc

        
class ContactEmail(BaseContactJunctionModel):
    email = models.ForeignKey(Email, null=True, on_delete=models.SET_NULL)
    contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
    event = models.ForeignKey(ContactEvent, on_delete=models.PROTECT)
    event_date = models.DateTimeField(default=timezone.now)


# other similar through tables for the rest of the manytomanys and their 
target models


class Organisation(Contact):

    name = models.CharField(max_length=255, blank=True)
    hierarchy = models.ManyToManyField(
        'self',
        blank=True,
        symmetrical=False,
        through='OrganisationHierarchy',
        through_fields=('sender', 'target'),
    )    

    # again, more manytomanys, not to self though

# not sure this is relevant but as it's to self, then just in case
class OrganisationHierarchy(BaseContactJunctionModel):
    # this, instance that specifies relationship
    sender = models.ForeignKey(
        Organisation,
        null=True, 
        related_name='senders',
        on_delete=models.SET_NULL,
    )
    
    # instance that 'this' or 'sender' is related to
    target = models.ForeignKey(
        Organisation,
        null=True, 
        related_name='targets',
        on_delete=models.SET_NULL,
    )

    connection_type = models.ForeignKey(
        ConnectionType,
        null=True,
        on_delete=models.PROTECT,
    )

I have a view based on CreateView and a template to capture user
input. The post request coming from browser is a-ok, saving
emails, contact, contactemails and other manytomany targets and
junction tables works without a problem but when getting to
saving Organisation, this happens (pseudocode):

save() is called from django/db/models/base.py
    save_base() is called with self=Organisation
        save_base calls _save_parents(self=Organisation, cls=Organisation)
            save_parents loops through cls._meta.parents and comes across 
relation
                parent=Contact, field=Organisation.contact_ptr
                calls _save_table with self=Organisation and cls=Contact
                    _save_table finds from cls._meta that it has
                    local concrete field "comment" and stores it in list 
non_pks
                    it then finds the values for those fields like 
this:                 
                    f.pre_save(self, false) for f in non_pks 

I then see a call to _update in queries.py and Contact instance
is updated with new values.

I don't really understand what's happening here, the code finds
local concrete fields from "cls" which at this point is Contact
and comes up, correctly, with "comment" but then it tries to
query the field value form "self" which at this point is
Organisation object. I'm not sure why Organisation has "comment"
attribute at all, because the way I read the docs it should only
happen when the base model is abstract or when the inherited
model is proxy model, neither of which is the case. Anyway, the
value returned by save_base for the "comment" from "self" is not 
the value I inserted into the form field (and what has previously 
been saved to Contact object) but is instead an empty string.

The end result is, after Contact object is correctly saved it is,
moments later, overwritten by an empty string. Does anybody have
a clue as to what is happening and most importantly, how can I
avoid it?

Thanks,

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/4587198f-5f6f-49a7-b54a-1dcfe5a436ab%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to