I have a RESTful django webapp that allows users to take quizzes in a progressive system where the quizzes become increasingly difficult. Their progress is saved when they answer a question. I'm using django-rest-framework.
class User(AbstractUser):
pass
class IntervalsProfile(models.Model):
# Belongs to User model in 1-to-1 relationship
# If User is deleted, then the corresponding IntervalsProfile will be deleted as well
user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='profile', on_delete=models.CASCADE)
level = models.IntegerField(default=0)
current_level = models.IntegerField(default=0) # Level the user is currently viewing/on
I would like users to be able to play as a guest, and if they so choose, register in order to save their progress. I cannot figure out how to save this guest information or how to save it once they register.
I've searched thoroughly and all the solutions I see are either several years old or seem too cumbersome (such as adding a check for authentication in every view and having 2 cases for each view).
Any advice or guidance would be much appreciated.
if they so choose, register in order to save their progress
Subclass django's User model and add a new field called is_guest = BooleanField. (django has good documentation on how to do this already.)
Ask your users to input just a username when they visit for the first time. (or you can also assign them a random username using something like coolname).
Create a User instance for their chosen username with is_guest=True without any password and now you can save all the game information anyway corresponding to this user.
Tomorrow, when they choose to register, you can simply update the already existing User instance and mark is_guest=False.
EDIT:
If you don't want the added complexity of your own User model, you could also achieve the same without subclassing User model and just adding the is_guest column to the IntervalsProfile model
I'm working on small project with Django framework. And as I can implement usage of authentication mechanism, that I can find a solution how to use information about logged user with model I define.
In example. I have model that will store information about QSL cards, and I want to have option that depends on which user is logged, his/her QSL cars will be shown from database.
I search here and in docs.djangoproject.com but without success.
Thanks in advance for any tips or links.
If you try,
user = request.user
Variable user will have currently logged in user object. You can use this user to filter some models objects where user is foreign key. For e.g posts = Post.objects.filter(user=request.user). If you want to get any specific user information, for e.g username. You can try username = request.user.username
I use "msignup" model for user signups. after signup is complete which works just fine, in the profile of the user I want to let them change some basic information that they used during the signup (which are saved in database in msignup model) using modelform named "accountSettingsForm".
Obviously the original user information must be there in the "accountSettingsForm " and the user would change any piece of information he/she likes.
I know it is possible to set the initial value of the accountSettingsForm:
form = accountSettingsForm(initial={'someFieldName':snomeVariable})
But I assume there is a better way of doing this that I don't know about.
Probably using __init__ methods is more appropriate.
Any helps will be greatly appreciated.
First of all I have tried to research my problem but have not been able to find what I need. My problem might be related to the design of my project (any help would be appreciated).
The problem I am facing is as follows:
I have a few models
I have a model that would be used specifically to create a ModelForm
In this model I have ForeignKey field that is represented by default as a select/option input widget in the ModelForm (for each the value attribute is the ForeignKey and text between the tags is the __str__() of the model the ForeignKey points to. The user sees the __str__() and value attribute of the option tag is submitted which is great).
So far so good but I want to replace the widget with an input text field so I can implement it as a search field.
Now when the user submits the form the string entered in the text input field is submitted and of course django doesn't like that since it expects a foreign key
I already can think of a few solutions to the problem and I am sure I can make it work but each of them feels like I would be violating some best practices. So my question is what should I do?
Do I exclude this particular field from the ModelForm and implement it as an input text field then after form submission make a query with it's value and then store the ForeignKey to the DB
Do I manipulate the data with JavaScript upon submission so that Django receives correct information
Can I clean this fields data with Django and transform it from string to FK?
Am I going the wrong way with this or there is a Django feature for this type of situation?
If anyone has the same problem here is the solution (to my problem at least):
I tried to use the clean_<fieldname> method to change the user entered string to database id. The method wasn't executing because the validation process was stopping earlier because of the difference between the form field and the widget. I redefined the form field to CharField so that step of the validation was working and then the clean_<fieldname> method executes without a problem.
The default Django's User model has some fields, and validation rules, that I don't really need. I want to make registration as simple as possible, i.e. require either email or username, or phone number - all those being unique, hence good as user identifiers.
I also don't like default character set for user name that is validated in Django user model. I'd like to allow any character there - why not?
I used user-profile django application before to add a profile to user - but this time I'd rather make the class mimimal. But I still want to use the User class, as it gives me an easy way to have parts of site restricted only for users logged in.
How do I do it?
Rather than modify the User class directly or do subclassing, you can also just repurpose the existing fields.
For one site I used the "first_name" field as the "publicly displayed name" of a user and stuff a slugified version of that into the "username" field (for use in URLs). I wrote a custom auth backend to allow people to log in using their "public name" or their email address, and I enforce the uniqueness of both of those at registration time. This plays nicely with other reusable apps and doesn't introduce extra tables or queries.
For another site I didn't want usernames at all, just unique emails. In order to satisfy Django's need for a unique username, I just hashed the email address and used that as the username (you have to base64-encode the hash to squeeze it under 30 characters). Custom auth backend to allow login with email.
If backwards-compatibility weren't an issue, there are a lot of improvements I'd love to see made to django.contrib.auth and the User model to make them more flexible. But there's quite a lot you can do inside the current constraints with a little creativity.
I misread the question. Hope this post is helpful to anyone else.
#in models.py
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.ForeignKey(User)
#other fields here
def __str__(self):
return "%s's profile" % self.user
def create_user_profile(sender, instance, created, **kwargs):
if created:
profile, created = UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_user_profile, sender=User)
#in settings.py
AUTH_PROFILE_MODULE = 'YOURAPP.UserProfile'
This will create a userprofile each time a user is saved if it is created.
You can then use
user.get_profile().whatever
Here is some more info from the docs
http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
The Django User model is structured very sensibly. You really don't want to allow arbitrary characters in a username, for instance, and there are ways to achieve email address login, without hacking changes to the base model.
To simply store additional information around a user account, Django supports the notion of user profiles. While you don't need to rely on the built in support to handle this, it is a convention that is commonly followed and it will allow you to play nice with the reusable Django apps that are floating around in the ether. For more information, see here.
If you want to actually modify the core User model but also "play nice" with reusable apps that rely on it, you're opening a bit of a Pandora's Box. Developers make base assumptions about how the core library is structured, so any changes may cause unexpected breakage. Nonetheless, you can monkeypatch changes to the base model, or branch a copy of Django locally. I would discourage the latter, and only recommend the former if you know what you're doing.
You face a bit of a dilemma which really has two solutions if you're committed to avoiding the profile-based customization already pointed out.
Change the User model itself, per Daniel's suggestions
Write a CustomUser class, subclassing User or copying its functionality.
The latter suggestion means that you would have to implement some things that User does automatically manually, but I wonder whether that's as bad as it sounds, especially if you're at the beginning of your project. All you'd have to do is rewrite a middle-ware class and some decorators.
Of course, I don't think this buys you anything that 1 won't get you, except that your project shouldn't break if you svn update your django. It may avoid some of the compatibility problems with other apps, but my guess is most problems will exist either way.
There are anumber of ways to do this, but here's what I'd do: I'd allow a user to enter an email, username (which must contain at least one letter and no # symbols) or mobile number. Then, when I validate it:
Check for the presence of #. If so, set it as the user's email, hash it appropriately and set it as their username as well.
Check to see if it's only numbers, dashes and +. Then, strip the appropriate characters and store it as both mobile number and username (if you're storing the mobile number in another model for SMS purposes or something).
If it's not either, just set it as username.
I'd also validate the user/phone/email field similarly on login and look in the appropriate place so that if, say, a user signs up with their mobile number and then changes their username (for some other purpose), they can still sign in with their mobile number.