Thanks Furbee,

UNDERSTOOD.

Thanks again for detailled and instructive answers.

Alain

On 2 nov, 21:36, Furbee <furbeena...@gmail.com> wrote:
> Hi Alain,
>
> Sort of. With this code:
>     if field == 'category':
>         instance.save()
> a Customer with 50 categories would write to the database 51 times (1
> INSERT, and 50 UPDATES).
>
> Including the "instance.id == None" like this:
>     if field == 'category' and instance.id == None:
>         instance.save()
> will make it write to the database one or two times maximum. If the
> Customer has 0 categories, it will write once (INSERT at bottom of
> program). If the Customer has n categories, it will only write once
> (INSERT) in the loops, and write once (UPDATE) at the bottom of the program.
>
> That is why it is much quicker running it this way.
>
> Cheers,
>
> Furbeenator
>
>
>
>
>
>
>
> On Wed, Nov 2, 2011 at 1:00 PM, youpsla <youp...@gmail.com> wrote:
> > Hi again
> > thanks for explanations.
>
> > I've understood difference between Null and None.
>
> > I've modify the code to add "instance.id == Non" and it seems to be
> > faster.
>
> > To be sure. You mean that if a customer has 1 category, there will be
> > 2 database access (one for all informations except category and one
> > for category).
>
> > If a customer has 50 categories, then it's 51 database access ? huuuuu
>
> > Thanks again
>
> > Alain
>
> > On 2 nov, 20:11, Furbee <furbeena...@gmail.com> wrote:
> > > Hi Alain,
>
> > > Glad that it worked out! :-)
>
> > > To clarify, a blank is different from a Null, or "None" in
> > Python/Django. A
> > > blank character field is "" where a null character field is NULL. If a
> > > field does not specify null=True, and you try to save an instance of that
> > > object without specifying that field, it will raise a Database error. So,
> > > in your loop if you hit category first, before any other fields, it would
> > > try to save the instance of the Customer without specifying all of the
> > > fields needed. That is why category must come AFTER all other fields that
> > > are required (not null=True).
>
> > > You are correct. The instance = Customer() creates a new customer object,
> > > when you executed instance.save() the instance information is saved
> > > (INSERT) to the database, and it received a PK (id). Every subsequent
> > > instance.save() actually runs (UPDATE) on the database, updating all
> > fields
> > > in the instance. If you have a whole lot of fields in the Customer, one
> > > optimization would be to add logic to the loop that if the field is
> > > 'category' and the instance has not yet been saved, save it. This way it
> > is
> > > only saved once before adding category and once at the end of setting all
> > > attributes. This will probably be a better solution, and will hit the
> > > database only twice instead of <num_categories>+1 times:
>
> > > class InscriptionWizard(SessionWizardView):
> > >     def done(self, form_list, **kwargs):
> > >         instance = Customer()
> > >         for form in form_list:
> > >             for field, value in form.cleaned_data.iteritems():
> > >                 if field == 'category' and instance.id == None: # if
> > this
> > > is a category, and the instance has not yet been saved, save it so it has
> > > an id.
> > >                     instance.save()
> > >                 setattr(instance, field, value)
> > >         instance.save()
>
> > > Happy coding!
>
> > > Furbeenator
>
> > > On Wed, Nov 2, 2011 at 12:00 PM, youpsla <youp...@gmail.com> wrote:
> > > > Oupsss, another question in the step by step:
>
> > > > 1 class InscriptionWizard(SessionWizardView):
> > > > 2    def done(self, form_list, **kwargs):
> > > > 3        instance = Customer()
> > > > 4        for form in form_list:
> > > > 5            for field, value in form.cleaned_data.iteritems():
> > > > 6                if field == 'category':
> > > > 7                    instance.save()
> > > > 8                setattr(instance, field, value)
> > > > 9        instance.save()
>
> > > > Line 7 : Will save in the DB all fields that have been already
> > > > iterated. Then I suppose the instance.save() will not clear
> > > > informations affected by the setattr() otherwise the PK is lost ...
> > > > and the Line 9 doesn't know wich PK to use ....
>
> > > > Then I suppose the Line 9 will save all informations of the form,
> > > > those which have been already saved by Line 7 and add category. Then I
> > > > suppose Django will perform an "UPDATE" rather than an "INSERT" SQL
> > > > statement ?
>
> > > > Is it right ?
>
> > > > Again, regards for the time spend to answer.
>
> > > > Alain
>
> > > > On 2 nov, 19:03, Furbee <furbeena...@gmail.com> wrote:
> > > > > In your Customer model there are fields which cannot be Null, so you
> > > > cannot
> > > > > instance.save() before setting those properties. So, you may have to
> > > > check
> > > > > for the category field in your loop and if it is category, save the
> > > > > instance first. Something like the following:
>
> > > > > views.py (in clients application)
> > > > > ---------------------------------------------
> > > > > class InscriptionWizard(SessionWizardView):
> > > > >    def done(self, form_list, **kwargs):
> > > > >        instance = Customer()
> > > > >        for form in form_list:
> > > > >            for field, value in form.cleaned_data.iteritems():
> > > > >                if field == 'category':
> > > > >                    instance.save()
> > > > >                setattr(instance, field, value)
> > > > >        instance.save()
> > > > > ---------------------------------------------
>
> > > > > This would of course depend on your ordering of the fields. In other
> > > > words,
> > > > > category would have to be the first Allow Null field in your model,
> > > > because
> > > > > you cannot save() until all Not Null fields have a value. If you
> > cannot
> > > > > order these fields so the category is last, you may have to do
> > something
> > > > > like:
>
> > > > > views.py (in clients application)
> > > > > ---------------------------------------------
> > > > > class InscriptionWizard(SessionWizardView):
> > > > >    def done(self, form_list, **kwargs):
> > > > >        instance = Customer()
> > > > >        for form in form_list:
> > > > >            for field, value in form.cleaned_data.iteritems():
> > > > >                if field != 'category':
> > > > >                    setattr(instance, field, value)
> > > > >        instance.save()
> > > > >        for form in form_list:
> > > > >            for field, value in form.cleaned_data.iteritems():
> > > > >                if field == 'category':
> > > > >                    setattr(instance, field, value)
> > > > > ---------------------------------------------
>
> > > > > I'm sure there is a MUCH more elegant way of getting just the
> > categories
> > > > > from the forms and field/value pairs, this is brute force (not very
> > > > > scalable for large number of fields), but should work. Anybody else
> > > > please,
> > > > > show code that could get the specific forms and field/values for
> > > > categories.
>
> > > > > Furbeenator
>
> > > > > On Wed, Nov 2, 2011 at 10:28 AM, youpsla <youp...@gmail.com> wrote:
> > > > > > Hello,
> > > > > > i'm currently doning a website where user can register (without
> > > > > > password, without auth module of Django). They put some
> > informations
> > > > > > and at the end (Step5Form) do multiple choices by clicking on
> > > > > > checkboxes. When I click on validate on the last step I've
> > "instance
> > > > > > needs to have a primary key value before a many-to-many
> > relationship
> > > > > > can be used" error. I've search the web to find a solution but
> > ..... :-
> > > > > > (
>
> > > > > > Here is my code:
>
> > > > > > models.py for Customer (in clients application)
> > > > > > ---------------------------------------------
> > > > > > class Customer (models.Model):
>
> > > > > >    email_adresse = models.EmailField(max_length=255, unique=True)
> > > > > >    some fields ..... for Step2 to Step4 of the form
> > > > > >    category = models.ManyToManyField(Categories)
> > > > > > ---------------------------------------------
>
> > > > > > models.py for categories (in categories application)
> > > > > > ---------------------------------------------
> > > > > > class Categories (models.Model):
> > > > > >    category = models.CharField(max_length=200)
>
> > > > > >    def __unicode__(self):
> > > > > >        return unicode(self.category)
> > > > > > ---------------------------------------------
>
> > > > > > The ManyToMany field has created(syncdb) a table
> > > > > > clients_customer_category with the following columns:
> > > > > >        1       id                      int(11)
> > > > > > AUTO_INCREMENT
> > > > > >        2       customer_id     int(11)
> > > > > >        3       categories_id   int(11)
>
> > > > > > urls.py
> > > > > > ---------------------------------------------
> > > > > > urlpatterns = patterns('',
> > > > > >    (r'^clients/$', InscriptionWizard.as_view([Step1Form, Step2Form,
> > > > > > Step3Form, Step4Form, Step5Form])),
> > > > > > )
> > > > > > ---------------------------------------------
>
> > > > > > forms.py (in clients application)
> > > > > > ---------------------------------------------
> > > > > > from django import forms
> > > > > > from clients.models import Customer
> > > > > > from categories.models import Categories
>
> > > > > > class Step1Form(forms.Form):
> > > > > >    email_adresse = forms.EmailField(max_length=255)
>
> > > > > > class Step5Form(forms.Form):
> > > > > >    category =
> > > > > > forms.ModelMultipleChoiceField(queryset=Categories.objects.all(),
> > > > > > widget=forms.CheckboxSelectMultiple, required=True)
>
> > > > > > views.py (in clients application)
> > > > > > ---------------------------------------------
> > > > > > class InscriptionWizard(SessionWizardView):
> > > > > >    def done(self, form_list, **kwargs):
> > > > > >        instance = Customer()
> > > > > >        for form in form_list:
> > > > > >            for field, value in form.cleaned_data.iteritems():
> > > > > >                setattr(instance, field, value)
> > > > > >        instance.save()
> > > > > > ---------------------------------------------
>
> > > > > > I got the following error:
> > > > > > ---------------------------------------------
> > > > > > Request Method: POST
>
> ...
>
> plus de détails »

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to