I have got tracks working with the extra() function. I do the following: tracks.extra(select={'owned':'SELECT Count(*) FROM shop_track_owners WHERE track_id=shop_track.id and user_id='+str(user.id)})
This works great for tracks. However, how will I do this when I'm just passing a queryset of albums or artists to a template? The template uses {% for track in album.track_set.all %} which will get the tracks without the extra owned field added. Is there a way around this? I don't think adding another function to the model would do it because it can't get access to the user details so {% for track in album.track_set_nice.all %} where Album.track_set_nice adds the extra() bits wont work. Is there a way of manipulating album in the view so that track_set doesn't fire off a new query but accesses a pre-gathered set of tracks? As far as I can tell it doesn't seem to like me adding my own (non-database) variables to a method, so I don't *think* I can do something like: for album in albums: album.myTempTracks = album.track_set.extra(select={'owned':'SELECT Count(*) FROM shop_track_owners WHERE track_id=shop_track.id and user_id='+str(user.id)}) in the view. Does anyone know if there is a way to achieve this? I tried but it didn't seem to work. Any other suggestions would be much appreciated. On Nov 13, 10:19 pm, Matt Schinckel <matt.schinc...@gmail.com> wrote: > On Nov 14, 1:01 am, Chris <chrisbrett...@googlemail.com> wrote: > > > > > Thanks for your reply. > > > From reading around it sounds as though I am probably not meant to > > solve this in the template (though this does seem like the easier > > option). > > > I have figured out that I could solve this through an SQL statement as > > follows: > > > select *, (select Count(*) FROM shop_track_owners where > > track_id=shop_track.id and user_id=<<<insert current user id > > here>>>)"owned" from shop_track; > > > I have run this and it works. There are two problems though: > > > 1: How do I do this through django querysets? I would like to keep the > > database abstracted. > > You can execute arbitrary SQL like this using the extra method on aqueryset. > Something like: > > qs.extra(select={'count':'SELECT count(*) FROM shop_track_owners where > track_id=shop_track.id and user_id=%i' % user.id) > > > > > > > 2: This will probably be rather awkward to do when talking about > > artists or albums... Could I somehow modify the .track_set function of > > the album model to not just return tracks (select * from shop_track) > > but to run my other funky query? > > > Also I have had another thought: I could add an "owned" field to the > > Track model. This could remain null for all tracks in the database > > forever, but could be used in the view when grabbing the tracks to > > pass the template whether or not each track is owned by the current > > user. For example: > > > tracks = Track.objects.all() > > for track in tracks: > > if request.user in track.owners: > > track.owned = True > > > Then render to response. Again, a couple of potential problems: > > > 1: Does altering the track object (track.owned = True) also alter the > > object within tracks? I don't know if it a reference or a copy. If it > > is a copy, is there any way of shoving it back in thequeryset? > > > 2: There is still the problem of what to do when talking about albums. > > Could you do something like: > > > for album in albums: > > for track in album.track_set(): > > if request.user in track.owners: > > track.owned = True > > > Again, would setting track.owned = True affect the track within the > > album's track_set()? I would assume not... I think album.track_set() > > executes a new database query to get the set, right? Is there any way > > around this? > > > One last possibility that I can think of: is there any way of allowing > > the track model to get at the request object? This would allow me to > > write a method in the track model (owned) that checks if the track is > > owned by the user in the request and then returns a bool. > > You can't always assume there is a request object: for instance any > interaction with the system through ./manage.py shell doesn't have a > request object. Also, consider that there may be many request objects > in the system at one time, if many users are using the system > simultaneously. > > This is something that belongs in the view, and probably no lower, as > that is the last place where there is _always_ a request object. > > Having said that, you could do something like this in the model: > > def owned(self, request): > "See if the user of this request owns this object" > return request.user in self.track_owners > > This then means you can call that method from anywhere, and pass in > the current request object. > > > Thanks again. > > > On Nov 12, 8:12 pm, Tomasz Zieliñski > > > <tomasz.zielin...@pyconsultant.eu> wrote: > > > On 12 Lis, 16:12, Chris <chrisbrett...@googlemail.com> wrote: > > > > > Is there a way of getting a model function to access user details so > > > > that I can do a simple "if track.owned" in the template? Is there a > > > > better solution to doing it in the view? Is there something I have not > > > > thought of? What would be the "best practice" solution to this? > > > > Just some quick ideas (after 10h of work, so watch out ;)): > > > > 1. You can write custom tag {%ifowned track request.user%} > > > > 2. You can try something less elegant: > > > > {%for user in track.m2m_users.all%} > > > {%ifequal user request.user%} > > > <do what you want here> > > > {%endifequal%} > > > {%endfor%} > > > > - but it's only good for small apps, as a temp solution. > > > > -- > > > Tomasz Zieliñskihttp://pyconsultant.eu -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=.