There are times when you are not worried about user authentication but still want to have each user sees only his/her stuff. Then you need a way to login a user without password, here is the solution posted on stackoverflow
Normally, when logging a user with password, authenticate() has to be called before login():
What authenticate does is to add an attribute called backend with the value of the authentication backend, take a look at the line of the source code. The solution is to add this attribute yourself:
When a user request a page view from a website (powered by Django), a cookie is returned along with the requested page. Inside this cookie, a key/value pair is presented:
This id is used to uniquely identify who's who by the server. User A's id is different from User B's etc. This id is not only stored in the cookie on the user's computer, it is also stored in the database on the server (assuming you are using the default session engine). By default, after running
./manage.py migrate, a table named django_session is created in the database. It has three columns:
The value stored in the session_key column matches the value stored in the cookie received by the user.
Let's say this user decides to login to the web service. Upon successfully logged into the system, a new sessionid is assigned to him/her and a different session_data is stored in the database:
*I made up this example to use numbers and usernames instead of hash strings. For security reasons, these are all hash strings in reality.
As we can see here, a new session_key has been assigned to this user and we now know that this user is 'John'. Form now on, John's session_key will not change even if he closes the browser and visit this server again. Thus, when John comes back the next day, he does not need to login again.
Django provides a setting to let developers to specify this behaviour, in settings.py, a variable named SESSION_SAVE_EVERY_REQUEST can be set:
If this is set to True, then John is forced to login everytime he visits this website.
Since saving and retrieving session data from the database can be slow, we can store session data in memory by:
The advantage of this approach is that session store/retrival will be faster. But the downside is if the server crashes, all session data is lost.
A mix of cache & database storage is:
According to django's documentation:
every write to the cache will also be written to the database. Session reads only use the database if the data is not already in the cache.
This approach is slower than a pure cache solution but faster than a purse db solution.
Django's offical document did warn to not use local-memory cache as it doesn't retain data long enough to be a good choice.
By default the session data for a logged in user lasts two weeks in Django, users have to log back in after the session expires. This time period can be adjusted by setting the SESSION_COOKIE_AGE variable.
I had to deploy a django project on CentOS 6.5 and here are the steps to set up Python and then Django. The problem with CentOS 6.5 is that it comes with python 2.6.6 and it's package installer yum relies on it.
Although we can install python 2.7.x and soft link 2.7.x as the system default, it will break yum and who knows what else relies on 2.6.6. Thus, I am installing python 2.7.x via pyenv, which is suggested by this blog post.
This solution is cleaner as it does not temper with the OS default python 2.6.6.
- Update all of yum's package
- Install pyenv, which works like rbenv:
Put the following lines into your .bashrc file:
Then, reload bashrc:
This will enable the pyenv command in bash.
- Install these packages before installing python:
- Use this command to list all of the 2.7.x version of python (grep 3.x for python 3):
- Install the python version you prefer:
- Use the newly installed version of python:
You can list all python versions abailable to pyenv by:
- Update pip to its latest version:
Now, we have everything setup and ready to go. The natural thing to do next is to install virtualenv and virtualenvwrapper:
Installing virtualenv and virtualenvwrapper
WARNING: DO NOT install virtualenv and virtualenvwrapper !!!
Let me tell you what happend after I installed both via pip. I put the following lines in .bashrc
Then, I was disconnected from the cloud server with the following warning:
It doesn't matter what I try, I cannot connect to the cloud server anymore because every time I login successfully, I get disconnected from the server with the same error above. I cannot even login using the VNC connection provided by the cloud service provider. The only option I had was to reinstall the image on the cloud server...
I cannot find the cause of this issue on Google, but from the look of it, I messed out the path to bash so everytime I logged in, cannot find bash -> disconnect
Don't worry you can still use virtualenv
If you look under the .pyenv/plugins directory, you can see a directory named pyenv-virtualenv. This is what we can use to create virtual environments.
To create a test environment:
Since we have already set our local version of python to be 2.7.10, this test env inherits from that. But if you did not set the local version, the test env will inherit from the system version of python which may not be what you want. (Note: while running the command above, the 'virtualenv' package is installed to your local version of python)
You can also specify which version of python to use (by putting a version number after 'pyenv virutalenv'):
Once the test environment has been setup, you can verify it by:
You should see something similar to this:
You can switch to the test env by:
To list virtualenvs:
To delete existing virtualenvs:
If you have seen pyenv-virtualenv's github page, you have probably noticed something named pyenv-virtualenvwrapper. Don't install it unless you know what it is. I don't have the time to figure out what it is ATM. But it is definitely NOT the virtualenv + virtualenvwrapper combination you are familiar with. So be cautious!
安装成功后, 编辑你的.bash_profile文件, 将一下两行命令添加在文件的最后:
I had the following code:
When the code above runs, an error is thrown:
There are two solutions to this problem, solution one:
According to Django's document, reverse_lazy should be used instead of reverse when your project's URLConf is not loaded. The documentation specifically points out that reverse_lazy should be used in the following situation:
providing a reversed URL as the url attribute of a generic class-based view. (this is the situation I encountered)
providing a reversed URL to a decorator (such as the login_url argument for the django.contrib.auth.decorators.permission_required() decorator).
providing a reversed URL as a default value for a parameter in a function’s signature.
It is unclear when URLConf is loaded. At least I cannot find the documentation on this topic. So if the above error occurs again, try reverse_lazy
I didn't expect creating a radio input in a form using Bootstrap3's style could have some many pitfalls.
Here is a model I have:
Here is the corresponding ModelForm:
I have a sex field which let users to pick their gender. When running the code above, I get three choices instead of two:
- '--------' # django automatically insert this 'default' option
This is of course not what we want. There should only be two options, 'Male' and 'Female'. So to correct this issue, I had to add TWO extra parameters to the Model:
Note that I added blank=False AND default='M'. If you only include blank=False, you will still see the '--------' option. It is important to have both of them set.
Now, I want to style my forms using Bootstrap3. To do this, I recommend using crispy-forms
Crispy-form creates a Bootstrap3 style input field for every single field defined in the model when this line runs:
The UserProfile model has 13 fields. It is nice that I don't have to specify each one of the 13 fields. But here comes the problem, when the radio input is been rendered. The male and female options are listed vertically. I want them to be listed horizontally. Crispy-form does provide an inline option for rendering radio inputs horizontally. This is nice, but how can I replace the default Layout of the gender field with the suggested inline Layout?
Crispy-forms allows you to access the Layout of each field by using index.
With the tweaks above, now I have a wonderful radio input for gender selection :) So many small things need to be taken care of for something seems so trivial.
When writing a user registration form in Django, you are likely to encounter this error message:
A user with that Username already exists.
This happens when a new user wants to register with a name that is already stored in the database. The message itself is self explainatory but what I need is to display this message in Chinese. According to Django's documentation, I should be able to do this:
But this didn't work. It turns out that Django's CharField only accepts the following error message keys:
Error message keys: required, max_length, min_length
Now when you try to enter a duplicate username, you will see the custom error message being shown instead of the default one :)