So let me start with the registration process in my web page. The user would register first, and then right after registration, he/she is redirected to a page where the user has to input his/her personal info, such as self-introduction, full name, etc. When the user completes filling his/her personal info in, then the user will be redirected to home page.
So what I wanted to do is this: When the user tries to access home page, check if he/she is logged in. If yes, check if he/she has filled in the personal info. If no, redirect the user to register page. If the user has filled in (=matching query exists), redirect him/her to the home page. If not, redirect him/her to the personal info page, to fill the fields in. And here's my code in views.py
def userHome(request):
if request.user.is_authenticated:
current_user = request.user
if PersonalInfo.objects.get(authuser_id=current_user.id).exists():
context = {
'thisUser' : thisUser,
'newSeed' : newSeed
}
return render(request, '/userhome.html', context)
else:
return redirect('/inputpersonalinfo')
else:
return redirect('/register')
models.py
from django.db import models
from django.contrib.auth.models import User
class PersonalInfo(models.Model):
objects = models.Manager()
authuser = models.OneToOneField(User, on_delete=models.CASCADE, related_name = 'personalinfo', null=True, default=None)
name = models.CharField(max_length=50)
...
I keep getting an error saying PersonalInfo matching query deos not exist. I do understand why this occurs, but can't think of the solution. Please help.
You have to use filter instead of get when you check if PersonalInfo exists:
PersonalInfo.objects.filter(authuser_id=current_user.id).exists()
get throws an error if there's no object matching the query. filter will return an empty queryset.
See the example in the documentation, and a question about get vs. filter
Even if the answer already provided works, I would avoid simply using exists() simply because I'm often likely to use the result of the query and exists() doesn't return the object. In your case I would rather do something like that:
try:
info = PersonalInfo.objects.get(authuser_id=current_user.id)
context = {
'thisUser' : thisUser,
'newSeed' : newSeed,
'someinfo' : info.whatever
}
return render(request, '/userhome.html', context)
except PersonalInfo.DoesNotExist:
return redirect('/inputpersonalinfo')
Related
I am little bit new to django and was working on my first instagram clone project all by myself. I got confused in a place where I needed to fetch user data based on 127.0.0.1:8000/username and I found a useful but useless answer(for me) from medium(.com) .The author was using class based view. In class based view, I didnot get any documentation to use multiple models as much as I searched so i had to do it with function based view as I have not learned class based view yet.I had to use post model, profile model and User model to get data for profile page.
This is the code that somehow worked but should I use this view?
from django.contrib.auth.models import User
from .models import Profile
#profile view
def profile_data(request, username):
mydata = User.objects.get(username=username)
myprofile = Profile.objects.filter(user=mydata)
mycontext ={'profile': myprofile}
return render(request,'firstapp/profile.html', context=mycontext)
#in urls.py,
from firstapp import views
path('<str:username>/', views.profile_data , name='profile'),
#in models.py,
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,unique=True)
fullname = models.CharField(max_length=100)
def __str__(self):
return self.fullname
In firstapp/profile.html,
<a href="#" class="text-3xl mt-5 text-center">{{user.profile.fullname}}
But I got confused on how to attatch my Profile model in it. So I created this, my own function-based view for it after few hours of researching . Is this ok to use or will give any error in my back? Thank you
I am expecting to get new ways or the correction or additon in my code if possible.
It seems ok, but be careful about the url part, because you will have problems when adding new urls (eg: /login) because it might be treated as a username.
You could get away by editing the order in your urlpatterns so the profile page is the last but now you have an issue if a user has the same username as a url in your page.
For example if a user has "login" as username, you won't be able to go to their profile page.
A solution is to use a prefix for the profile pages (eg: /u/<username> or /#<username>).
Some other improvements:
mydata = User.objects.get(username=username)
myprofile = Profile.objects.filter(user=mydata)
Can be rewriten with only one request:
user = User.objects.get(username=username).select_related("profile")
myprofile = user.profile
See the documentation for select_related: https://docs.djangoproject.com/en/4.1/ref/models/querysets/#select-related
You should also handle the case where the user is not found:
try:
user = User.objects.select_related("profile").get(username=username)
except User.DoesNotExist:
raise Http404("No User matches the given query.")
myprofile = user.profile
This is probably a simple answer but I cant figure it out. I have a comment system on my blog. I need to get the username from the user id.
I get the id from which is a fk to the users table
{{child_comment.parent_userdata_id}}
Usually when I need to do this I just user .username but it doesn't seem to work in this case
The only way you can get object data from the database is to fetch it on the server-side.
Unfortunately, you can't do that on the live HTML template.
Django template is just for evaluating the pre-existing context data for better use.
So, filtering the username from user id in views (backend) and passing it via the context into the template is the only (and probably the best) option.
Assuming user login is required to comment, you can create a variable of user = request.user in your view function, now user variable has the instance of user and pass it as context in template. It would look like this
views.py
def view_function(request):
user = request.user
# do something
context = {
'user' : user,
}
return render(request, 'template.html', context)
template.html
<p>{{user.username}}</p>
reference
Till now i have been using userid's (pk) as an argument in the profile urls for my application. Recently i decided to use the username instead of the user id's So i changed the following :
Urls.py
# This was what i was using previously
url(r'^profile/(?P<uid>\d+)/$', 'app.views.user_profile', name="profile"),
# Changed the above to this.
url(r'^profile/(?P<username>[-\w\d]+)/$', 'app.views.user_profile', name="profile"),
Views.py
# Previous view
#login_required
def user_profile(request, uid):
user = get_object_or_404(models.User, pk=uid)
profile = helpers.get_profile(user)
render_to_response('profile.html', {'profile' : profile})
# Changed the above to
#login_required
def user_profile(request, username):
user = get_object_or_404(models.User, username=username)
profile = helpers.get_profile(user)
render_to_response('profile.html', {'profile' : profile})
Until Now it's all good. When i try to visit 127.0.0.1:8000/profile/some_username/ instead of the previous 127.0.0.1:8000/profile/some_number/ it works fine.
I have a toolbar in the profile.html, which contains links such as:
/profile/edit/
/profile/settings/
in the urls.py these urls map to very simple views. Such as the following.
#login_required
def profile_settings(request):
"""
This view helpers.renders the profile's settings panel
"""
print 'hello'
rec, can = helpers.get_user_or_noprofile(request.user)
if not can is None:
gform = forms.CandidateGeneralSettingsForm(instance=can)
jsform = forms.CandidateJobSearchSettingsForm(instance=can)
data = {'candidate' : can, 'gform' : gform, 'jsform' : jsform }
else:
form = forms.RecruiterSettingsForm(instance=rec)
data = { 'recruiter' : rec, 'form' : form }
return helpers.render(request, 'profile_settings.html', data)
The weird part is after i changed to use username in the profile url. As soon as i click on any of the links in the toolbar, i see the 404 : Error : No User matches the given query. page.
To debug i tried printing a few debug statements within these views and found out something more weird. Nothing gets printed even if i Comment the whole code inside the view and just write a print statement.
This makes me doubt that the problem might be with the login_required decorator. but if that's the case howcome it is working while visitng 127.0.0.1:8000/profile/some_username/.
I really can't think of anything that might be causing this. Any help will be greatly appreciated. Thanks.
PS: Also, JFYI, i am using a custom Email Authentication backend that lets user login through their email address instead of the username.
It doesn't work because edit is not a valid username.
This url /profile/edit/ matches ^profile/(?P<username>[-\w\d]+)/$, and username becomes edit.
Since you don't have a user called "edit", this user = get_object_or_404(models.User, username=username) fails, and raises a 404.
The same for /profile/settings/.
How to get the currently logged-in user's id?
in models.py:
class Game(models.model):
name = models.CharField(max_length=255)
owner = models.ForeignKey(User, related_name='game_user', verbose_name='Owner')
in views.py:
gta = Game.objects.create(name="gta", owner=?)
First make sure you have SessionMiddleware and AuthenticationMiddleware middlewares added to your MIDDLEWARE_CLASSES setting.
The current user is in request object, you can get it by:
def sample_view(request):
current_user = request.user
print current_user.id
request.user will give you a User object representing the currently logged-in user. If a user isn't currently logged in, request.user will be set to an instance of AnonymousUser. You can tell them apart with the field is_authenticated, like so:
if request.user.is_authenticated:
# Do something for authenticated users.
else:
# Do something for anonymous users.
You can access Current logged in user by using the following code:
request.user.id
Assuming you are referring to Django's Auth User, in your view:
def game(request):
user = request.user
gta = Game.objects.create(name="gta", owner=user)
FROM WITHIN THE TEMPLATES
This is how I usually get current logged in user and their id in my templates.
<p>Your Username is : {{user}} </p>
<p>Your User Id is : {{user.id}} </p>
I wrote this in an ajax view, but it is a more expansive answer giving the list of currently logged in and logged out users.
The is_authenticated attribute always returns True for my users, which I suppose is expected since it only checks for AnonymousUsers, but that proves useless if you were to say develop a chat app where you need logged in users displayed.
This checks for expired sessions and then figures out which user they belong to based on the decoded _auth_user_id attribute:
def ajax_find_logged_in_users(request, client_url):
"""
Figure out which users are authenticated in the system or not.
Is a logical way to check if a user has an expired session (i.e. they are not logged in)
:param request:
:param client_url:
:return:
"""
# query non-expired sessions
sessions = Session.objects.filter(expire_date__gte=timezone.now())
user_id_list = []
# build list of user ids from query
for session in sessions:
data = session.get_decoded()
# if the user is authenticated
if data.get('_auth_user_id'):
user_id_list.append(data.get('_auth_user_id'))
# gather the logged in people from the list of pks
logged_in_users = CustomUser.objects.filter(id__in=user_id_list)
list_of_logged_in_users = [{user.id: user.get_name()} for user in logged_in_users]
# Query all logged in staff users based on id list
all_staff_users = CustomUser.objects.filter(is_resident=False, is_active=True, is_superuser=False)
logged_out_users = list()
# for some reason exclude() would not work correctly, so I did this the long way.
for user in all_staff_users:
if user not in logged_in_users:
logged_out_users.append(user)
list_of_logged_out_users = [{user.id: user.get_name()} for user in logged_out_users]
# return the ajax response
data = {
'logged_in_users': list_of_logged_in_users,
'logged_out_users': list_of_logged_out_users,
}
print(data)
return HttpResponse(json.dumps(data))
This is how I usually get current logged in user and their id in my templates.
<p>Your Username is : {{user|default: Unknown}} </p>
<p>Your User Id is : {{user.id|default: Unknown}} </p>
Just go on your profile.html template and add a HTML tag named paragraph there,
<p>User-ID: {% user.id %}</p>
I have the following model
class Team(models.Model):
name = models.CharField(max_length=100)
members = models.ManyToManyField(User, related_name="members", blank=True, null=True)
And the following view
def team_details(request, team_id):
# Look up the Team (and raise a 404 if it is not found)
team = get_object_or_404(Team, pk=team_id)
# check to see if user is authenticated
if request.user.is_authenticated():
# check to see if the authenticated user is listed in members
if team.members == request.user: # This condition always returns False
return render_to_response('teams/team_detail.html', {'team': team},)
else:
# User is in members list, redirect to join team page
return redirect('/join')
else:
# User isn't authenticated, redirect them to login page
return redirect('/login')
The objective of this view is to list the details of a team only if the current authenticated user is a member of the team.
Firstly, is there a better way to do this?
Secondly, I've tried team.members == request.user but this did not work, it always returns False. What would be the correct syntax for the condition of this IF?
Any advice on how to achieve this would be greatly appreciated.
team.members returns a Manager - ie something you then do queries on. So you can do team.members.get(user=request.user) and catch the User.DoesNotExist exception if the user isn't found.
It's always worth exploring this sort of thing in the Python shell - if you had imported Team and done a query to get an instance, you could have just typed team.members and seen what it returned, which would have told you why your initial try wouldn't have worked.