3

Let's say I have a webpage that displays songs. And let's say there are public and private songs. Public songs are available for everyone to see, while private songs are songs that a certain user has created and are only available for him to see. So the user should only see those songs with the owner_id == NULL and owner_id == currently_logged_in_user_id (his own id)

Model:

import ....

    class Song(models.Model):
        name = models.CharField(max_length=100)    
        duration = models.IntegerField(max_length=15)
        owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)

        def __unicode__(self):
            return self.name

View:

from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from songapp.models import Song
from songapp.forms import SongInfoForm

@login_required
def song_info(request):
    song = get_object_or_404(Box)
    song_status = song.get_status()
    form = SongInfoForm(initial={'song_list': song.song_list})

    return render(request, 'songapp/song_info.html',
        {'form': form, 'song': song, 'song_status': song_status})

Form:

    from django import forms
    from django.forms import ModelChoiceField

    from songapp.models import Song


    class SongInfoForm(forms.Form):

-->     selected_songs = Song.objects.filter(owner=None) | Song.objects.filter(owner=3)
        song_list = ModelChoiceField(queryset=selected_songs, required=False)

Note the line with the arrow in the Form file. This is where the problem lies. The code works now, but the

(owner = 3)

is hardcoded. I know for a fact that my users id is 3. But I want it to work properly. It should be something like this:

(owner = currently_logged_in_user.id)

I'm still very new to Django and Python and I don't know how to pass the users id to the SongInfoForm FormModel.

Saša Kalaba
  • 4,241
  • 6
  • 29
  • 52

2 Answers2

5

I've figured it out.

In views.py change:

form = SongInfoForm(initial={'song_list': song.song_list}, user=request.user)

And thanks to the answers before and this example django form: Passing parameter from view.py to forms gives out error I've came up with this, and it works like a charm.

In forms.py

class SongInfoForm(forms.Form):
    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user')
        super(SongInfoForm, self).__init__(*args, **kwargs)
        self.fields['song_list'] = forms.ModelChoiceField(queryset=Song.objects.filter(owner=None) | Song.playlist.objects.filter(owner=user), required=False)
Community
  • 1
  • 1
Saša Kalaba
  • 4,241
  • 6
  • 29
  • 52
0

OK, my bad. Didn't read enought to see problem lies in the form, But according to this post: https://stackoverflow.com/a/5122029/2695295 you could rewrite your for like this:

class SongInfoForm(forms.Form):
    def __init__(self, user, *args, **kwargs):
        self.user = user
        super(SongInfoForm, self).__init__(*args, **kwargs)

    selected_songs = Song.objects.filter(owner=None) | Song.objects.filter(owner=user.id)
    song_list = ModelChoiceField(queryset=selected_songs, required=False)

and then in view create your form like this:

form = SongInfoForm(request.user, initial={'song_list': song.song_list})

this way form object should have access to user.

Community
  • 1
  • 1
Dawid
  • 385
  • 9
  • 19
  • I get an error "name 'request' is not defined". I've tried this before and it didn't work. Maybe I need to do an import like "from django.http import HttpRequest"? Keep in mind i'm very new to this. – Saša Kalaba Jul 14 '15 at 12:03
  • no, cause `request` is an object passed to the view here: `def song_info(request):` and since you're using it in render: `return render(request, 'songapp/song_info.html', [...]` it should be working. And if you're using `./manage.py runserver` with debug there should be full trace where the problem occurs. And since my answer comes straight from Django 1.7 documentation I don't understand the down vote. – Dawid Jul 14 '15 at 12:09
  • I haven't downvoted you, but here's an upvote to balance it out :/. Exception Location reports that the problem is in the forms.py file on the exact line as stated above. Still not working, but thanks for trying. – Saša Kalaba Jul 14 '15 at 12:17
  • 1
    @Dawid no, this can't possibly work. That line is not in the view or the template, but in the definition of the form class. There is no access to the request there. – Daniel Roseman Jul 14 '15 at 12:21
  • I've came across this solution in the last half hour myself, and I still get an error. I've modified my code as you've posted it, but I get a "name 'user' is not defined" error on the "form = SongInfoForm(request.user, initial={'song_list': song.song_list})" line – Saša Kalaba Jul 14 '15 at 12:52