Code

Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#14944 closed (invalid)

Saving a model which refers to unexistent models does not spit any errors

Reported by: ferran Owned by: nobody
Component: Database layer (models, ORM) Version: 1.2
Severity: Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

I had these models:

class IPv4(models.Model):
    addr = models.IPAddressField(
        unique=True,
        primary_key=True
    )
    
    def __unicode__(self):
        return self.addr

class Hostname(models.Model):
    host = models.CharField(
        max_length=200,
        unique=True,
        primary_key=True,
    )
    
    def __unicode__(self):
        return self.host

class NameServer(models.Model):
    host = models.ForeignKey(Hostname, related_name="hostname")
    ip = models.ForeignKey(IPv4, related_name="ip address")
    handle = GenericRelation(Handle, null=True)
    
    def __unicode__(self):
        return "%s (%s)" % (self.host, self.ip)

    class Meta:
        unique_together = ('host', 'ip')

If i try to add a NameServer with non-saved models, it does not fail until it searches for objects:

>>> ns = NameServer(host=Hostname(host='tetuan.fompi.net'), ip=IPv4(addr='87.216.178.18'))
>>> ns.save()
>>> Hostname.objects.all()
[<Hostname: seie.fompi.net>, <Hostname: uno.uno.uno>, <Hostname: dos.dos.dos>]
>>> j.objects.all()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/usr/lib/python2.7/site-packages/django/db/models/manager.py", line 211, in __get__
    raise AttributeError("Manager isn't accessible via %s instances" % type.__name__)
AttributeError: Manager isn't accessible via NameServer instances
>>> NameServer.objects.all()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/usr/lib/python2.7/site-packages/django/db/models/query.py", line 71, in __repr__
    return repr(data)
  File "/usr/lib/python2.7/site-packages/django/db/models/base.py", line 344, in __repr__
    u = unicode(self)
  File "domains/models.py", line 114, in __unicode__
    return "%s (%s)" % (self.host, self.ip)
  File "/usr/lib/python2.7/site-packages/django/db/models/fields/related.py", line 302, in __get__
    rel_obj = QuerySet(self.field.rel.to).using(db).get(**params)
  File "/usr/lib/python2.7/site-packages/django/db/models/query.py", line 341, in get
    % self.model._meta.object_name)
DoesNotExist: Hostname matching query does not exist.

Attachments (0)

Change History (3)

comment:1 Changed 3 years ago by ferran

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

I think the wanted functionality is to do a cascade save() if referenced model does not have a pk value, i can't imagine a case scenario where might be useful to save a model referencing unexistent ones.

comment:2 Changed 3 years ago by Honza_Kral

  • Resolution set to invalid
  • Status changed from new to closed

The ORM doesn't do any validation by default, you have to do that manually if you need it, see the docs for model validation for more details. Normally the DB will complain of violating a constraint, you must be using some DB that doesn't do that or have the table definitions in different state than reflected by your models.py.

btw. your unique_together won't work like this, it must be a tuple of tuples to work.

comment:3 Changed 3 years ago by ferran

Thank you, Honza_Kral; it seems like a South problem, i've just created a new app only with these model definitions and .save() method failed.

My fault for not testing it well.

Also, thank you for pointing out the unique_together issue; but it seems to work as is on django 1.0+

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


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

 
Note: See TracTickets for help on using tickets.