ratrace123
ratrace123

Reputation: 1076

pass object primary key across templates django

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

Answers (2)

Mounir
Mounir

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

Alasdair
Alasdair

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

Related Questions