title: Django CRUD update object with many to one relationship to user
body: <p>I followed along the awesome tutorial <a href="https://simpleisbetterthancomplex.com/tutorial/2016/11/15/how-to-implement-a-crud-using-ajax-and-json.html" rel="nofollow noreferrer">How to Implement CRUD Using Ajax and Json</a> by Vitor Freitas.  For my project I have an object with a many to one relationship with the user that I want users to be able to add and update.  I can add the object, but when I try to update it throws a
  <code>ValueError: Cannot query "Case object": Must be "User" instance.</code></p>
  
  <p><strong>views.py</strong></p>
  
  <pre><code>def case_update(request, pk):
      case = get_object_or_404(Case, pk=pk)
      if request.method == 'POST':
          form = CaseForm(request.POST, instance=case)
      else:
          form = CaseForm(instance=case)
      return save_case_form(request, form, 'cases/includes/partial_case_update.html')
  </code></pre>
  
  <p>It breaks when I try to save the edit, but I am struggling to see a way around this.  To edit this case, I need the form to be an instance of this particular case as the user may have many cases.  When I set the instance to user, nothing happens, when I remove the instance altogether it obviously just makes a copy of the case so I have two of the same cases.</p>
  
  <p>I can post more code if necessary.  Thank you</p>
  
  <p><strong>EDIT</strong>
  I refactored my code using only the inlineformset and it is working... kind of.  I now can edit cases, but I still cannot edit a single case.  I continue to receive a <code>ValueError: Cannot query "Case object": Must be "User" instance</code> when I try to do an instance of <code>case = get_object_or_404(Case, pk=pk)</code>with the inlineformset.  When I change this to an instance of user it brings up all the cases of that particular user, but it saves correctly.  </p>
  
  <pre><code>def save_case_form(request, case_formset, template_name):
      data = dict()
  
      if request.method == 'POST':
          if case_formset.is_valid():
              case_formset.save()
              data['form_is_valid'] = True
              cases = Case.objects.all()
              data['html_case_list'] = render_to_string('cases/includes/partial_case_list.html', {
                  'cases': cases
              })
          else:
              data['form_is_valid'] = False
      context = {'case_formset' : case_formset}
      data['html_form'] = render_to_string(template_name, context, request=request)
      return JsonResponse(data)
  
  
  def case_create(request):
      if request.method == 'POST':
          case_formset = CaseFormset(request.POST, instance = request.user)
      else:
          case_formset = CaseFormset()
      return save_case_form(request, case_formset, 'cases/includes/partial_case_create.html')
  
  
  def case_update(request, pk):
      case = get_object_or_404(Case, pk=pk)
      if request.method == 'POST':
          case_formset = CaseFormset(request.POST, instance=request.user)
      else:
          case_formset = CaseFormset(instance=request.user)
      return save_case_form(request, case_formset, 'cases/includes/partial_case_update.html')
  </code></pre>
  
  <p><strong>forms.py</strong></p>
  
  <pre><code>class CaseForm(forms.ModelForm):
      class Meta:
          model = Case
          fields = ('title', 'publication_date', 'author', 'price', 'pages', 'case_type', )
  
  
  CaseFormset = inlineformset_factory(User,Case, 
                                      fields = ('title', 'publication_date', 
                                                'author', 'price', 
                                                'pages', 'case_type', ), 
                                      can_delete = False,
                                      extra = 1)
  </code></pre>
  
  <p><strong>EDIT</strong></p>
  
  <p>A non DRY implementation that works:</p>
  
  <p><strong>forms.py</strong></p>
  
  <pre><code>class CaseForm(forms.ModelForm):
      class Meta:
          model = Case
          fields = ('title', 'publication_date', 'author', 'price', 'pages', 'case_type', )
  
  
  CaseFormset = inlineformset_factory(User,Case, 
                                      fields = ('title', 'publication_date', 
                                                'author', 'price', 
                                                'pages', 'case_type', ), 
                                      can_delete = False,
                                      extra = 1)
  
  CaseFormsetUpdate = inlineformset_factory(User,Case, 
                                      fields = ('title', 'publication_date', 
                                                'author', 'price', 
                                                'pages', 'case_type', ), 
                                      can_delete = False,
                                      extra = 0)
  </code></pre>
  
  <p><strong>views.py</strong></p>
  
  <pre><code>def save_case_form(request, case_formset, template_name):
      data = dict()
  
      if request.method == 'POST':
          if case_formset.is_valid():
              case_formset.save()
              data['form_is_valid'] = True
              cases = Case.objects.all()
              data['html_case_list'] = render_to_string('cases/includes/partial_case_list.html', {
                  'cases': cases
              })
          else:
              data['form_is_valid'] = False
      context = {'case_formset' : case_formset}
      data['html_form'] = render_to_string(template_name, context, request=request)
      return JsonResponse(data)
  
  
  def case_create(request):
  
      if request.method == 'POST':
          case_formset = CaseFormset(request.POST, instance = request.user)
      else:
          case_formset = CaseFormset()
      return save_case_form(request, case_formset, 'cases/includes/partial_case_create.html')
  
  
  def case_update(request, pk):
  
      case = get_object_or_404(Case, pk=pk)
      if request.method == 'POST':
          case_formset = CaseFormsetUpdate(request.POST, instance=request.user)
      else:
          case_formset = CaseFormsetUpdate(instance=request.user, queryset = Case.objects.filter(pk=pk))
      return save_case_form(request, case_formset, 'cases/includes/partial_case_update.html')
  </code></pre>
  
  <p>I was unable to find a way to change the extra parameter on an inline formset when it is instantiated in views.  So I just made a second one with extra set to 0 and added that to my update case view.  I would still be interested in a better approach.</p>