I'm a new programmer attempting to put in a "submit comment" page in my project using a generic CreateView. The page displays properly when it first loads, but after clicking the form's "submit" button, I get a "TypeError at /blog/blog/4/create - cannot unpack non-iterable int object."
Here is the generic view in question:
class BlogCommentCreate(LoginRequiredMixin, CreateView):
model = Comment
template_name = 'blog/comment_create_form.html'
fields = ['content',]
def get_context_data(self, **kwargs):
context = super(BlogCommentCreate, self).get_context_data(**kwargs)
context['blogpost'] = get_object_or_404(BlogPost, pk = self.kwargs['pk'])
return context
def form_valid(self, form):
form.instance.comment_author = self.request.user
form.instance.blogpost = get_object_or_404(BlogPost, self.kwargs['pk'])
return super(BlogCommentCreate, self).form_valid(form)
def get_success_url(self):
return reverse('blogpost-detail', kwargs={'pk': self.kwargs['pk'],})
Here are the relevant url patterns. "comment_create" is the create page that is giving me issues with form submission, and "blogpost-detail" is where I'm trying to redirect to:
urlpatterns = [
path('blog/<int:pk>', views.BlogPostDetailView.as_view(), name='blogpost-detail'),
path('blog/<int:pk>/create', views.BlogCommentCreate.as_view(), name='comment_create')
]
And finally, here is the comment model:
class Comment(models.Model):
date_created = models.DateField(blank=False, default = date.today)
content = models.TextField(max_length=200)
comment_author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
blogpost = models.ForeignKey('BlogPost', on_delete=models.CASCADE)
def __str__(self):
return self.content
Things I have tried: 1. Renaming parameters in my get_object_or_404 call that might overlap with built-in django keywords (as suggested in another thread here) 2. Renaming model fields and playing with capitalization in the views. Ran makemigrations before and after this step 3. (After trying 1 and 2) Wiping and recreating my blogpost objects 4. Getting rid of the parameters in super(), as it seems like they might not be necessary?
The only thing that the error text makes me think of is that the context might be receiving **kwargs as a list instead of a bunch of individual parameters. But I don't know enough about the get_context_data or form_valid methods to fix this, as I am just going off of the Django docs and code snippets I found.
You should specify the pk
in get_object_or_404
as a named parameter:
form.instance.blogpost = get_object_or_404(BlogPost, pk=self.kwargs['pk'])
or perhaps it is simpler, to just pas the primary key as blogpost_id
:
form.instance.blogpost_id = self.kwargs['pk']
You can pass positional parameters to get_object_or_404
, but these are Q
objects [Django-doc], for example to do more sophisticated filtering.