Django options for making variables widely available - django

Every time I open a page I want to get the currently active project id. This will be done by chacking the subdomain and verifying the currently logged in user can view it.
Once I reach my view I want to be able to do
tasks = Task.objects.filter(project = current_project)
WHere current_project (or CURRENT_PROJECT or current_project ???) has already been setup.
Can anyone explain the pros/cons of the various approaches I have found in the docs and put me on the right track?
Sessions
Middleware
Threading
builtins
This was how I did it in the end:
Decorator:
def check4project(fn):
current_project = 'fred'
def check(*args, **kw):
kw['project']=current_project
return fn(*args, **kw)
return check
View example
#login_required
#check4project
#tweetpost
def index(request, project=0):
print project

It all depends on what your semantics of "current project" are. Here are some possibilities:
It could be a characteristic of the user: he visits his profile page and sets a current project. This would be stored in the database, and you would access it with the ORM.
It could be a characteristic of the URL, based solely on subdomain. This could be done with middleware, which has access to the request, and could for example, parse the host name and set a custom attribute on the request that you could access in your view functions.
Similar to #2, you could use a view decorator if checking projects is done for some views but not all. This is similar to Django's decorators for checking authorization.
It could be a characteristic of the user's visit to the site: he visits a page of projects, chooses one to work on, and it's sticky until he chooses another project. This would be best stored in the session, which is specifically for this sort of transient storage.
From your description, it sounsd like #2 or #3 is the best for you, depending on how your views divide up between caring about subprojects and not.

You could make a context_processor and then get your value from the request object.

Have you considered a custom template tag?

Related

How can I change the view site link in Django admin, depending on which app is used?

I am making a project where each client have their own app. This is because they have similar pages but not exactly the same so I think it's a good approach(I may be wrong) to just copy one app for each new client. I have not tried it yet, I am still planning for it. I see one problem with the view site link in the admin. I will let the clients use the admin. How can I set the view site link to the main page for the client? One way to solve it would be to leave it as is and have a function checking their user name and redirecting to the right app. But is there any other way to solve this problem?
I don't think it will be a good idea to have applications generated for users as that's too much once you reached a specific amount of users.
they have similar pages but not exactly the same
Then what you should do is to, after getting the user in your view, pass in a different context to your template. Something like:
def my_view(request):
# First assign different context to different users
context = {'data': 'whatever each user gets', 'other': 'put in more than 1 data',}
return render(request, 'myapp/index.html', context)
I will let the clients use the admin
That's not a good idea as the clients MUST be a superuser to view the admin site. Otherwise, you need to change the permissions of a superuser, make a separate superuser if you are the maintainer of the site, and all sorts of trouble. Just take some time and make your own templates.

django extending an app to allow non authenticated votes

I have been testing a few django voting apps and found qhonuskan-votes. I have managed to install it and is works great. However, I also want it allow voting rights to non authenticated users which I am not able to do. Need help with this please.
Here is the link for its models.py, views.py and compact.py files of this app.
models
views
compact
You could write a custom view which would look like def vote(request, model, object_id, value) from the external app, but without this piece of code in it:
if not request.user.is_authenticated():
return HttpResponse(status=401)
Also make sure, that you map your custom view to the correct url instead of including app's urls:
url(r'^vote/$', view='custom_vote', name='qhonuskan_vote'))
This is not the best solution, because you are simply rewriting the code from the external app and I can't think of any proper way to override the default view in a way that would suit your needs. A better solution would be to use a different app, which allows votes by unauthenticated users (if a few lines of additional code are not a problem you can use this).

How to moderate django_openid_auth

