When a User successfully makes a POST
request to edit their own question, they are redirected to a detail page for the same question. When a subsequent GET
request is sent to the PostedQuestionPage
view after editing a question, the following ValueError is raised when trying retrieve an instance with get_object_or_404()
:
ValueError: Field 'id' expected a number but got '<built-in function id>'
Why is PostedQuestionPage
being passed '<built-in function id>'
and not a value that is suppose to represent a question instance id?
> c:\..\posts\views.py(137)get()
-> question = get_object_or_404(Question, id=question_id)
(Pdb) ll
134 def get(self, request, question_id):
135 import pdb; pdb.set_trace()
136 context = self.get_context_data()
137 -> question = get_object_or_404(Question, id=question_id)
138 context['question'] = question
139 return self.render_to_response(context)
(Pdb) question_id
'<built-in function id>'
(Pdb) n
ValueError: Field 'id' expected a number but got '<built-in function id>'.
> c:\..\posts\views.py(137)get()
-> question = get_object_or_404(Question, id=question_id)
(Pdb) n
--Return--
> c:\..\posts\views.py(137)get()->None
-> question = get_object_or_404(Question, id=question_id)
class TestPostEditQuestionPage(TestCase):
'''Verify that a message is displayed to the user in the event
that some aspect of the previous posted question was edited.'''
@classmethod
def setUpTestData(cls):
cls.user = get_user_model().objects.create_user(
username="OneAndOnly",
password="passcoderule"
)
profile = Profile.objects.create(user=cls.user)
tag = Tag.objects.create(name="TagZ")
question = Question.objects.create(
title="This is Question Infinity",
body="The is the content body for This is Question Infinity",
profile=profile
)
question.tags.add(tag)
cls.data = {
"title": "This is Question Zero",
"body": "The is the content body for This is Question Infinity",
"tags_0": "TagN", "tags_1": "TagZ"
}
def test_posted_question_content_changed(self):
self.client.force_login(self.user)
response = self.client.post(
reverse("posts:edit", kwargs={"question_id": 1}),
data=self.data
)
self.assertRedirects(
response, reverse("posts:question", kwargs={"question_id": 1}),
status_code=303
)
class TestGetEditQuestionPage(TestCase):
@classmethod
def setUpTestData(cls):
cls.user = get_user_model().objects.create_user("The_User_000")
profile = Profile.objects.create(user=cls.user)
tag = Tag.objects.create(name="TagABC")
question = Question.objects.create(
title="What is the difference between A & B?",
body="I'm trying to figure out this out. Can you help me?",
profile=profile
)
question.tags.add(tag)
def test_user_question_instance_populates_edit_form(self):
self.client.force_login(self.user)
response = self.client.get(
reverse("posts:edit", kwargs={
'question_id': 1
})
)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "posts/ask.html")
self.assertContains(response, "Edit your question")
from django.views.generic.base import TemplateView
from django.contrib import messages
from django.db import IntegrityError
from django.shortcuts import get_object_or_404
from django.urls import reverse
from authors.models import Profile
from .forms import SearchForm, QuestionForm, AnswerForm
from .models import Question, Tag, Answer
from django.http import HttpResponseRedirect
from authors.http_status import SeeOtherHTTPRedirect
class Page(TemplateView):
def get_context_data(self, **kwargs):
context = super().get_context_data()
context['search_form'] = SearchForm()
return context
class QuestionListingPage(Page):
template_name = "posts/main.html"
extra_context = {
"title": "Top Questions",
"query_buttons": ["Interesting", "Hot", "Week", "Month"]
}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['questions'] = Question.objects.all()
return context
def get(self, request):
context = self.get_context_data()
return self.render_to_response(context)
class AskQuestionPage(Page):
template_name = "posts/ask.html"
extra_context = {
'title': "Ask a public question"
}
def attach_question_tags(self, tags):
question_tags = []
for name in tags:
try:
tag = Tag.objects.get(name=name)
except Tag.DoesNotExist:
tag = Tag.objects.create(name=name)
finally:
question_tags.append(tag)
return question_tags
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['form'] = QuestionForm
return context
def post(self, request):
context = self.get_context_data()
form = context['form'](request.POST)
if form.is_valid():
tags = self.attach_question_tags(form.cleaned_data.pop("tags"))
try:
question = form.save(commit=False)
question.profile = request.user.profile
question.save()
except IntegrityError:
form.add_error(None, "This post is already posted")
context['form'] = form
else:
question.tags.add(*tags)
form.save_m2m()
return SeeOtherHTTPRedirect(
reverse("posts:question", kwargs={"question_id": question.id})
)
return self.render_to_response(context)
class EditQuestionPage(AskQuestionPage):
template_name = "posts/ask.html"
extra_context = {
'title': "Edit your question"
}
def get(self, request, question_id):
question = get_object_or_404(Question, id=question_id)
context = self.get_context_data()
context['form'] = context['form'](instance=question)
return self.render_to_response(
context, headers={
'Content-Type': "text/html"
}
)
def post(self, request, question_id):
question = get_object_or_404(Question, id=question_id)
context = self.get_context_data()
form = context['form'](request.POST, instance=question)
if form.is_valid():
if form.has_changed():
messages.success(request, "Question updated!")
x = form.cleaned_data.pop("tags")
tags = self.attach_question_tags(x)
question = form.save()
question.tags.set(tags)
return SeeOtherHTTPRedirect(reverse(
"posts:question", kwargs={"question_id": id}
))
return self.render_to_response(context)
class PostedQuestionPage(Page):
template_name = "posts/question.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['answer_form'] = AnswerForm
return context
def get(self, request, question_id):
context = self.get_context_data()
question = get_object_or_404(Question, id=question_id)
context['question'] = question
return self.render_to_response(context)
def post(self, request, question_id):
question = get_object_or_404(Question, id=question_id)
context = super.get_context_data()
form = context['answer_form'](request.POST)
if form.is_valid():
form.cleaned_data.update({"profile": request.user.profile})
answer = Answer.objects.create(
**form.cleaned_data, question=question
)
return SeeOtherHTTPRedirect(
reverse("posts:question", kwargs={
"question_id": answer.question.id
})
)
class EditPostedAnswerPage(PostedQuestionPage):
def get(self, request, question_id, answer_id):
context = super().get_context_data()
question = get_object_or_404(Question, id=question_id)
answer = get_object_or_404(Answer, id=answer_id)
context.update({
"answer_form": context['answer_form'](instance=answer),
'question': question,
'answer': answer
})
return self.render_to_response(context)
def post(self, request, question_id, answer_id):
context = super().get_context_data()
question = get_object_or_404(Question, id=question_id)
answer = get_object_or_404(Answer, id=answer_id)
# import pdb; pdb.set_trace()
if context['answer_form'](request.POST, instance=answer).is_valid():
return SeeOtherHTTPRedirect(
reverse("posts:question", kwargs={
'question_id': 1
})
)
CodePudding user response:
class EditQuestionPage(AskQuestionPage):
...
def post(self, request, question_id):
...
return SeeOtherHTTPRedirect(reverse(
"posts:question", kwargs={"question_id": id}
))
This is the problem. You're passing the built-in function id
as question_id
.