Basic django app - app design issue - django

To learn Django, I was making a very basic app which does the following:
Takes a user's login (checks id password in a database).
If user exists and password is right, give user option to either insert,delete or update.
If insert, user can insert an entry into a common table.
Similarly for delete or update.
I was cruising through this but I just got stuck.
My Login page is /index/.
Option for insert/delete/update is at /application/.
Now next, page is displayed according to insert/delete/update at /application/action/
Now the problem is that after completing one insertion, I want to return to /application to carry on my next operation.
But if I do that, I get this error
"Key 'userid' not found in <QueryDict: {}>"
So the view for /application/ is expecting the userid and password in request.POST.
How do I get around this without using external user login modules. I just want a very basic login system just to learn.

Django comes with user authentication built in. I don't think it is external as it is included in django.contrib.
If you use the built in user authentiaction and User model, you will not have to pass the userid to each view. Django will automatically retrieve the logged in user from the session and make it available as a property of the request object.
So using built in user and authentiaction, after logging in a user, you can access that user at
request.user

Related

Sign up for membership in Django City, create admin authentication process

Currently, it is set to return to the first screen of the program when membership registration is completed in Django. However, since anyone can sign up and view information within the program, I want to make it possible to access the program's first page only after the administrator approves it when someone completes membership registration. As a result of Googling, only email verification was found, so I had to ask a question. There seems to be no admin authentication process provided by Django. Are there any similar examples or methods?
I want to make it possible to access the program's first page only after the administrator approves it when someone completes membership registration.
At first you can set the step for every registration level.
and to approve the user to authenticate the page, you can create and check status user profile.
Another way is using a django permission for an authenticated page.
you can do this, if the user completed a couple of registration and a step number, for example is 7, you can give needed permission to the user.

Guest Checkout in django

