Django, MySQL - bug?

7 views
Skip to first unread message

Tomasz Zieliński

unread,
Jul 18, 2009, 5:39:38 PM7/18/09
to Django users
I prepared following repro case, just paste to models.py to an empty
project:

-----------------------------------------------------------
from MySQLdb import Warning as Warning
from django.db import models
import unittest

class TestModel(models.Model):
char_field = models.CharField(max_length=5)

class Case1(unittest.TestCase):
def test1(self):
print "Count 1:", TestModel.objects.count()
m = TestModel(char_field="123456")
try:
m.save()
except Warning:
print "Count 2:", TestModel.objects.count()
print "m.id=", m.id
print "all()[0].id=", TestModel.objects.all()[0].id
-----------------------------------------------------------

manage.py test returns:

Count 1: 0
Count 2: 1
m.id= None
all()[0].id= 1

Which seems like a bug to me (m.id=None). Am I right or I overlooked
some info in documentation?

--
Tomasz Zieliński
http://pyconsultant.eu

Daniel Roseman

unread,
Jul 19, 2009, 4:35:26 AM7/19/09
to Django users
On Jul 18, 10:39 pm, Tomasz Zieliński
I don't know why you think it's a bug. Django's models are - by design
- not an instantaneous reflection of the database. Rather, they only
interact with the DB when you load and save them. So this is the
expected behaviour.
--
DR.

Tomasz Zieliński

unread,
Jul 19, 2009, 6:42:31 AM7/19/09
to Django users
On 19 Lip, 10:35, Daniel Roseman <dan...@roseman.org.uk> wrote:
>
> I don't know why you think it's a bug. Django's models are - by design
> - not an instantaneous reflection of the database. Rather, they only
> interact with the DB when you load and save them. So this is the
> expected behaviour.

So, should m.save() set m.id to some other value than None
or this is relaxed when Warning exception is thrown?

Joshua Russo

unread,
Jul 19, 2009, 10:29:29 AM7/19/09
to django...@googlegroups.com
2009/7/19 Tomasz Zieliński <tomasz.z...@pyconsultant.eu>

So, should m.save() set m.id to some other value than None
or this is relaxed when Warning exception is thrown?

It's the database that gives m.id a value upon a valid save. So because the record couldn't be saved it never received a value.

Tomasz Zieliński

unread,
Jul 19, 2009, 11:41:23 AM7/19/09
to Django users


On 19 Lip, 16:29, Joshua Russo <josh.r.ru...@gmail.com> wrote:
> 2009/7/19 Tomasz Zieliński <tomasz.zielin...@pyconsultant.eu>
>
> > So, should m.save() set m.id to some other value than None
> > or this is relaxed when Warning exception is thrown?
>
> It's the database that gives m.id a value upon a valid save. So because the
> record couldn't be saved it never received a value.

The record is saved - what is raised is Warning (about string being
truncated), not Error.

As a proof, following instruction prints 1:

print "all()[0].id=", TestModel.objects.all()[0].id

Alex Gaynor

unread,
Jul 19, 2009, 12:32:21 PM7/19/09
to django...@googlegroups.com
2009/7/19 Tomasz Zieliński <tomasz.z...@pyconsultant.eu>:
I believe this is just a shortcoming of either MySQL, or MySQLDb, in
that it can't return the ID of an inserted object.

Alex

--
"I disapprove of what you say, but I will defend to the death your
right to say it." -- Voltaire
"The people's good is the highest law." -- Cicero
"Code can always be simpler than you think, but never as simple as you
want" -- Me

Tomasz Zieliński

unread,
Jul 19, 2009, 6:29:10 PM7/19/09
to Django users
On 19 Lip, 18:32, Alex Gaynor <alex.gay...@gmail.com> wrote:
> 2009/7/19 Tomasz Zieliński <tomasz.zielin...@pyconsultant.eu>:
>
>
>
>
>
> > On 19 Lip, 16:29, Joshua Russo <josh.r.ru...@gmail.com> wrote:
> >> 2009/7/19 Tomasz Zieliński <tomasz.zielin...@pyconsultant.eu>
>
> >> > So, should m.save() set m.id to some other value than None
> >> > or this is relaxed when Warning exception is thrown?
>
> >> It's the database that gives m.id a value upon a valid save. So because the
> >> record couldn't be saved it never received a value.
>
> > The record is saved - what is raised is Warning (about string being
> > truncated), not Error.
>
> > As a proof, following instruction prints 1:
>
> > print "all()[0].id=", TestModel.objects.all()[0].id
>
> > --
> > Tomasz Zieliński
> >http://pyconsultant.eu
>
> I believe this is just a shortcoming of either MySQL, or MySQLDb, in
> that it can't return the ID of an inserted object.
>

Thanks, I'll check it down the pipeline then.

Tomasz Zieliński

unread,
Jul 20, 2009, 7:13:13 AM7/20/09
to Django users
I tried this:

import MySQLdb
db = MySQLdb.connect(...)
c = db.cursor()
c.execute("create table mtest (pk int not null auto_increment primary
key, s varchar(5)) type=InnoDB")

print c.execute("insert into mtest values (null,'12345')")
print c.messages
print c.lastrowid

print c.execute("insert into mtest values (null,'123456789')")
print c.messages
print c.lastrowid

And I got this:

1
[]
21

1
[(<class '_mysql_exceptions.Warning'>, ('Warning', 1265L, "Data
truncated for column 's' at row 1"))]
22

So it seems to my MySQLdb actually returns primary key for INSERT that
causes Warning.

One thing that is different here from Django scenario is that Warning
is not being thrown,
does someone know how to turn on raising Warning exceptions in
MySQLdb?
Reply all
Reply to author
Forward
0 new messages