Reputation: 1076
new to python/django. I am using class based views. I have objects named Video
that I want to be able to create ratings for. I have a DetailView
for the Video
, and on that same page I have a link that brings you to another page to rate the Video
that was on the DetailView
(because I have not wanted to mess with Mixins yet to have it all on the same page).
How can I keep/get the reference to the DetailView
Video
object so when I submit the rating it knows that the rating is for Video
object that was on the DetailView
?
models.py
class Video(models.Model):
title = models.CharField(max_length=100, default="Community Video ")
class Rating(models.Model):
rate_choice = ((1, '1'), (2, '2'), (3, '3'), (4, '4'), (5, '5'))
rate_value = models.IntegerField(default=5, choices=rate_choice)
video = models.ForeignKey('Video', related_name='video', null=True, default=1)
views.py
class VideoView(DetailView):
model = Video
template_name = 'video_view.html'
class RatingView(CreateView):
model = Rating
template_name = 'rating_create.html'
fields = ['rate_value', 'video']
Basically I want the primary key of the Video
to go with me when I go from the video_view
to rating_create
template. I am thinking of just using function based views, class views are confusing me.
urls.py:
urlpatterns = [
url(r'^upload', UploadVideo.as_view(), name='upload'),
url(r'^(?P<pk>[0-9]+)/$', VideoView.as_view(), name='videoview'),
url(r'^(?P<pk>[0-9]+)/ratings', RatingView.as_view(success_url='success_yea'), name='rating_view'),
url(r'^success', upload, name='success_yea')
]
Upvotes: 2
Views: 2160
Reputation: 11736
You can pass this as a parameters on your urls.py, something like
url(r'^(?P<pk>[0-9]+)/ratings', RatingView.as_view(),
In the video_view.html
template file reverse it with the current video id.
And then in your view:
class RatingView(CreateView):
model = Rating
template_name = 'rating_create.html'
fields = ['rate_value']
success_url = reverse_lazy('success_yea')
def form_valid(self, form):
form.instance.video = get_object_or_404(Video, id=self.kwargs.get('pk'))
return super(RatingView, self).form_valid(form)
Upvotes: 2
Reputation: 308999
Your url looks good, you already have the pk there.
url(r'^(?P<pk>[0-9]+)/ratings', RatingView.as_view(), name='rating_view'),
In your view, you should remove video
from the list of fields because you don't want it to be editable.
You can then override form_valid
and set video
on the form's instance.
from django.shortcuts import get_object_or_404
from django.urls import reverse
class RatingView(CreateView):
model = Rating
template_name = 'rating_create.html'
fields = ['rate_value']
# I recommend moving this here, to avoid splitting config between the view and the urls.
# You need reverse_lazy to turn the pattern name into the url
success_url = reverse_lazy('success_yea')
def form_valid(self, form):
# Fetch video from the db to check it exists
video = get_object_or_404(Video, pk=self.kwargs['pk'])
form.instance.video = video
return super(RatingView, self).form_valid(form)
One disadvantage of the above code is that you only validate the pk in the url when the form is valid. If you would prefer to validate the primary key for all requests, you could move that code into the dispatch method.
class RatingView(CreateView):
model = Rating
template_name = 'rating_create.html'
fields = ['rate_value']
success_url = reverse_lazy('success_yea')
def dispatch(self, request, *args, **kwargs):
# Fetch video from the db to check it exists
self.video = get_object_or_404(Video, pk=self.kwargs['pk'])
return super(RatingView, self).dispatch(request, *args, **kwargs)
def form_valid(self, form):
form.instance.video = self.video
return super(RatingView, self).form_valid(form)
Upvotes: 0