RunLoop
RunLoop

Reputation: 20376

Django field name conflicts on save

I have a template which displays a form with data from 2 models. Both models contain an attribute called "name". The issue is that when I save, the incorrect value for "name" from the form is saved for appuser model. How can I get the correct values for each of the 2 forms for the "name" field please?

View see (#ISSUE)

    class FarmCreateView(CreateView):
        template_name = 'directory/farm_registration.html'
        model = Appuser
        success_url = '/'

        def get_context_data(self, **kwargs):
            context = super(FarmCreateView, self).get_context_data(**kwargs)
            context['farm'] = FarmForm()
            context['appuser'] = FarmUserCreateForm()
            return context

        def post(self, request, *args, **kwargs):
            farm_form = FarmForm(self.request.POST)
            appuser_form = FarmUserCreateForm(self.request.POST)

            if farm_form.is_valid() and appuser_form.is_valid():
                # Save the appuser
                new_user = appuser_form.save(commit=False)
                new_user.name = appuser_form.cleaned_data.get('name') 

# ISSUE I would expect the line above to return the name from the
# appuser_form, but instead it return the name from the farm_form
                new_user.save()

                # Save the farm
                new_farm = farm_form.save(commit=False)
                new_farm.appuser = new_user; 
                new_farm.save()
                farm_form.save_m2m() # This is needed because we 
# initially save with commit=false - it's just the way django works

                # Log user in after registration
                new_user_login = authenticate(email=request.POST['email'], 
                   password=request.POST['password'])
                login(request, new_user_login)

                return HttpResponseRedirect('/')
            else:
                return render_to_response('directory/farm_registration.html', {'farm': 
                   farm_form, 'appuser': appuser_form}, 
                   context_instance=RequestContext(request))

Template extract

<div class="pure-g">
   <div class="pure-u-1-2 {{appuser.name.css_classes}}" style="margin-bottom: 20px;">{{appuser.name}}</div>
    <div class="pure-u-1-2 {{appuser.surname.css_classes}}"><div style="float:right;">{{appuser.surname}}</div></div>
 <div class="pure-u-1-2 {{appuser.email.css_classes}}" style="margin-bottom: 20px;">{{appuser.email}}</div>
   <div class="pure-u-1-2 {{appuser.phone_number.css_classes}}"><div style="float:right;">{{appuser.phone_number}}</div></div>
   <div class="pure-u-1-2 {{appuser.password.css_classes}}" style="margin-bottom: 20px;">{{appuser.password}}</div>
   <div class="pure-u-1-2 {{appuser.password1.css_classes}}"><div style="float:right;">{{appuser.password1}}</div></div>
</div>
 <!-- Farm Info -->
<div style="height:28px; position:relative; text-align:center; margin-bottom:10px; margin-left:1px; margin-right:1px">
 <div class="page_section_strikethrough"></div>    
  <div class="page_section_heading" style="background:rgb(246,246,246)">FARM INFO</div>
 </div>
  <div class="pure-g">
  <div class="pure-u-1-1 {{farm.name.css_classes}}" style="margin-bottom: 20px;">{{farm.name}}</div>

Upvotes: 1

Views: 220

Answers (2)

Amit Yadav
Amit Yadav

Reputation: 1861

Use prefix in the form, like this:

context['farm'] = FarmForm(prefix="farm_form")
context['appuser'] = FarmUserCreateForm(prefix='farm_user_create')

Upvotes: 2

user707650
user707650

Reputation:

Check the name attribute in the rendered forms, in particular those for the {{ appuser.name }} and {{ farm.name }} input elements.

I guess they are the same, because I don't think there is be namespacing going on inside the rendered template. Thus, there'll be two <input name="name" ...> elements, and upon POST, one will overwrite the other.

Hence when you're creating the bound forms inside the post(...) method, you fill both forms with the same name. You can verify the latter by printing the value of self.request.POST when running the development server: you should only see one name key.

Upvotes: 0

Related Questions