Reputation: 738
I have an item. An item can have many reviews. I expect a review to be created within the context of an item. Therefore, I capture the pk from the url and add it to the context.
This is where I get stuck, I'm unsure how to access the context in form_valid and, more importantly, I'm concerned the path I'm trying to go down seems hacky.
Essentially when the user prepares to submit a review, the application will know what item it's in reference to. What's the most pythonic/django-onic way to do this?
Models
class Item(models.Model):
name = models.CharField(max_length=100)
source = models.ForeignKey('Source')
class Review(models.Model):
rating = models.CharField(max_length=30)
value = models.CharField(max_length=30)
date = models.DateField(auto_now_add=True)
comment = models.CharField(blank=True,max_length=100)
item = models.ForeignKey(Item,blank=True)
user = models.ForeignKey(User)
Urls
url(r'^review/create/item/(?P<itempk>\d+)',views.ReviewCreate.as_view(),name='review_create'),
Views
class ReviewCreate(CreateView):
model = Review
fields = ['rating', 'value', 'comment']
def get_context_data(self, **kwargs):
context = super(ReviewCreate, self).get_context_data(**kwargs)
itempk = self.kwargs['itempk']
item = get_object_or_404(Item, pk=itempk)
context['item'] = item
return context
def form_valid(self, form):
review = form.save(commit=False)
review.user = self.request.user
context = super(ReviewCreate, self).get_context_data(**kwargs) '''doesn't work'''
review.item = context['item']
return super(ReviewCreate, self).form_valid(form)
template_name = 'food/review_form.html'
Upvotes: 1
Views: 62
Reputation: 308849
The get_context_data
method is meant to return the context for a template, so I agree that calling it in form_valid
is a bit hacky.
You could fetch the item in the dispatch
method instead and store it as self.item
. Then you can retrieve the item in get_context_data
and form_valid
.
In form_valid
you can modify form.instance
- that way you don't have to save with commit=False
.
class ReviewCreate(CreateView):
model = Review
fields = ['rating', 'value', 'comment']
def dispatch(self, request, *args, **kwargs):
itempk = self.kwargs['itempk']
self.item = get_object_or_404(Item, pk=itempk)
return super(ReviewCreate, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(ReviewCreate, self).get_context_data(**kwargs)
context['item'] = self.item
return context
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.item = self.item
return super(ReviewCreate, self).form_valid(form)
template_name = 'food/review_form.html'
Upvotes: 1