Django: добавление объектов в связанный набор без сохранения в БД - PullRequest
1 голос
/ 19 августа 2011

Я пытаюсь написать внутренний 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 ]

2 голосов
/ 19 августа 2011
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

Объяснение: Сначала необходимо создать объект продукта, а затем назначить его объекту изображения, поскольку здесь необходимо указать имя и имя.

Мне интересно, почему бы вам не потребовать сделать запись продукта в БД в первом случае?Если есть какая-то конкретная причина, то я могу предложить вам немного поработать?

РЕДАКТИРОВАТЬ: Хорошо!я думаю, что я вас понял, вы не хотите изначально назначать продукт объекту изображения.Как насчет создания поля продукта, поскольку значение 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 голос
/ 25 апреля 2013

У меня такая же проблема с @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

Это означает, что нам нужно только установить свойство _prefetched_objects_cache для объекта.

0 голосов
/ 31 августа 2011

Ваша проблема в том, что идентификатор задается не django, а базой данных (он представлен в базе данных автоинкрементным полем), поэтому, пока он не сохранен, идентификатора нет. Подробнее об этом в документации .

Я могу придумать три возможных решения:

  1. Установите другое поле вашей модели изображения в качестве первичного ключа (задокументировано здесь ).
  2. Установите другое поле вашей производственной модели в качестве внешнего ключа (задокументировано здесь ).
  3. Использовать API транзакций базы данных django (задокументировано здесь ).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...