Django:将对象添加到相关集而不保存到DB

时间:2011-08-19 12:09:50

标签: django django-models

我正在尝试在我的应用程序中编写内部API,而不必将其与数据库耦合。

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

现在,当我调用create_product()时,Django会抛出一个错误:

IntegrityError: products_images.product_id may not be NULL

但是,如果我打电话给p.save()& i.save()在调用p.image_set.add之前(i)它有效。有没有办法可以将对象添加到相关的对象集而不先保存到数据库?

3 个答案:

答案 0 :(得分:2)

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

<强>说明: 必须首先创建Product对象,然后将其分配给Image对象,因为此处的id和name是必填字段。

我想知道为什么在第一种情况下你不需要在数据库中输入产品?如果有任何具体原因,我可能会建议你解决一些问题吗?

编辑:好的!我想我得到了你,你不想最初将产品分配给图像对象。如何将产品字段创建为null等于true。

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

现在,你的功能变成了这样:

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

希望对你有帮助吗?

答案 1 :(得分:1)

我和@Saurabh Nanda有同样的问题

我正在使用Django 1.4.2。当我读到django时,我看到了

# 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

这就是sese,我们只需要为对象设置属性_prefetched_objects_cache

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}

答案 2 :(得分:0)

你的问题是id不是由django设置的,而是由数据库设置的(它在数据库中由一个自动递增的字段表示),所以直到它被保存为止没有id。有关此in the documentation的更多信息。

我可以想到三种可能的解决方案:

  1. 将图像模型的其他字段设置为主键(记录为here)。
  2. 将生产模型的其他字段设置为外键(记录为here)。
  3. 使用django的数据库事务API(记录为here)。