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
> > > > Request URL:    http://127.0.0.1:8010/clients/
> > > > Django Version: 1.3.1
> > > > Exception Type: ValueError
> > > > Exception Value:
> > > > 'Customer' instance needs to have a primary key value before a many-to-
> > > > many relationship can be used.
> > > > ...............
> > > > ...............
> > > > ▶ Local vars
> > > > C:\dev\Flash\clients\views.py in done
> > > >                setattr(instance, field, value) ...
> > > > ---------------------------------------------
>
> > > > What I've tried:
> > > > 1)I've search the web and didn't find any way to solve this. I've read
> > > > on save_m2m() wich doesn't apply here as far I understand because no
> > > > "commit=False" and this form is not a ModelForm.
>
> > > > 2)I've trie to save in 2 steps with the hope an id has been set in the
> > > > DB:
> > > > -First step : for form in form_list[0:3]: ...... instance.save()
> > > > -Second step :
> > > >        for form in form_list[4]:
> > > >            for field, value in form.cleaned_data.iteritems():
> > > >                instance.category.add(value)
>
> > > > I've the following error : 'BoundField' object has no attribute
> > > > 'cleaned_data' for the line "for field, value in
> > > > form.cleaned_data.iteritems():" in Second step.
>
> > > > Then I can maybe split my form in 2 forms, one from Step0 to Step3 and
> > > > another one for Step4 and passing the id_customer in teh session but
> > > > maybe there is a solution to solve this issue in one form.
>
> > > > Help will be really appreciated.
>
> > > > I apologize if my explanations are not enough clear (and for my
> > > > english) and feel free to ask informations.
>
> > > > Regards
>
> > > > Alain
>
> > > > --
> > > > 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
>
> ...
>
> 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