I am implementing openid feature using django_openid_auth library which is quite amazing..
However I am looking for very specific moderation settings.
Although openid is made available for everyone..I am looking to implement the below rules
OpenId should provide email address.. Not all guys do provide
The email address should be one of the access granted list present in my db
I started to think quite possible ways like creating custom middleware, custom login_required decorator etc.. But I am unable to think a possible way of fitting them exactly in the bill.
Can anyone add suggestions would be appreciated
aquiring email address is simple enough - you just need to ask openid server for it. django-openid-auth provides settings for it:
OPENID_SREG_EXTRA_FIELDS = ['email']
In my project i also needed to do extra stuff after authentication. I solved it with signal:
def register_login_signal():
from django.contrib.auth.signals import user_logged_in
from django.contrib.auth.models import User
user_logged_in.connect(your_function_name_here, sender = User)
def your_function_name_here(sender, **kwargs):
request = kwargs.get('request')
logout(request) if request.user.email not in your_list_of_authenticated_emails else pass
and dont forget to put register_login_signal() to some place where it gets used like projects init.py file
Edit:
1st comment/question.
The extra fields part is not stated in documentation. Also, if you scan through the github package then you notice nothing like it, i'm sure. I am using older version of https://pypi.python.org/pypi/django-openid-auth/0.5. Download it, unpack and open views.py in django-openid-auth folder. Search for OPENID_SREG_EXTRA_FIELDS and you'll see it. Works like a charm if you define it in settings.py.
2nd question
Async? Nope, not really. Async would be something that gets run outside of current function stack - if you can describe it like that. This is nothing like that. Imagine it like that - in the end of login function there is check, that if there are some functions hooked on the end of login function. And they get run instantly. Its as much async as django middleware is. So not at all.
But is it right place to do it? I imagine that you have your site set up that you check if user has logged with #login_required decorator - or something like that.
So lets see how things will get executed:
1) Your openid server sends you all the information you requested with last request
2) Your django-openid-auth login_complete view takes over and authenticates user using it's backend
3) in the end of that process the signal for which you listen to is triggered, user's email is checked against your list and if the check fails, then he is instantly logged out.
4) Since the view is done, it automatically redirects you to either the url whcih was specified in original view with "next" parameter or to LOGIN_REDIRECT_URL specified in your settings
5) Before that view all the middleware and decorators get used. And if you have used something like #login_required decorator (which is smart thing to do for each login protected page), then it instantly redirects user to login page. If you bothered to add some kind of message to request in signal, then the message is displayed (given that your login/logout page supports that)
And to say something in the end - there is no stronger method than logging out.
/edit

how to check if a user has logged in from outside the US using Django middleware

I am pretty new to Django and wanted to know how I could check if a user logging to a django powered website is from outside the US?
How would I write a class in Middleware to check the same? I want to hide particular sections of the website from users logging out of the US.
I know I am not providing any details and the question might seem vague... but I needed a general idea to get started. I have not started working on the website yet.
I went through the Django Middleware documentation but still did not understand how to do so.
Does the user authentication https://docs.djangoproject.com/en/1.4/topics/auth/#limiting-access-to-logged-in-users provide any such functionality?
You could use the GeoIP module included with django.
A simple middleware could look something like this:
class GeoLocationMiddleware:
def process_request(self, request):
if 'geoip_check' not in request.session:
g = GeoIP()
country = g.country(request.META.get('REMOTE_ADDR'))
do_something(country) #Do something with country result.
request.session['geoip_check'] = True #Could store country result
return None
You'll notice I add a flag to the session. Checking the GeoIP on every request is unnecessary and bad for performance, so we only check it once per session.
Hope this is what you were looking for.
Edit:
If you only want to do this for logged in users, throw this in there:
if request.user.is_authenticated():
at the beginning.

Project platform suggestion for web application with proper User Auth and integration support

So, I have an idea to build a web app. I am new to this business but am a programmer. I liked Python and thought let me start with Django. I ran into a problem with the built-in Django User Auth system as pointed by this question of mine on SO.
In short, I am using Django's built-in User auth and thought that it will easily fill my user field (the foreignkey) in my model but it does not. I have Googled and asked questions but only got a very convoluted answer or that I have to use the Admin section if I want anything like that.
My simple need is that whenever user saves anything in their profile, the user field should get populated so that I can reference it. To me, it sounds like the most basic need for any web app.
Am I wrong. I need advice. If Django is not good for this then I am ready to learn any other good framework or platform if need be.
In short, I am using Django's built-in
User auth and thought that it will
easily fill my user field (the
foreignkey) in my model but it does
not.
This won't just magically happen. You will have make it happen. Models are separated from the request so this would happen in your view, or a model method (perhaps save) that is passed the active user.
MVC / MTV design separates the database from the view / control logic. I don't see what framework has to do with this: unless you write the functionality yourself, the database doesn't know what to do with some User table and the currently logged in user (also separated from the data). Building in this functionality would inconvenience a lot of people as well...
In general, the python/django philosophy is: Explicit is better than implicit.
Now the solutions:
If you wanted this behavior in the view, for any form, you could potentially write:
instance = MyForm.save(commit=False) # commit=False prevents DB save.
instance.user = request.user
instance.save()
You could overwrite the save method on the model that accepts an optional user argument as well.
def save(self, *args, **kwargs):
user = kwargs.pop(user, None)
self.user = user
super(MyModel, self).save(*args, **kwargs)
mymodel = MyModel()
mymodel.save(user=request.user)