I am currently developing guest checkout in django as I don't want to use django-oscar which gives guest checkout functionality. I searched and got to the conclusion that it can be done through session and got to know that when user logs in the system at that time row will be created in django_session table. So I will have to create manual entry in django_session for my guest checkout. Can anyone please throw some light on how and which will be the best way to do it?
The easiest way it would be to set request.session['user'] to some default value (e.g. guest) by default (you can do
try:
request.session['user']
except KeyError:
request.session['user'] = 'guest'
at the start of every view function (pr functions that can be accessible directly by typing some URL. That's what I've always done and it makes miracles ;). What it actually does is checks whether a user is logged in (request.session has the key user) or not (request.session does not have the key user). When user logs in, set request.session['user'] to his username.
You don't want to touch the django_session table yourself.
Instead, please read
a tutorial about the session framework, or
the more in-depth documentation
The gist of it is that you can store things in the session dict using
request.session['foo'] = True
and they will be transparently persisted using a cookie. You can retrieve them similarly.

How to check session for all views in Django?

I set the session["UserID"] for user login status in view login page after pass the verify of username and password.
Then I need to check if the user is logged in within every other views, such as home page, shopping bag page and so on.
My question is, can I check it just for one time and where should I write it? Are there some methods triggered before the views called?
My question is, can I check it just for one time and where should I write it?
You do check it one time, providing you are using django's built in authentication method then the whole handling of users is done for you, you don't need session user id's since django handles the user through requests with its auth middleware.
Once logged in there will be a user as part of the request object which will either be a AnonymousUser if not logged in, or an instance of your user class if you are logged in.
Are there some methods triggered before the views called?
Yes, middlewares, which you could write your own custom middleware but I don't really think you need it.
I check the login status within the MASTER PAGE in ASP.NET and it can control all the other page which import it.
I haven't really used asp.net but again, you don't need to do this, django handles its users for you (providing your using built in auth tools).
See Limiting access to logged-in users and the functions and properties available on the user class

Passing parameter to load data from DB after login with Django Auth App

I am new user of Django.
I want to use the built in Django Auth app for secure login. However, once a user logs in, based upon the username, I want to load it's data on the first page (lets call it welcome or home page). If I write my own login, I get stuck with URLs. All my pages become http://127.0.0.0.1:8000/login/..... I don't know where this /login/ comes from (it's written in settings file but who calls it I don't know) so after losing hope, I went for Auth login again.
I am sure there is a nice and easy way to retrieve the username but where should I write this code? in the login view of Auth app? would then that code will become part of my application?
Information about the user that's currently logged in is stored in the request.user object (request being the first parameter of every view function). request.user is an instance of the User class from django.contrib.auth. So, you can pass the user object to your templates and make all the information about the logged in user avalable that way (user.username, user.email, etc).

In Django, what is the right place to plug in changes to the user instance during the login process?

Background
I have a custom authentication back end for our django applications that refers to an LDAP server.
As soon as I authenticate someone, I have a wealth of information that our network infrastructure guys put in the LDAP server about the user - their last names (which can change, for instance, if they marry), their e-mails (which can also change), plus other company specific information that would be useful to transfer to the Django auth_user table or profile table for local reference. (*)
To take advantage of this data, as of now, in our custom authenticate method I'm looking up (if it is an existing user logging in) or creating a new (if a new user that never logged in to our Django apps) user, making any changes to it and saving it.
This smells bad to me. Authentication should be about saying yay or nay in granting access, not about collecting information about the user to store. I believe that should happen elsewhere!
But I don't know where that elsewhere is...
My current implementation also causes a problem on the very first login of a user to one of our Django apps, because:
New user to our apps logs in - request.user now has a user with no user.id
My custom authenticate method saves the user information. Now the user exists in the DB
django.contrib.auth.login() kicks in and retrieves the request.user (which still has no user.id and no idea that authenticate saved the user) and tries to save an update to last logged in date.
Save fails because there is already a row in the database for that username (unique constraint violation)
Yes, this only happens the very first time a user logs in; the next time around it will be an update, request.user will have a user.id and everything is fine.
Edit: I'm investigating the striked-out area above. The login code clearly only uses the request.user if the user is None (which, coming out of the validation of the AuthenticationForm it shouldn't be. I probably am doing something wrong in my code...
But it still smells bad to have the authentication doing more than just, you know, authenticating...
Question
What is the right place to plug in changes to the user instance during the login process?
Ideally I would be able to, in my custom authenticate method, state that after login the information collected from a LDAP server should be written to the user instance and potentially the user profile instance.
(*) I do this local caching of the ldap information because I don't want to depend on it being up and running to let users log in to my systems; if ldap is down, the last username and password in auth_user are accepted.
I've done similar things by writing my own authentication backend and putting it in the authenticate() method. The code is public and up here. I also included a pluggable system of "mappers" to do most of the work that isn't just authenticating the user (eg, getting fullname from ldap, automatically creating groups based on "affiliations" that our auth service gives us, and mapping certain users and affiliations into staff/superuser roles automatically).
Basically, the authenticate method looks like:
def authenticate(self, ticket=None):
if ticket is None:
return None
# "wind" is our local auth service
(response,username,groups) = validate_wind_ticket(ticket)
if response is True:
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
user = User(username=username, password='wind user')
user.set_unusable_password()
# give plugins a chance to pull up more info on the user
for handler in self.get_profile_handlers():
handler.process(user)
user.save()
# give plugins a chance to map affiliations to groups
for handler in self.get_mappers():
handler.map(user,groups)
return user
else:
# i don't know how to actually get this error message
# to bubble back up to the user. must dig into
# django auth deeper.
pass
return None
So I pretty much agree with you that authentication should be just a yes/no affair and other stuff should happen elsewhere, but I think with the way Django sets things up, the path of least resistance is to put it in with authentication. I do recommend making your own authentication code delegate that stuff to plugins though since that's within your control.
I'm only fetching the LDAP data on their very first login though (when the auth_user row gets added). Anytime they login after that, it just uses what it already has locally. That means that if their LDAP info changes, it won't automatically propagate down to my apps. That's a tradeoff I'm willing to make for simplicity.
I'm not sure why you're running into problems with the first login though; I'm taking a very similar approach and haven't run into that. Maybe because the login process on my apps always involves redirecting them to another page immediately after authentication, so the dummy request.user never gets touched?
This will be a two part answer to my own question.
What is the right place to plug in changes to the user instance during the login process?
Judging from the Django code, my current implementation, and thraxil's answer above, I can only assume that it is expected and OK to modify the user instance in a custom authenticate() method.
It smells wrong to me, as I said in my question, but the django code clearly assumes that it is possible that a user instance will be modified and I can find no other hooks to apply changes to the user model AFTER authentication, elsewhere.
So, if you need an example, look at thraxil's code - in the selected answer to my question.
Why my implementation is working differently from thraxil's and generating a unique constraint violation?
This one was rather nasty to figure out.
There is absolutely nothing wrong with Django. Well, if it already supported multiple databases (it is coming, I know!!!) I probably wouldn't have the problem.
I have multiple databases, and different applications connect to one or more different ones. I'm using SQL Server 2005 (with django_pyodbc). I wanted to share the auth_user table between all my applications.
With that in mind, what I did was create the auth models in one of the databases, and then create SQL Server synonyms for the tables in the other databases.
It works just fine: allowing me to, when using database B, select/insert/update/delete from B.dbo.auth_user as if it were a real table; although what is really happening is that I'm operating on A.dbo.auth_user.
But it does break down in one case: to find the generated identity, django_pyodbc does a:
SELECT CAST(IDENT_CURRENT(%s) as bigint) % [table_name]
and that doesn't appear to work against synonyms. It always returns nulls. So when in my authenticate() method I did user.save(), the saving part worked fine, but the retrieval of the identity column didn't - it would keep the user instance with a id of None, which would indicate to the django code that it should be inserted, not updated.
The workaround: I had two choices:
a) Use views instead of synonyms (this is what I did)
b) Reload the user right after a user.save() using User.objects.get(username=username)
Hope that might help someone else.