I am trying to use django-password-reset (https://pypi.python.org/pypi/django-password-reset/0.2) to allow users recovering their passwords.
django-password-reset provides a form where the user can enter their username or email address, and tries to find one of those in the database.
In my project, the user has no username field - only the email field.
Thus, I need to make it search users by the 'email' field only, and not by the 'username' field, which does not exist in my system.
The projects documentation says there are attributes to change this behavior:
http://django-password-reset.readthedocs.org/en/latest/views.html.
However, I simply cannot find out how to set these attributes.
Can someone help?
Just override Recover view like so:
class MyRecover(Recover):
search_fields = ['email']
myrecover = MyRecover.as_view()
because there are two recover urls, you need to pass the one with signature first and then the overridden one and then the included one, seems not very DRY, but it's the only way to make the urls be dispatched correctly:
url(r'^recover/(?P<signature>.+)/$', 'password_reset_recover.views.recover_done',
name='password_reset_sent'),
# next we override our url, assuming your app name is called 'core'
url(r'^recover/$', 'core.views.myrecover', name='password_reset_recover'),
url(r'^/', include('password_reset.urls')),
The documentation for django-password-reset says that it uses django.contrib.auth.models.User (the django built in User model) to search for username or email. So here a username would exist.
If you want to change the functionality of the django-password-reset you can go into the forms.py file and change the form's search_fields variable (and other logic) so that it only searches by email.
Here is the hyperlink to the forms.py:
https://github.com/brutasse/django-password-reset/blob/master/password_reset/forms.py
I'd start with changing the PasswordRecoveryForm
Related
Please note--this is an updated version of my original question on this subject, but deserves to be asked again with the change in how Django deals with users and authentication.
I'm working on a website with two very different kinds of users--let's call them Customers and Store Owners. Both register on the site, but have very different functionality. Customers simply have a single profile and can shop among the stores that they like. Store Owners have a single account but can have access to multiple stores, and each store can have multiple Store Owners.
The exact details of the models don't matter, but the two types of users would require very different fields. The models ideally would look something like this:
Customer
email (username)
password
name
address
time_zone
preferred_shipping
favorite_stores (many-to-many field)
...
Store Owner
email (username)
password
name
balance
stores_owned (many-to-many field on Stores)
stores_managed (many-to-many field on Stores)
...
Originally, when Django had poor custom user support, I had a UserProfile class with some additional fields with a OneToOne on User, and then additional Customer and StoreOwner classes that were OneToOne on UserProfile. This didn't work very well.
Given the changes in Django 1.5/1.6, I'm trying to come up with the best way to structure this. Right now, I have the following:
class CustomerUser(AbstractBaseUser):
...
class StoreOwnerUser(AbstractBaseUser):
...
But because there would be two types of user, I can't set AUTH_USER_MODEL to only one of them.
What is the best way to structure this so that I can have two different types of users with different fields, without causing me any problems in user authentication, user creation, or the admin?
Also, how will I be able to tell from login alone whether this user is a CustomerUser or a StoreOwnerUser?
It seems like there are some common features and uncommon features to your user types. If there are common features in your user types that Django's default User model doesn't support out of the box, you should subclass it directly.
Adding in extra, uncommon features to your user types are best done not by subclassing but by using a profile. My rationale for this is because your authentication for these user types doesn't fundamentally change, but details about the user does depending on the type of user it is. To accomodate this, you create a separate model with these details and reference your User class as a OneToOne/ForeignKey relationship (depending on your design).
You can make modifications to your user creation process to identify what kind of user type it should be, and set its associated OneToOneField/ForeignKey (depending on your design) to the appropriate customer type model.
By doing it this way, you should only have one AUTH_USER_MODEL, and you should be able to handle details for your different customer types.
What is the best way to structure this so that I can have two
different types of users with different fields, without causing me any
problems in user authentication, user creation, or the admin?
You actually only have one type of user. Just that some users have specific properties set and others do not. Consider how django has "users" and "admins". They are the instances of the same model, but with different properties and permissions.
You should approach it similarly. Have one user model for your entire application. You can set properties/methods in your custom user class to identify what flags this user has set (which would determine the "type" of user there is).
Also, how will I be able to tell from login alone whether this user is
a CustomerUser or a StoreOwnerUser?
You can use the user_passes_test decorator, which takes an argument that is a function name and will only process the view if the function returns a truth value.
Create a BaseUser which extends Django's Abstract base User
Create two Sub Classes Named CustomerUser and StoreOwnerUser which extends BaseUser
from django.db import models
from django.contrib.auth.models import AbstractUser
class BaseUser(AbstractUser):
# all the common fields go here, for example:
email = models.EmailField(max_length=10,unique=True)
name = models.CharField(max_length=120)
class StoreOwnerUser(BaseUser):
# All Store Owner specific attribute goes here
balance = models.some_balance_field()
stores_owned = models.some_stores_owned_field()
class Meta:
verbose_name = 'Store Owner'
class CustomerUser(BaseUser):
# All Customer specific attribute goes here
customer_id = models.CharField(max_length=30, unique=True)
address = models.some_address
time_zone = models.something...
...
class Meta:
verbose_name = 'Customer'
hello i'm new in python and django
I need a view that get current user profile I know I shoud use get_profile from User but I don't know how to use it . i read the django document and It didn't help me.
this is what I found from doc:
from django.contrib.auth.models import User
profile=request.user.get_profile()
Django's documentation says it all, specifically the part Storing additional information about users. First you need to define a model somewhere in your models.py with fields for the additional information of the user:
models.py
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
accepted_eula = models.BooleanField()
favorite_animal = models.CharField(max_length=20, default="Dragons.")
Then, you need to indicate that this model (UserProfile) is the user profile by setting AUTH_PROFILE_MODULE inside your settings.py:
settings.py
...
AUTH_PROFILE_MODULE = 'accounts.UserProfile'
...
You need to replace accounts with the name of your app. Finally, you want to create a profile every time a User instance is created by registering a post_save handler, this way every time you create a user Django will create his profile too:
models.py
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
accepted_eula = models.BooleanField()
favorite_animal = models.CharField(max_length=20, default="Dragons.")
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
Accessing the Profile
To access the current user's profile in your view, just use the User instance provided by the request, and call get_profile on it:
def your_view(request):
profile = request.user.get_profile()
...
# Your code
Basically django User models will provide access only for the fields ( firstname,lastname,email,password,is_staff,is_active,last_login).
However if we want to add any extra fields to this model, say we need to add a new column named dateofbirth for every user, then we need to add a column named DOB into User model. But this is not possible as we aren't able to edit django User models.
To achieve this either
1.We can have a separate new table with email id & DOB column, such that a column in User model is mapped with a column in the new table. But this will create a new db instance for every db request. Say if u want to find the DOB of a customer,
First we need to fetch the value of mapped id of a customer from the
User table.
WIth the above value, get DOB from the new table.
In the second method,
Instead of using django User model, use your own customize model with all the fields needed. However if any updation related to security or some enhancement made to django User model we can't use it directly. We need to do more code changes at our end( wherever we use our customize models.) This will be a bit pain for a developer to identify the code & make changes.
To overcome the above issues, django introduce django profile which is very simple and more flexible. The advantages are
Updation/enhancement to the User model can be applied without modifying the code much
No need of creating new db instance to fetch the extra values.
Since the field has onetoone mapping deletion of data from one table will delete others also.
More secure, since we use django models ( no sql injection)
How to Use this:
In settings.py create a variable AUTH_PROFILE_MODULE = "appname.profiletable"
In models.py, create a new table with the fields needed and make sure that the id in User model is onetoone mapped with new table.
create a signal which inserts a row into the new table whenever a new entry is added into User model.
The value in the new table can be accessed using User object itself.
Say, we created a new table extrauser which has DOB, emailid. To find the DOB of a customer, use
a=User.objects.get(email='x#x.xom')
a.get_profile().DOB will give the dateofbirth value from extrauser table.
Hope the above details make you clear in understanding django profile. Incase of any help further, let me know. I have used django profile in my project.
Old question but I thought anyone seeing it today may benefit from this:
Django 1.5 adds the ability to - easily - extend the User model. This may be preferable as you now only got one object to deal with rather than two! Seems the more modern way.
https://hurricanelabs.com/blog/django-user-models/
You need to specify which class is your "Profile" by setting AUTH_PROFILE_MODULE = 'accounts.UserProfile' (for example)
https://docs.djangoproject.com/en/1.4/topics/auth/
I'm new to Django and python. I've done login forms but I need to know. How can I connect the contents of the page with the user.
For example: It's a Q&A site. When you logged in, It shows profile page with the questions that user asked before. How the datas are linked to the specific user ID in the model?
Can it be done using the User object? If so, could you give me some simple example with the script?
Thank you.
Anything that "belongs" to a user, should either have a ForeignKey or ManyToManyField (depending on whether the object is owned by one user or many) to User on it. Then you can either filter the model based on the User:
SomeModel.objects.filter(user=some_user)
# where `user` is the name of your foreign key field
Or you can access the model through the user via reverse relations, for example:
class SomeModel(models.Model):
...
user = models.ForeignKey(User)
# Later ...
some_user.somemodel_set.all()
The second method is more typical since you generally have the user already from the request, so in your view, you'd just do:
somemodels = request.user.somemodel_set.all()
To get all the SomeModels that belong to the currently logged-in user.
I'm trying to selectively process a field in my Django/Python application based on whether a user is logged in or not. Basically, I have a model similar to the following:
class Resource(models.Model):
uploaded = models.DateTimeField()
name = models.CharField(max_length=200)
description = models.CharField(max_length=500, blank=True)
file = models.CharField(max_length=200)
What I want to do is for the file attribute to be set to one value if the user happens to be logged in (and has access to this resource based on a test against some permissions backend), and another value if the user is not logged in. So, when any client code tries to access Resource.file, it will get something like the following if the user is not logged in 'http://mysite.com/dummy_resource_for_people_without_access'. However, if the user is logged in and passes some tests for permissions, then the value of resource.file will actually be the true url of that resource (including any security keys etc. to access that resource).
From what I've read, it seems that you can only take account of the currently logged in user by passing that through the request context from a view function to the model. However, in the above use case I am trying to control the access more closely in the model without needing the client code to call a special function.
Your best bet is to create a function used to access the file attribute, and check there. In general, it would possible to turn the attribute into a descriptor which does it implicitly, but Django's metaclass magic would impede that.
In general however, Django is designed to handle authentication at the view-level (and does it very cleanly). If you need database layer authentication, consider a different setup, such as CouchDB.
Just in case anyone's interested, I solved the above issue by actually creating a custom model field in django that could then have a method that takes a user to generate a URI. So, in the database, I store a key to the resource as above in the file column. However, now the file column is some custom field:
class CustomFileField(models.CharField):
def to_python(self, value):
...
return CustomFileResource(value)
class CustomFileResource:
def __init__(self, *args, **kwargs):
....
def uri(usr):
#this method then gets the uri selectively based on the user .
The pattern above is nice because I can wrap the db field and then create a specific method for getting the uri based on who is trying to access it.
I'd like to create a subset of Users that don't have a login... basically as a way to add a photographer field to photos without having a full blown account associated with that person (since in many cases, they'll never actually log in to the site). A caveat is that I'd also like to be able to enable an account for them later.
So, I think the question becomes what's the best way to set up a "People" table that ties to the User table without actually extending the User table with UserProfile.
A user profile (as returned by django.contrib.auth.models.User.get_profile) doesn't extend the User table - the model you specify as the profile model with the AUTH_PROFILE_MODULE setting is just a model which has a ForeignKey to User. get_profile and the setting are really just a convenience API for accessing an instance of a specific model which has a ForeignKey to a specific User instance.
As such, one option is to create a profile model in which the ForeignKey to User can be null and associate your Photo model with this profile model instead of the User model. This would allow you to create a profile for a non-existent user and attach a registered User to the profile at a later date.
Users that can't login? Just given them a totally random password.
import random
user.set_password( str(random.random()) )
They'll never be able to log on.
Supply your own authentication routine, then you can check (or not check) anything you like. We do this so if they fail on normal username, we can also let them in on email/password (although that's not what I'm showing below).
in settings.py:
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'userprofile.my_authenticate.MyLoginBackend', # if they fail the normal test
)
in userprofile/my_authenticate.py:
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
class MyLoginBackend(ModelBackend):
"""Return User record if username + (some test) is valid.
Return None if no match.
"""
def authenticate(self, username=None, password=None, request=None):
try:
user = User.objects.get(username=username)
# plus any other test of User/UserProfile, etc.
return user # indicates success
except User.DoesNotExist:
return None
# authenticate
# class MyLoginBackend
From the documentation on django auth, if you want to use the User model, it's mandatory to have a username and password, there are no "anonymous accounts". I guess you could create accounts with a default password and then give the opportunity for people to enable a "real" account (by setting a password themselves).
To set up a "People" table that ties to the User table you just have to use a ForeignKey field (that's actually the recommended way of adding additional info to the User model, and not inheritance)
Using a model with a ForeignKey field linking to User might not work as you want because you need anonymous access. I'm not sure if that's going to work, but you might try what happens if you let it have a ForeignKey to AnonymousUser (whose id is always None!) instead.
If you try it, post your results here, I'd be curious.
The django.contrib.auth.models.User exists solely for the purpose of using default authentication backend (database-based). If you write your own backend, you can make some accounts passwordless, while keeping normal accounts with passwords. Django documentation has a chapter on this.
Another upvote for insin's answer: handle this through a UserProfile. James Bennett has a great article about extending django.contrib.auth.models.User. He walks through a couple methods, explains their pros/cons and lands on the UserProfile way as ideal.