0

I'm trying to upgrade a Django project from Django(1.10) to Django(2.1), while doing that I'm just stuck at one error, where I was using the request.user.pk to pass a user create an object.

Here's what I have, so far:

From models.py:

class TaggedArticle(models.Model):
    user = models.ForeignKey(User, related_name='tagging', on_delete=models.CASCADE)
    email = models.EmailField(max_length=255)
    category_fit = models.CharField(choices=choices, max_length=255)
    article = models.ForeignKey(Article, related_name='articles', on_delete=models.CASCADE)
    link = models.URLField(max_length=255,)
    relevant_feedback = models.TextField(blank=True)
    category = models.CharField(max_length=255,)
    created_at = models.DateTimeField(default=timezone.now, editable=False)

From forms.py:

class TagForm(forms.ModelForm):
    class Meta:
        model = TaggedArticle
        fields = ('user', 'category_fit', 'article', 'link', 'relevant_feedback', 'category',)
        widgets = {
            'category_fit': forms.RadioSelect()
        }

And From views.py:

class TagView(LoginRequiredMixin, generic.CreateView):
    form_class = forms.TagForm

    def post(self, request, *args, **kwargs):
        try:
            post_data = request.POST.copy()
            post_data.update({'user': request.user.pk})
            print(post_data.values)
            form = forms.TagForm(post_data)
            if form.is_valid():
                tag = form.save(commit=False)
                tag.user = request.user
                tag.email = request.user.email
                tag.save()
                request.session['user'] = tag.user
                request.session['email'] = tag.email
            else:
                print(form.errors)
                return HttpResponse(form.errors, status=400)

            print('going to redirect after successful tagging.')
            return HttpResponseRedirect(reverse('users:dashboard'))

        except Exception as exp:
            logging.error(exp)
            print('error is: {}'.format(exp))
            return HttpResponse(exp, status=400)

Update: Here's the HTML form from template:

<form class="omb_loginForm" action="{% url 'users:tagged' %}" method="POST">
      {% csrf_token %}
      <table class="table">
         <thead><h4> Tag this Article:</h4></thead>
         <tbody>
            <tr>
               <th>Reviewer:</th>
               <td></td>
               <td>{{ user.username }}</td>
             </tr>
             <tr>
                <th>No of Article Reviewed:</th>
                <td></td>
                <td>{{ user.tagging.all |length }}</td>
              </tr>
              <tr>
                 <th>Category:</th>
                 <td></td>
                 <td>{{ art.category }}
                     <input type="hidden" value="{{ art.id }}" name="article"/>
                     <input type="hidden" value="{{ art.link }}" name="link"/>
                     <input type="hidden" value="{{ art.category }}" name="category"/>
                 </td>
              </tr>
              <tr>
                <th>Does the text of this article fit in this category?</th>
                   <td><label class="radio-inline"><input type="radio" name="category_fit"
                                                                            value="yes">Yes</label></td>
                    <td><label class="radio-inline"><input type="radio" name="category_fit"
                                                                               value="no">No</label></td>
                    <td><label class="radio-inline"><input type="radio" name="category_fit"
                                                                               value="not sure">Not Sure</label>
                     </td>
                </tr>
                <tr>
                   <th><label for="comment">Copy and then paste in a relevant sentence for categorization:</label></th>
                      <td colspan="3">
                          <textarea class="form-control" rows="7" id="comment"
                                                      name="relevant_feedback"></textarea>
                      </td>
                  </tr>
              </tbody>
         </table>
         <button class="btn btn-lg btn-primary btn-block" type="submit">Tag</button>
</form>

So, on POST request it returns the error below as:

TypeError: Object of type 'User' is not JSON serializable

When I print the form.errors then it prints:

<ul class="errorlist"><li>user<ul class="errorlist"><li>Select a valid choice. That choice is not one of the available choices.</li></ul></li></ul>

So, what can be wrong here?

Thanks in advance!

Abdul Rehman
  • 5,326
  • 9
  • 77
  • 150
  • Can you show the template being used and what options are being displayed while choosing `user`? – Sanip Mar 03 '19 at 08:42
  • the user will be the current logged in user, that's why I'm not passing it from the template and adding it into the `request.POST` here in the view. – Abdul Rehman Mar 03 '19 at 08:43
  • Then why do you require the `user` field in the form? – Sanip Mar 03 '19 at 08:45
  • Because I need to save the user's related `TaggedArticle` as you can see I have mentioned the `related_name` attribute in the model. – Abdul Rehman Mar 03 '19 at 08:46
  • can you show your template? – Sanip Mar 03 '19 at 09:14
  • Hi @Sanip I have added the HTML form above in the question, take a look, please! – Abdul Rehman Mar 03 '19 at 09:23
  • Can you find out which line is generating this error? Is it from post_data.update({'user':request.user.pk}) or tag.user=request.user? – Sanip Mar 03 '19 at 09:27
  • I have printed a statement inside the `if form.is_valid()` as `print('inside valid')` and it's printing and another statement at the end of `try` you can see in the code, this statement is also printed. So, I think it's something happening on redirect. – Abdul Rehman Mar 03 '19 at 09:31
  • I have edited my answer, please have a look at it. I think the problem is not because of form validation but because of the sessions being used. – Sanip Mar 03 '19 at 09:33

1 Answers1

1

Since the user in your TaggedArticle instance is the currently logged in user, I think you don't need to specify the user in the TagForm. You can remove the user from the fields of TagForm:

class TagForm(forms.ModelForm):
    class Meta:
        model = TaggedArticle
        fields = ('category_fit', 'article', 'link', 'relevant_feedback', 'category',)
        widgets = {
            'category_fit': forms.RadioSelect()
        }

Now since your view automatically saves the currently logged in user as user for TaggedArticle, no more work is needed and the error might also not occur.

EDIT: Maybe the error is generated by the line:

request.session['user'] = tag.user

Here the User object is not JSON serializable and Django uses JSON to serialize the session data after version 1.6. So you might need to store the user id instead of the User object. Example:

request.session['user'] = tag.user.id
Sanip
  • 1,772
  • 1
  • 14
  • 29