I have a simple django model
class Directory(models.Model):
id = models.AutoField(primary_key=True)
path = models.TextField(unique=True)
def __unicode__(self):
return self.path
class Meta:
db_table = u'directories'
However, there seems to be some problem to save a Directory instance into the db
>>> from cygapp.models import Directory
>>> d = Directory()
>>> d.path = '/usr'
>>> d.id
>>> d.save()
>>> d.id
4
>>> d
<Directory: /usr>
while the ID field is assigned correctly (the next free value), it is not stored in the db
sqlite> select * from directories;
1|/bin
2|/system/lib
3|/system/bin
|/usr
What am i missing here?
Everything you're doing to save the record is correct and an auto id should be assigned.
Remove your custom id field id = models.AutoField(primary_key=True) since Django does this automatically for you. Then drop your 'directories' table and run python manage.py syncdb. This will ensure you have a correct id field on your model.
Related
I got a ValueError while trying to add model instances with a many-to-many relationship.
ValueError: "(Idea: hey)" needs to have a value for field "id" before this many-to-many relationship can be used.
A lot of responses were given here, but none was helpful.My (idea) solution was to "manually" input the "id" values.
>>> import django
>>> django.setup()
>>> from myapp1.models import Category, Idea
# Notice that I manually add an "id"
>>> id2=Idea.objects.create(
... title_en='tre',
... subtitle_en='ca',
... description_en='mata',
... id=5,
... is_original=True,
... )
>>> id2.save()
>>> cat22=Category(title_en='yo')
>>> cat22.save()
>>> id2.categories.add(cat22)
>>> Idea.objects.all()
<QuerySet [<Idea: tre>]>
>>> exit()
How do i command django to auto-add the "id" field?
Note: I tried adding autoField but failed, thanks
#python_2_unicode_compatible
class Idea(UrlMixin, CreationModificationDateMixin, MetaTagsMixin):
id = models.IntegerField(primary_key=True,)
title = MultilingualCharField(_("Title"), max_length=200,)
subtitle = MultilingualCharField(_("Subtitle"), max_length=200, blank=True,)
description = MultilingualTextField(_("Description"), blank=True,)
is_original = models.BooleanField(_("Original"), default=False,)
categories = models.ManyToManyField(Category,
You're confusing two things here:
With many-to-many relationships, when connecting two objects, both objects must already be saved to the database (have a primary key), because under the hoods, Django creates a third object that points at the two objects to connect them. It can only do that if both have an id, assuming id is the primary key.
When creating an object, you don't have to explicitly set the id (actually you shouldn't). By default, a django Model will have id set as an auto field and as a primary key (you can override that by specifying your own pk, but in general there's no need to). The id is automatically created when the model is saved the first time.
You saw the error because probably one of the objects (idea or category) wasn't saved to the database before you connected them. In your code sample, you don't have to pass id=5, it will work without it, because you save id2 and category before connecting them.
Here is my models.py:
class Foo(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=30)
In django manage.py shell:
>>> a,b = Foo.objects.get_or_create(name='hi')
>>> b
True
>>> vars(a)
{'_state': <django.db.models.base.ModelState object at 0x02761390>, 'id': None,
'name': 'hi'}
The problem here is the customized id attribute has no value. And if I continue to do the following:
>>> c = foo.objects.get(name='hi')
>>> c.id
1
>>> a is c
False
So that newly created object (denoted by c) already exists now, but b is not an exact reference to it like c is.
Is this a bug? My django version is 1.6.5.
By default, if you have not specified the id field for you model, Django will create AutoField:
id = models.AutoField(primary_key=True)
In your case you've created just IntegerField. I suppose this is the point. In the database, it will still be incremented, but django won't assign the id value from database to the object, returned by get_or_create
By the way, in your question:
>>> b is c
False
b - is a bool value. I think you were trying to do
>>> a is c
But also this is not a good idea. If you want to compare django model objects, use ==, not is:
>>> a == c
You will get False anyway, as a has its id set to None.
You have declared your id field as an IntegerField, so Django does not know it needs to autoincrement. You could define it as an AutoField, but actually there is no reason to declare it at all: Django will automatically define it for you if you leave it out.
Note this has nothing to do with get_or_create: you would have exactly the same problem with a normal create/save.
My models:
class InventoryItem(models.Model):
quantity = models.IntegerField()
...
class Requisition(models.Model):
from_inventoryitem = models.ForeignKey(InventoryItem)
quantity = models.IntegerField()
...
Assuming that requisition has an OneToMany relation with inventory_item below, and the initial value of inventory_item.quantity is 0, When I excute:
>>> requisition = Requisition.objects.get(id=1)
>>> requisition.from_inventoryitem.quantity = 500
>>> requisition.save()
>>> requisition.from_inventoryitem.quantity
500
>>> inventory_item.quantity
0
>>> requisition.from_inventoryitem == inventory_item
True
The inventory_item.quantity in database and InventoryItem side is still 0.
How can I update that change to the database?
This is by design. You have to save each instance seperately. requisition.from_inventoryitem actually queries the InventoryItem instance from the database, just to set the quantity.
requisition = Requisition.objects.get(id=1)
requisition.from_inventoryitem.quantity = 500 # this generates another query here!
requisition.from_inventoryitem.save()
or even better, with a single query, single save
inv_item = InventoryItem.objects.get(requisition_set__id=1)
inv_item.quantity = 500
inv_item.save()
best way. single database call:
InventoryItem.objects.filter(requisition_set__id=1).update(quantity=500)
I have a basic model called Restaurant
class Restaurant(models.Model):
place = models.OneToOneField(Place, primary_key=True)
serves_pizza = models.BooleanField()
serves_hotdog = models.BooleanField()
def __unicode__(self):
return u'%s the restaurant' % self.place.name
Querying with Restaurant.objects.all() and Restaurant.objects.get() yields two different results in which only the former is correct.
# this is correct
>>> r=Restaurant.objects.all()
>>> r
[<Restaurant: Hogwarts the restaurant>, <Restaurant: Domino the restaurant>]
>>> r[0].serves_hotdog
True
# this is not correct
>>> r0=Restaurant.objects.get(pk=4556376185503744)
>>> r0.serves_hotdog
False
# although they have the same pk
>>> r0.pk == r[0].pk
True
# their property values are different
>>> r[0].serves_hotdog == r0.serves_hotdog
False
>>> r[0].serves_pizza == r0.serves_pizza
False
Has anyone seen anything similar to this?
If you are using Django-nonrel on GAE, make sure that you don't set primary_key=True for related models because the engine will use the same primary key for both models. For example, in my case, I have Restaurant and Place with OneToOneRelationship. If we use Place as primary key for Restaurant, a restaurant object created from a place object will share the same pk, thus messing up Restaurant.objects.get(pk=).
Dropping the primary key rule fixes my problem:
class Restaurant(models.Model):
place = models.OneToOneField(Place) # no primary_key=True
I can't find this information elsewhere, so I'm posting it here. Hope it helps someone else.
I have two models in Django: one of them is a bunch of entries, and another model is a link table - it basically maps one entry to another, so it has a entry_a_id and an entry_b_id field... how do I write a QuerySet query to properly select the first entry's related fields then the second one?
=== EDIT ===
Here's an example:
class Nodes(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=45)
description = models.CharField(max_length=255)
class Links(models.Model):
id = models.AutoField(primary_key=True)
node_a_id = models.ForeignKey('Nodes')
node_b_id = models.ForeignKey('Nodes')
So, with that said (or typed), I would like to be able to figure out how to have a final result of node_a_id, name, description, node_b_id, name, description according to the Links model. Let me know if you want me to clarify further.
I might have misunderstood but here I go. Having a Link object:
>>> link = Links.objects.all()[0]
You automagically have access to the fields of your foreign relations (node_a_id and node_b_id). With that, you can do the following:
>>> link = Links.objects.all()[0]
>>> link.node_a_id.id
1
>>> link.node_a_id.name
'Name for node A'
>>> link.node_a_id.description
'Description for node B'
>>> link.node_b_id.id
2
>>> link.node_b_id.name
'Name for node B'
>>> link.node_b_id.description
'Description for node B'
As a side note, there is no point in using id as your auto-incrementing primary key field since you get that for free: AutoField and Automatic primary key fields