I know to access the logged-in user's data we use request.user. My goal is to list all the users in the table and have a link to their profile page. How do I make the link go to the user's profile page?
I have the following:
# app/views.py
def tutors_list(request):
user_list = CustomUser.objects.all()
context = {
'user_list': user_list
}
return render(request, 'tutors_list.html', context)
def show_profile(request, username):
user = CustomUser.objects.get(username = username) ### NOT DISPLAYING RIGHT USER
#user = CustomUser.objects.get(id=id)
context = {
'user': user
}
return render(request, 'show_profile.html', context)
# myproject/urls.py
url_patterns = [
# ...
path('show_profile/', views.show_profile, name='show_profile'),
# ...
I'm getting an error saying show_profile is expecting 1 more argument, username. How exactly would this model work if I need to pull data for a specific user in the database and not the logged-in user?
As your error says show_profile is expecting 1 more argument, username, so you need to pass username in your url pattern:
path('<str:username>/show_profile/', views.show_profile, name='show_profile'),
Related
I have two models: Faculty and Student. Both have a username and password.
I want to check if the username and password input provided is present in either of them. In the view, I can do a simple check on one model like this:
try:
user = Student.objects.get(username=username, password=password)
except Student.DoesNotExist:
error_message = "**Incorrect login. Please try again."
context = {'error_message' : error_message}
return render_to_response('myapp/login.html',context, context_instance=RequestContext(request))
Can you point out how to do the same for both Faculty and Student at the same time?
The simplest way is probably just to try the second query if the first fails:
context = {}
try:
user = Student.objects.get(username=username, password=password)
except Student.DoesNotExist:
try:
user = Faculty.objects.get(username=username, password=password)
except Faculty.DoesNotExist:
error_message = "**Incorrect login. Please try again."
context['error_message'] = error_message
# rest of your view here
return render_to_response('myapp/login.html', context, context_instance=RequestContext(request))
By the way, you can save yourself some effort if you use django.shortcuts.render instead of render_to_response:
from django.shortcuts import render
...
return render(request, 'myapp/login.html', context)
I suggest, you should use custom user model to join your models and classic django auth utils.
I got, following Error messages,
TypeError at /save/ int() argument must be a string or a number, not
'SimpleLazyObject'
While executing following form.
views.py
def bookmark_save_page(request):
if request.method == 'POST':
form = BookmarkSaveForm(request.POST)
if form.is_valid():
# create or get link
link, dummy = Link.objects.get_or_create(
url = form.cleaned_data['url']
)
# create or get bookmark
bookmark, created = Bookmark.objects.get_or_create(
user=request.user,
link=link
)
# update bookmarks title
bookmarks.title = form.cleaned_data['title']
# if the bookmark is being updated, clear old tag list.
if not created:
bookmark.tag_set.clear()
# create new tag list
tag_names = form.cleaned_data['tags'].split()
for tag_name in tag_names:
tag, dummy = Tag.objects.get_or_create(name=tag_name)
bookmark.tag_set.add(tag)
# save bookmark to database.
bookmark.save()
return HttpResponseRedirect(
'/user/%s/' % request.user.username
)
else:
form = BookmarkSaveForm()
variables = RequestContext(request, {
'form': form
})
return render_to_response('bookmark_save.html', variables)
I thought I got error because I passed link at
bookmark, created = Bookmark.objects.get_or_create(
user=request.user,
link=link
)
But I can not figure out how to fix it.
How can I fix it?
The likely cause is that you're setting user = request.user, where request.user is not a real User object, but a SimpleLazyObject instance. See django: Purpose of django.utils.functional.SimpleLazyObject? for more details, but using request.user.id should fix your issue.
You have to login when running this piece of code on localhost. Otherwise the request.user will be a SimpleLazyObject, then the errors comes out.
Here you trying to create a Bookmark object based on request.user , but request.user is a SimpleLazyObject , so we can get a more secure user object by :
from django.contrib import auth
current_user = auth.get_user(request)
and further your query should be
bookmark, created = Bookmark.objects.get_or_create(
user=current_user,
link=link
)
Most likely the user who is loading the page is not authenticated. Therefor the error is thrown. If you want to save a request.user reference to the database, you obviously have to ensure that only authenticated users are able to call the function.
In your case there are two possibilities - add the "#login_required" decorator to the function or check if the user is authenticated inside the code. Here are the snippets:
With Decorator:
from django.contrib.auth.decorators import login_required
#login_required
def bookmark_save_page(request):
if request.method == 'POST':
form = BookmarkSaveForm(request.POST)
if form.is_valid():
# Do something
OR - checking inside the code if the user is authenticated:
def bookmark_save_page(request):
if request.method == 'POST' and request.user.is_authenticated():
form = BookmarkSaveForm(request.POST)
if form.is_valid():
# Do something
Thats strange, I had the same problem and the same solution. After trying a bunch of alternatives I went back to user = request.user and it worked
if you want to set an addition request attr, based on user -> you need to use lazy Django function which is correctly handled by Field.get_prep_value
from django.utils.functional import lazy
request.impersonator = lazy(lambda: request.user.id, int)()
Am new to django framework,am just trying to create seperate login form other than administrator login.I need to authenticate a user using username and password, fetch the details of that user from database and pass that data to a templae (home page) to display it.
My code is as follows:-
view.py:-
def login_user(request):
user = ''
passw = ''
username1 = ''
if request.POST:
user = request.POST.get('username')
passw = request.POST.get('password')
#password1 = ''
try:
userdata = Employee.objects.get(username = user, password = passw)
user_id = request.session["user_id"] = userdata.id
employee_details = Employee.objects.get(id=user_id)
request.session['user_id'] = employee_details.id
return HttpResponseRedirect('/home/', kwargs={'user_id': employee_details.id}))
except Employee.DoesNotExist:
state = "Username or password incorrect !"
return render_to_response('login.html',
{'username' : username1,'state' : state},
context_instance = RequestContext(request))
else:
state = "Please login here:"
return render_to_response('login.html' , {'state' : state} ,
context_instance = RequestContext(request))
i tried using kwargs={'user_id': employee_details.id} but it is not working.How can i pass datas to home page after redirecting?
Thanks
You can not redirect user using POST request. Use GET parameter instead.
In your case the requested data is already stored in session. Just try to read from the session on next request. Django contrib.auth uses user.is_authenticated method for the job.
i tried using kwargs={'user_id': employee_details.id} but it is not working.How can i pass datas to home page after redirecting?
You can:
use session variables
use "get" variables (pass variables encoded in the URL like '/home/?a=1&b=2', see urllib.urlencode)
However you should be using the standard Django user related functions and methods. See "How to log a user in". TLDR:
check credentials: user = authenticate(username=username, password=password)
test if user is not None and any other tests you want (is he active, has some privilege, etc)
mark the request.user as authenticated: login(request, user)
I'm building a Django app and am trying to use twython-django to authenticate a Twitter user when they submit a form. I have tried to edit my views.py, urls.py and models.py files as suggested by this example https://github.com/ryanmcgrath/twython-django/tree/master/twython_django_oauth but I'm simply guessing at it so I'm sure that's why it isn't working.
Could you please help me out with how to get this working? I'm completely new to Twitter wrappers so any help would very much be appreciated.
The flow I'm trying to achieve:
User submits a message through the form
User is asked to authenticate their Twitter account on hitting "Submit" button
User's message, Twitter name, Twitter screen_name, profile_image_url and followers_count are saved in the database (I'm using Heroku Postgres)
User's profile image, name, screen_name and message are printed to index.html in a (Twitter-like) feed.
My views.py:
def logout(request, redirect_url=settings.LOGOUT_REDIRECT_URL):
django_logout(request)
return HttpResponseRedirect(request.build_absolute_uri(redirect_url))
def submit(request):
twitter = Twython(
twitter_token=settings.TWITTER_KEY,
twitter_secret=settings.TWITTER_SECRET,
callback_url=request.build_absolute_uri(reverse('alpha.views.submit'))
)
auth_props = twitter.get_authentication_tokens()
request.session['request_token'] = auth_props
return HttpResponseRedirect(auth_props['auth_url'])
form = MessageForm(request.session.get('message'))
if form.is_valid():
new_message = form.save()
return HttpResponseRedirect('/')
else:
request.session['message'] = request.POST
twitter = Twython(
twitter_token = settings.TWITTER_KEY,
twitter_secret = settings.TWITTER_SECRET,
oauth_token = request.session['request_token']['oauth_token'],
oauth_token_secret = request.session['request_token']['oauth_token_secret'],
)
authorized_tokens = twitter.get_authentication_tokens()
try:
user = User.objects.get(username = authorized_tokens['screen_name'])
except User.DoesNotExist:
user = User.objects.create_user(authorized_tokens['screen_name'], authorized_tokens['oauth_token_secret'])
profile = Message()
profile.user = user
profile.name = name
profile.profile_image_url = profile_image_url
profile.oauth_token = authorized_tokens['oauth_token']
profile.oauth_secret = authorized_tokens['oauth_token_secret']
profile.save()
user = authenticate(
username = authorized_tokens['screen_name'],
password = authorized_tokens['oauth_token_secret']
)
login(request, user)
return HttpResponseRedirect(redirect_url)
Disclaimer: I'm a newbie so the above code is probably a complete mess!
Yes, your use-case is different from that intended by twython-django, but that doesn't mean it's not going to work in your case, and you can use the library as it stands with your flow. After setting up everything as described on the main page, you'll need something like this for your views.py:
from django.shortcuts import redirect, reverse
def submit(request):
# initial form submission, first check if we're authenticated
# if we are, process as normal, otherwise redirect to the login
# page. If you've set up twython-django correctly, it'll redirect
# to twitter for the actual login.
if request.method == "POST":
if request.user.is_authenticated():
form = MessageForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
else:
# Modify this to display validation errors
pass
else:
request.session['message'] = request.POST
# the reverse(submit) resolves this view for redirection
# back from the twitter authentication
return redirect(settings.LOGIN_URL, next=reverse(submit))
# A Get request, where we should first check for the message stored
# We then process the form and remove it from session to prevent
# accidental re-use.
else:
if 'message' in request.session and request.user.is_authenticated():
form = MessageForm(request.session['message'])
del request.session['message']
if form.is_valid():
form.save()
return redirect('/')
else:
# Modify this to display validation errors
pass
else:
# handle the case where this is a get request and the variable
# isn't in session
pass
As for loading their profile image and follower count, those are not currently handled at all by twython django. You can either fork it on github and add them to the TwitterProfile model and add the appropriate code to the thanks view to load those too, or you can add a new model to your code which extends TwitterProfile.
from twython_django_oauth.models import TwitterProfile
from django import models
class ExtendedTwitterProfile(models.Model)
profile = models.OneToOne(TwitterProfile, related_name="extended")
avatar = models.CharField(max_length=255)
followers = models.IntegerField()
And add the code into the submit view to add/update the profile as needed.
extended_profile = ExtendedTwitterProfile.objects.get_or_create(profile=request.user.twitterprofile)
extended_profile.avatar = avatarurl
extended_profile.followers = followercount
extended_profile.save()
You should be able to access those details via
user.twitterprofile.extended.avatar
Although, I have in the past used a url to get the avatar, for example:
# avatar redirection urls
url(r'^avatar/(?P<userid>[0-9A-Za-z_]+)$', redirect_to,
{ 'url' : 'http://api.twitter.com/1/users/profile_image/%(userid)s.json' }, name='avatar' ),
url(r'^avatar/(?P<userid>[0-9A-Za-z_]+)/(?P<size>[a-z]+)$', redirect_to,
{ 'url' : 'http://api.twitter.com/1/users/profile_image?screen_name=%(userid)s&size=%(size)s' } ),
In a template where you want to display the avatar, you simply use and img tag using the url template tag to do the reverse url resolution, like so:
<img src="{% url avatar userid=request.user.username %}" />
As a further pointer, you can also request all of the users' basic details via Twitter's json API
https://twitter.com/users/zandeez.json
For example, will get you my public profile in a form you can use either in python using urllib or even javascript/ajax depending on what you want to do with the follower count.
Hopefully that should get you sorted, if you need any more help fell free to ask.
My views.py:
#login_required
def some_views(request):
if request.method == 'POST':
form = AddressCreateFrom(request.POST)
if form.is_valid():
name = form.cleaned_data['Address']
ip_value = form.cleaned_data['value']
user_list = get_username(name)
address_create = form.save()
extra_context = {
'user_list': user_list
}
return redirect_to(request, url=address_create.get_absolute_url())
else:
form = AddressCreateFrom()
extra_context = {
'form':AddressCreateFrom(initial={'user': request.user.pk})
}
return direct_to_template(request,'networks/user_form.html',extra_context)
In form.py:
class AddressCreateFrom(forms.ModelForm):
Address = forms.CharField(max_length=40)
value = forms.CharField(max_length=40)
class Meta:
model = Network
widgets = {
'user': forms.HiddenInput()
}
As you see that i am using Django model form with two extra Django form field i.e. Address and value in AddressCreateForm class. I need all of the field at the time of rendering the template.
Indeed some_views method are working fine but i also want render some extra data written in context_dictionary i.e. user_list to a requesting URL i.e. address_create.get_absolute_url().
If i am not wrong, if we are handling with the database we have to use redirect_to method. Is it possible to do that?
A redirect will return a HTTP response with status code 301 or 302, and the location to redirect to:
301 MOVED PERMANENTLY
Location: http://www.example.com/new-url/
There is no template rendered by the original view, so you can't pass extra_context to it.
The user's browser will usually follow the redirect, and request the new URL.
If you want to display information about a particular user in the next view, you have to do something like:
design your URL pattern to include the user id, e.g. /users/200/,
include it as a get parameter e.g. /users/?id=200, then fetch the user id from request.GET in the view.
store the user_id in the session
Before redirecting, create a message using the messages framework using the user data.
Then in the view that you redirect to, you can fetch the user from the database, and add it to the template context.
Context, Extra Context and POST Data will not survive the redirect.
Here is what you can do.
# before the redirect
....
request.session['user_list'] = user_list
return redirect_to(request, url=address_create.get_absolute_url())
# after the redirect (in the views.py that handles your redirect)
....
user_list = request.session['user_list']
extra_context = { 'user_list': user_list }
....
# now you have the user_list in the extra_context and can send it to the rendering engine.
Note: This solution only works for redirects within your own server.