开发者

Django: Adding objects to a related set without saving to DB

I'm trying to write an internal API in my application witho开发者_JAVA技巧ut necessarily coupling it with the database.

class Product(models.Model):
    name=models.CharField(max_length=4000)
    price=models.IntegerField(default=-1)
    currency=models.CharField(max_length=3, default='INR')

class Image(models.Model): 
    # NOTE -- Have changed the table name to products_images
    width=models.IntegerField(default=-1)
    height=models.IntegerField(default=-1)
    url=models.URLField(max_length=1000, verify_exists=False)
    product=models.ForeignKey(Product)

def create_product:
    p=Product()
    i=Image(height=100, widght=100, url='http://something/something')
    p.image_set.add(i)
    return p

Now, when I call create_product() Django throws up an error:

IntegrityError: products_images.product_id may not be NULL

However, if I call p.save() & i.save() before calling p.image_set.add(i) it works. Is there any way that I can add objects to a related object set without saving both to the DB first?


def create_product():
    product_obj = Product.objects.create(name='Foobar')
    image_obj = Image.objects.create(height=100, widght=100, url='http://something/something', product=product_obj)
    return product_obj

Explanation: Product object has to be created first and then assign it to the Image object because id and name here is required field.

I am wondering why wouldn't you not require to make a product entry in DB in first case? If there is any specific reason then i may suggest you some work around?

EDIT: Okay! i think i got you, you don't want to assign a product to an image object initially. How about creating a product field as null is equal to true.

product = models.ForeignKey(Product, null=True)

Now, your function becomes something like this:

def create_product():
        image_obj = Image.objects.create(height=100, widght=100, url='http://something/something')
        return image_obj

Hope it helps you?


I got same issue with @Saurabh Nanda

I am using Django 1.4.2. When I read in django, i see that

# file django/db/models/fields/related.py
def get_query_set(self):                                              
   try:                                                              
      return self.instance._prefetched_objects_cache[rel_field.related_query_name()]
   except (AttributeError, KeyError):                                
      db = self._db or router.db_for_read(self.model, instance=self.instance)
      return super(RelatedManager,self).get_query_set().using(db).filter(**self.core_filters)


# file django/db/models/query.py 
qs = getattr(obj, attname).all()                                          
qs._result_cache = vals                                                   
# We don't want the individual qs doing prefetch_related now, since we
# have merged this into the current work.                                 
qs._prefetch_done = True                                                  
obj._prefetched_objects_cache[cache_name] = qs

That 's make sese, we only need to set property _prefetched_objects_cache for the object.

p = Product()
image_cached = []
for i in xrange(100): 
   image=Image(height=100, widght=100, url='http://something/something')
   image_cached.append(image)
qs = p.images.all()
qs._result_cache = image_cached
qs._prefetch_done = True
p._prefetched_objects_cache = {'images': qs}


Your problem is that the id isn't set by django, but by the database (it's represented in the database by an auto-incremented field), so until it's saved there's no id. More about this in the documentation.

I can think of three possible solutions:

  1. Set a different field of your Image model as the primary key (documented here).
  2. Set a different field of your Production model as the foreign key (documented here).
  3. Use django's database transactions API (documented here).
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