Electronics & Programming

develissimo

Open Source electronics development and programming

  • You are not logged in.
  • Root
  • » Django
  • » Question on passing user to model objects [RSS Feed]

#1 Dec. 13, 2010 10:22:39

S.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

Question on passing user to model objects


Hi guys,
I have a (probably easy) question.

I need to pass the logged in user to my objects.

I have the objects company and offer.

I tried the following on the project's index / start view:

c = Company.objects.all()
cmp.login=request.user
for j in cmp.offer_set.all():
j.company.login=request.user
return render_to_response('show/startseite.html', {'company':
c},context_instance=RequestContext(request))

This works fine for the company objects. However, it does *not* for
the offer objects.

For whatever reason, even though it should be available, the offer's
user attribute is 0 (it's initial value).

The template is like this (shortened to cover only import points):

{% if company.editable %}(... user has edit rights - this works){%endif
%}

{% if company.offer_set.all %}
{% for item in company.offer_set.all %}
{% if journey.editable %} *** does not work ***

Strange enough, when I display the vars:
C: {{company.editable}} / OC: {{offer.company.editable}} / O:
{{offer.editable}}

I get
C: true / OC: false / O: false


So for whatever reason company does not seem to be the same as
offer.company, although it is in the same loop.



How could I solve this problem? Is there a suggested way to pass the
logged in user to all objects?



Kind Regards and thanks
Stephan

--
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 athttp://groups.google.com/group/django-users?hl=en.

Offline

#2 Dec. 13, 2010 10:39:00

Daniel R.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

Question on passing user to model objects


On Monday, December 13, 2010 10:22:32 AM UTC, Scoox wrote:Hi guys,
I have a (probably easy) question.

I need to pass the logged in user to my objects.

I have the objects company and offer.

I tried the following on the project's index / start view:

c = Company.objects.all()
cmp.login=request.user
for j in cmp.offer_set.all():
j.company.login=request.user
return render_to_response('show/startseite.html', {'company':
c},context_instance=RequestContext(request))

This works fine for the company objects. However, it does *not* for
the offer objects.

For whatever reason, even though it should be available, the offer's
user attribute is 0 (it's initial value).

The template is like this (shortened to cover only import points):

{% if company.editable %}(... user has edit rights - this works){%endif
%}

{% if company.offer_set.all %}
{% for item in company.offer_set.all %}
{% if journey.editable %} *** does not work ***

Strange enough, when I display the vars:
C: {{company.editable}} / OC: {{offer.company.editable}} / O:
{{offer.editable}}

I get
C: true / OC: false / O: false


So for whatever reason company does not seem to be the same as
offer.company, although it is in the same loop.



How could I solve this problem? Is there a suggested way to pass the
logged in user to all objects?



Kind Regards and thanks
Stephan



It's a bit hard to see what's going on, as you haven't provided your
model definitions and your code seems to be incomplete (what is cmp?)


But the issue is likely to be that each call to foo_set.all() creates a
brand new queryset fetched straight from the database. So doing
something on the result of calling .all() in the view is irrelevant
when you call .all again in the template.

The best way to do this is probably to keep the queryset in a variable
and send it explicitly to the template, then iterate through that:


offers = cmp.offer_set.all()
for j in offers:
.... whatever ...
return render_to_response('show/startseite.html',
{'company': c, 'offers': offers},
context_instance=RequestContext(request))



and in the template:
{% for item in offers %}



--
DR.

--
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 athttp://groups.google.com/group/django-users?hl=en.

Offline

#3 Dec. 13, 2010 11:20:28

S.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

Question on passing user to model objects


Hi Daniel,
thanks for your answer. Sorry, cmp should be c. I tried to only give
the import parts to make it more readable, but I made a mistake there.
The model code is pretty standard, except for one function:

isEditable=0
login=0
def editable(self):
if self.login==0: return False
else:
if self.isEditable!=0: return self.isEditable
if self==self.login.get_profile():
self.isEditable=True
for o in self.offer_set.all(): o.editable=True
return True
else:
self.isEditable=False
return False

(I added the isEditable attribute to cache if the object is editable,
since I wasn't sure if get_profile() is lazy loaded or sends a request
to the db with each iteration)

>> But the issue is likely to be that each call to foo_set.all() creates a
>> brand new queryset fetched straight from the database. So doing
>> something on the result of calling .all() in the view is irrelevant
>> when you call .all again in the template.

That's probably right. But from what I understood, all() is a lazy
loader, so when Django loaded the objects once out of the db, it
should not do that again when the same object is called in a template.
Or did I understand that wrong?

>> The best way to do this is probably to keep the queryset in a variable
>> and send it explicitly to the template, then iterate through that
Yes that sounds possible. Just wondering if there is a cleaner way to
do it - the ideal way would of course every object having access to
the user in some way, but that seems impossible.



Kind Regards
Stephan

--
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 athttp://groups.google.com/group/django-users?hl=en.

Offline

#4 Dec. 13, 2010 13:40:01

bruno d.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

Question on passing user to model objects


On 13 déc, 12:20, Scoox <stephan.f.mul...@gmail.com> wrote:
> Hi Daniel,
> thanks for your answer. Sorry, cmp should be c. I tried to only give
> the import parts to make it more readable, but I made a mistake there.
> The model code is pretty standard, except for one function:
>
>     isEditable=0
>     login=0

Assuming these two previous lines are at the top-level of you class
statement, both attributes will be class-attributes (that is "shared
by all instances"). I don't think this is what you want.

>     def editable(self):
>         if self.login==0: return False
>         else:
>             if self.isEditable!=0: return self.isEditable
>             if self==self.login.get_profile():

Are you sure you want to compare the current whatever instance with a
profile ???

>                 self.isEditable=True
>                 for o in self.offer_set.all(): o.editable=True

Such a side-effect is really really bad practice (and, in this case,
mostly useless).

>                 return True
>             else:
>                 self.isEditable=False
>                 return False


Code depending on the request.user should either takes an user as
param or live elsewhere.

> (I added the isEditable attribute to cache if the object is editable,
> since I wasn't sure if get_profile() is lazy loaded or sends a request
> to the db with each iteration)

When you aren't sure, check, don't wildguess.

> That's probably right. But from what I understood, all() is a lazy
> loader, so when Django loaded the objects once out of the db, it
> should not do that again when the same object is called in a template.
> Or did I understand that wrong?

You did. What "lazy" means here is that no request is issued until you
start to iterate over the queryset or subscript it.

> Yes that sounds possible. Just wondering if there is a cleaner way to
> do it - the ideal way would of course every object having access to
> the user in some way, but that seems impossible.

Indeed. How would your code work in another environnment (command line
tool for example) else ?

wrt/ "a cleaner way to do it", your business rules are not clear
enough to come with a sensible answer.

--
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 athttp://groups.google.com/group/django-users?hl=en.

Offline

#5 Dec. 13, 2010 15:19:16

Daniel R.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

Question on passing user to model objects


On Monday, December 13, 2010 11:20:21 AM UTC, Scoox wrote:Hi Daniel,
thanks for your answer. Sorry, cmp should be c. I tried to only give
the import parts to make it more readable, but I made a mistake there.
The model code is pretty standard, except for one function:

isEditable=0
login=0
def editable(self):
if self.login==0: return False
else:
if self.isEditable!=0: return self.isEditable
if self==self.login.get_profile():
self.isEditable=True
for o in self.offer_set.all(): o.editable=True
return True
else:
self.isEditable=False
return False

(I added the isEditable attribute to cache if the object is editable,
since I wasn't sure if get_profile() is lazy loaded or sends a request
to the db with each iteration)

>> But the issue is likely to be that each call to foo_set.all()
creates a
>> brand new queryset fetched straight from the database. So doing
>> something on the result of calling .all() in the view is irrelevant
>> when you call .all again in the template.

That's probably right. But from what I understood, all() is a lazy
loader, so when Django loaded the objects once out of the db, it
should not do that again when the same object is called in a template.
Or did I understand that wrong?



That's not quite right. Calling .all() on a queryset is indeed lazy,
which means that it doesn't call the database until it's evaluated or
iterated. Subsequent iterations *on the same queryset object* do not
hit the database again.


However, calling foo.bar_set multiple times does *not* get the same
queryset each time. So, each one is a separate query, and changing
attributes on the instances returned by one iteration does not have any
effect on those returned by a second. I discuss this a little in a blog
entry here:http://blog.roseman.org.uk/2010/01/11/django-patterns-part-2-efficient-reverse-lookups/>> The best way to do this is probably to keep the queryset in a
variable
>> and send it explicitly to the template, then iterate through that
Yes that sounds possible. Just wondering if there is a cleaner way to
do it - the ideal way would of course every object having access to
the user in some way, but that seems impossible.



Does this necessarily need to be a model method? Why not a custom
template tag or filter, that you can pass the request.user object to?
--
DR.

--
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 athttp://groups.google.com/group/django-users?hl=en.

Offline

#6 Dec. 13, 2010 16:00:09

S.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

Question on passing user to model objects


> >     isEditable=0
> >     login=0
>
> Assuming these two previous lines are at the top-level of you class
> statement, both attributes will be class-attributes (that is "shared
> by all instances"). I don't think this is what you want.
Yes but that's what I intended. They should (and do) not all have the
same value, but every instance of the object should have access to the
user. Ideally I would have a static user class holding the current
user (or global variable), but unfortunately I could not get that to
work.

> >     def editable(self):
> >         if self.login==0: return False
> >         else:
> >             if self.isEditable!=0: return self.isEditable
> >             if self==self.login.get_profile():
>
> Are you sure you want to compare the current whatever instance with a
> profile ???

Nope, absolutly not :-). That should mean self.user instead of self.
In the company self is right since it extends the user, but here I
changed it.


> >                 self.isEditable=True
> >                 for o in self.offer_set.all(): o.editable=True
>
> Such a side-effect is really really bad practice (and, in this case,
> mostly useless).
I agree it's kind of bad.


> >                 return True
> >             else:
> >                 self.isEditable=False
> >                 return False
>
> Code depending on the request.user should either takes an user as
> param or live elsewhere.

I will put it somewhere else. I guess you mean because the code is re-
used twice.


> > (I added the isEditable attribute to cache if the object is editable,
> > since I wasn't sure if get_profile() is lazy loaded or sends a request
> > to the db with each iteration)
>
> When you aren't sure, check, don't wildguess.

Will do as soon as I am a little more used to Django.

> > Yes that sounds possible. Just wondering if there is a cleaner way to
> > do it - the ideal way would of course every object having access to
> > the user in some way, but that seems impossible.
>
> Indeed. How would your code work in another environnment (command line
> tool for example) else ?

There it worked fine (the original version, as you stated this one had
a bug). So it really must be the a different queryset.

> wrt/ "a cleaner way to do it", your business rules are not clear
> enough to come with a sensible answer.

What I am trying to archive is rather simple - I just did not figure
out a simple and clean way to do it:

I have the company and offer objects. Each offer belongs to a company
which belongs to a user. Whatever user is logged in should see an
"edit" link on the live site, whenever his own company or offers come
up. Anoynmous users should not see any edit links.

--
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 athttp://groups.google.com/group/django-users?hl=en.

Offline

#7 Dec. 13, 2010 17:20:27

S.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

Question on passing user to model objects


Hi Daniel,

> However, calling foo.bar_set multiple times does *not* get the same
> queryset each time.
Okay, that was new to me :-)... Do you know what the reason for that
is?


> I discuss this a little in a blog
> entry
> here:http://blog.roseman.org.uk/2010/01/11/django-patterns-part-2-efficien...
Thanks! I thank that is exactly what I want to achieve. I changed
_related_items to related_items (else Django would give me an error).

The data should now be correct.

I have a little problem passing the dict to the template though. When
I did so, the template would have the keys - not the actual values.

I also added:
obj_arr=
for key, obj in obj_dict.items():
obj_arr.append(obj)

It's not very beautiful, but keeps the designer from using {% for
key,value in dictionary.items %}{{ value }}{% endfor %}


> Does this necessarily need to be a model method? Why not a custom
> template tag or filter, that you can pass the request.user object to?
Then the filter would have to be inserted everywhere where any of the
object's attributes should be shown (the edit button is shown for each
visible attribute).




Thanks a lot!
Stephan

--
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 athttp://groups.google.com/group/django-users?hl=en.

Offline

  • Root
  • » Django
  • » Question on passing user to model objects [RSS Feed]

Board footer

Moderator control

Enjoy the 24th of October
PoweredBy

The Forums are managed by develissimo stuff members, if you find any issues or misplaced content please help us to fix it. Thank you! Tell us via Contact Options
Leave a Message
Welcome to Develissimo Live Support