Thanks for the detailed responses, they helped clarify things a lot.

I will try the first option you mentioned about creating the Questions 
first (and saving them) and then creating the Choices using the Questions 
that were just created.
My back-up plan will be to use a different pk field for Question (like 
question text) that will be already known when I create Choices for a 
question.

On Monday, November 28, 2016 at 8:55:02 AM UTC-5, C. Kirby wrote:
>
>
>
> On Monday, November 28, 2016 at 3:12:37 PM UTC+2, Michael Viveros wrote:
>>
>> Thanks for the reply Kirby.
>>
>> I understand that the Question's pk is null when you pass in the Question 
>> to the Choice constructor. But when you save the Choice, the Question was 
>> saved earlier so the Question's pk is not null. But the Choice's 
>> question_id attribute (representing the Question's pk) is still null when 
>> you save the Choice. 
>>
>> *1. Should the Choice's question_id have been updated to it's current 
>> value when saving the Choice?* 
>>
> No. The preparing you linked handles type changes between python and the 
> db, if the db cannot handle the type you have (like the referenced python 
> datetime).
> What is happening is no different than:
>
> >>> a = 1
> >>> b = a
> >>> a = 2
> >>> b
> 1
> >>> a
> 2
>
>
>> I read some more about what happens when you save 
>> <https://docs.djangoproject.com/en/1.10/ref/models/instances/#what-happens-when-you-save>
>>  an 
>> object in Django and it seems like the Choice's question_id should be 
>> updated when the data is prepared for the db (step 3 from the link). 
>> I understand I can override the Choice class's save method to do 
>> this (see code below) but it seems like it should be something that is 
>> already done by the Django framework.
>>
>>     def save(self, *args, **kwargs):
>>         self.question_id = self.question.id
>>         super(Choice, self).save(*args, **kwargs)
>>
>>
>> This won't work for 1 or 2 reasons, depending on versions. save() does 
> not get called when using bulk_create(). Also, unless you are using 
> postgres and django 1.10, pk's get saved to the db, but not assigned to the 
> object when using bulk_create() 
>
>> *2. Is there a better way to bulk create objects in a one-to-many 
>> relationship *(Questions and Choices)*?*
>>
>> My idea (from the code snippet after models.py) was to bulk create the 
>> Questions and then bulk create the Choices but this has the problem 
>> mentioned above of the Choice's FK (question_id) not being updated even 
>> after the Questions were bulk created.
>>
> You pretty much can't do it inline like you want with bulk_create(), I 
> don't think. If you have the question objects retrieved you can then assign 
> them to the choices and you are all set. If you really want to do it how 
> you are trying then your best bet would be to assign a primary_key field 
> instead of using the AutoField primary key provided. If you use the 
> question title, or generate a uuid for each question and set that as the 
> primary_field then you can provide the primary key that you know for a 
> question to the associated choices. 
>
>>
>> On Monday, November 28, 2016 at 6:59:13 AM UTC-5, C. Kirby wrote:
>>>
>>> The reason it isn't working in your first example is because the pk gets 
>>> assigned to the object when it is saved to the database.  When you supply 
>>> question=q to the choice, it is (correctly) getting a pk of null because q 
>>> has not been saved. 
>>>
>>> On Saturday, November 26, 2016 at 2:56:37 AM UTC+2, Michael Viveros 
>>> wrote:
>>>>
>>>> I have a Question model and a Choice model where a Question can have 
>>>> many Choices so the Choice model has a Foreign Key mapping to a Question.
>>>>
>>>> models.py:
>>>>
>>>> from django.db import models
>>>>
>>>>
>>>> class Question(models.Model):
>>>>     text = models.CharField(max_length=200)
>>>>     title = models.CharField(max_length=200)
>>>>     total_response_count = models.IntegerField()
>>>>     topic = models.CharField(max_length=20)
>>>>     sequence_num = models.IntegerField()
>>>>     select_multiple = models.BooleanField(default=False)
>>>>
>>>>     def __str__(self):
>>>>         return self.text
>>>>
>>>>
>>>> class Choice(models.Model):
>>>>     question = models.ForeignKey(Question, on_delete=models.CASCADE)
>>>>     text = models.CharField(max_length=200)
>>>>     response_count = models.IntegerField()
>>>>     response_percent = models.FloatField()
>>>>
>>>>     def __str__(self):
>>>>         return self.text
>>>>
>>>>
>>>> I need to parse a csv file containing these models and insert them into 
>>>> a database. 
>>>> I want to be efficient and bulk create these models instead of having 
>>>> to call save() after creating each model.
>>>> I can bulk create the Questions but then when I try to bulk create the 
>>>> Choices I get an IntegrityError about the Choice's foreign key id 
>>>> attribute 
>>>> ("question_id") violating a not-null constraint.
>>>> After creating the Questions, the Question's id attribute gets updated 
>>>> but the Choice's question_id attribute does not get updated and it does 
>>>> not 
>>>> get re-evaluated when the Choice is created.
>>>>
>>>> Here's a simplified version of what I want to do:
>>>> from censustest.models import Question,Choice
>>>>
>>>>
>>>> q=Question(text="Q1",title="",topic="",sequence_num=0,total_response_count=0)
>>>> c=Choice(text="C1",response_count=5,response_percent=0.3,question=q)
>>>> print("q.id %s, c.question %s, c.question_id %s" % (q.id, c.question, 
>>>> c.question_id)) # None,Q1,None
>>>> Question.objects.bulk_create([q])
>>>> print("After creating q: q.id %s, c.question %s, c.question_id %s" % (
>>>> q.id, c.question, c.question_id)) # valid id,Q1,None
>>>> Choice.objects.bulk_create([c]) # ERROR: IntegrityError
>>>>
>>>> Output:
>>>>
>>>> <https://lh3.googleusercontent.com/-FFbndWx_lfU/WDjbHC_0QUI/AAAAAAAACPQ/xnwdyg_mVNM6lS-jytZTN7n0ujR7FzYiwCLcB/s1600/Screen%2BShot%2B2016-11-25%2Bat%2B7.42.20%2BPM.png>
>>>>
>>>> *Is this a bug with Django *(the foreign key id attribute not being 
>>>> updated)* or is there a better way to do it?*
>>>>
>>>> An alternative approach I thought of was to assign the Choice's 
>>>> Question after creating the Questions and this works.
>>>> from censustest.models import Question,Choice
>>>>
>>>>
>>>> q=Question(text="Q1",title="",topic="",sequence_num=0,total_response_count=0)
>>>> c=Choice(text="C1",response_count=5,response_percent=0.3)
>>>> print("q.id %s" % (q.id)) # None,Q1,None
>>>> Question.objects.bulk_create([q])
>>>> c.question=q
>>>> print("c.question %s, c.question_id %s" % (c.question, c.question_id)) 
>>>> # Q1,valid id
>>>> Choice.objects.bulk_create([c]) # works, no error
>>>>
>>>> Output:
>>>>
>>>> <https://lh3.googleusercontent.com/-pncM3xKl0Gc/WDjboxPCzWI/AAAAAAAACPU/V4I9TczbqnAm6mBnogU-kIVCvWXJ7ebrQCLcB/s1600/Screen%2BShot%2B2016-11-25%2Bat%2B7.43.53%2BPM.png>
>>>>
>>>

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/2eac5cbb-2f5e-4444-9e60-1fb0c446c183%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to