I have created a small project using python social auth for logging with facebook.I have referred python social auth example at link.I can able to get the user name with request.name.But how can i get the other data like first_name,last_name,email.Any help would be appriciated
example code in views is:
def home(request):
context = RequestContext(request,
{'request': request,
'user': request.user})
return render_to_response('home.html',
context_instance=context)
Here is one way: request.user has a helper method called is_authenticated, which you can use like this:
ctx = {
'user' : request.user
}
if request.user.is_authenticated():
ctx.update({
'first_name': request.user.first_name,
'last_name': request.user.last_name,
'email' : request.user.email
})
Now, the extra attributes are present only if the user is authenticated
This is, assuming you are using the auth model of django. If not, please change the model field names accordingly.
On a side note, you should not be passing the entire request object in the context. You should be extracting only the relevant info and sending it in the context.
Now, you can access all these values from the template anyways. Example:
{% if request.user.is_authenticated %}
{{request.user.username}}
{{request.user.email}}
{# etc.. #}
{% endif %}
No need to send anything in the context explicitly. The request object already has everything
Related
Using Django I want to implement some middleware that will calculate some context that is to be used by the view itself.
For example, I have a middleware that looks at the request, and adds the user's permissions to the request, or some user configuration. The view looks at these permissions and decides how to handle the request using it.
This saves the need for multiple views (and multiple parts within the view) to query for this information.
I'm wondering what is the correct way to do that. One option is to just add request.user_permissions=... directly on the request. But is there some documented and expected way to do that?
There's no real documented way to do that, but Middleware is the correct place to do it and just adding properties to the request object is also the correct way.
You can confirm this, because Django is already doing it:
LocaleMiddelware
AuthenticationMiddleware
RemoteUserMiddleware
CurrentSiteMiddleware
SessionMiddleware
So just pick whatever is the most convenient data structure for your use case and tack that on to the request object.
This is not a perfect answer but at my experience I use this code. Every permission is saved in a boolean value which is true or false. You can access it in a html template like.
{% if request.user.is_admin %}
"Your code here"
{% else %}
"Your code here"
{% endif %}
and to send extra context you should create and pass an dicionary and pass it as as an argument to the render method from the view.
For eg:
def view(request, slug):
context = {'administrator':True}
blog_post = get_object_or_404(BlogPost, slug=slug)
context['blog_post'] = blog_post
return render(request, 'blog/detail_blog.html', context)
and access it like
{% if context.administrator %}
"Your code here"
{% else %}
"Your code here"
{% endif %}
I believe, since your middleware will calculate context, it should be implemented as context processor.
https://docs.djangoproject.com/en/3.1/ref/templates/api/#using-requestcontext
https://docs.djangoproject.com/en/3.1/ref/templates/api/#writing-your-own-context-processors
I'm using Django 2.1.
I'm having a problem with a CreateView because I need to redirect to the update url, but that url contains one argument that is created manually after verifying that the form is valid.
This is the view code:
class ProjectCreateInvestmentCampaignView(LoginRequiredMixin, SuccessMessageMixin, generic.CreateView):
template_name = 'webplatform/project_edit_investment_campaign.html'
model = InvestmentCampaign
form_class = CreateInvestmentCampaignForm
success_message = 'Investment campaign created!'
def get_success_url(self):
return reverse_lazy('project-update-investment-campaign',
args=(self.kwargs['pk'], self.object.campaign.pk, self.object.pk))
def form_valid(self, form):
project = Project.objects.get(pk=self.kwargs['pk'])
form.instance.investment_type = "A"
form.instance.contract_type = "CI"
form.instance.history_change_reason = 'Investment campaign created'
valid = super(ProjectCreateInvestmentCampaignView, self).form_valid(form)
if valid:
campaign = CampaignBase.objects.create(project=project, )
form.instance.campaign = campaign
form.instance.campaign.project = project
form.instance.campaign.creation_date = timezone.now()
form.save()
return valid
As you can see, on the form_valid I validate first the form, and then I create the object campaign and assign all the related data. This is working fine.
The problem came when I changed the get_success_url to fit my use case, that is redirecting to the update view.
I debugged and saw that at the moment I create the variable valid on the form_valid, it checks the success url, and that triggers me the following error:
Exception Type: AttributeError
Exception Value:
'NoneType' object has no attribute 'pk'
Exception Location: /Volumes/Archivos/work/i4b/webplatform/views/investor_campaign_views.py in get_success_url, line 25
I asume that the error is because the campaign is not created yet so it's trying to get the pk from a non existing object.
The thing is that I cannot create the campaign if the form is not validated, but I need the campaign to make the url working (that url is working as it is on the UpdateView that I already have).
It will only invoke get_success_url after form_valid. So it's up to form_valid to create and save the objects needed. If it's valid for them not to be created, you need a different approach. Maybe initialize (say) self.campaign_pk = 0, update it if a campaign can be created with the pk of the campaign object, and let the next view sort out what to do when pk==0. Or,
...
args=(self.kwargs['pk'],
self.object.campaign.pk if self.object.campaign else 0,
self.object.pk))
(I don't fully follow your code so I might be barking up the wrong tree here)
It may be that you don't want CreateView but FormView, which doesn't handle object creation for you, so you may find greater flexibility over how to process a valid form that nevertheless cannot be fully honoured all the time. Or even, just a plain old function-based view, in which you can process two or more forms and be far more able to decide on conditions that constitute non-validity even after all the forms have technically validated.
This is a function-based view structure I have used where I have two forms to process, and a fairly long but boring set of operations to do after BOTH forms validate:
def receive_view( request):
# let's put form instantiation in one place not two, and reverse the usual test. This
# makes for a much nicer layout with actions not sandwiched by "boilerplate"
# note any([ ]) forces invocation of both .is_valid() methods
# so errors in second form get shown even in presence of errors in first
args = [request.POST, ] if request.method == "POST" else []
batchform = CreateUncWaferBatchForm( *args, layout=CreateUncWaferBatchLayout )
po_form = CreateUncWaferPOForm( *args, layout = CreateUncWaferPOLayout, prefix='po')
if request.method != "POST" or any(
[ not batchform.is_valid(), not po_form.is_valid() ]):
return render(request, 'wafers/receive_uncoated.html', # can get this out of the way at the top
{'batchform': batchform,
'po_form': po_form,
})
#it's a POST, everything is valid, do the work
...
return redirect('appname:viewname', ...)
For me, get_success_url was not invoked as the form was not valid (was invalid) and I didn't know. You can override form_invalid(self, form) to control the behavior.
Also, consider this block of code to show any errors in your template
{% if form.errors %}
<div class="alert alert-danger" role="alert">
{% for field, errors in form.errors.items %}
{% for error in errors %}
<b>{{ field }}</b>: {{ error }}
{% endfor %}
{% endfor %}
</div>
{% endif %}
I would like to get your advices in order to block the url modification by my clients.
For example, I have a client in my website and he will redirect to his own page after the log process.
His homepage url looks like : http://localhost:8000/Compagny/id/ with id corresponding to the Compagny1.
For example : http://localhost:8000/Compagny/1/ with 1 is the first Compagny
But, in the url bar, if my client writes : http://localhost:8000/Compagny/2/ he will be redirected to Compagny2's homepage and I don't want this possibility.
My question is :
How I can implement some rules, functions, or anything else in order to set unchangeable the url adress ? Client couldn't change the url and see the homepage which make reference to another client ?
Thank you
EDIT :
This is my homepage view :
#login_required
def HomePage_Compagny(request, id) :
compagny = get_object_or_404(Compagny, pk=id)
intervention = CompagnyIntervention.objects.filter(Compagny__id=id).all()
pointsajoutes = CompagnyAjout.objects.filter(Compagny__id=id).all()
coefficient = CoefficientIntervention.objects.last()
if request.method == 'POST':
form_ajout = ContratAjoutFormulaire(request.POST or None)
if form_ajout.is_valid() :
#Several processes
return HttpResponseRedirect('http://mywebsite/'+id)
else:
form_ajout = ContratAjoutFormulaire()
context = {
...
}
return render(request, 'CompagnyHomePage.html', context)
My url for this part is : url(r'^Compagny/(?P<id>\d+)/$', views.Homepage_Compagny, name="Homepage"),
You can't prevent the user from typing a url in their browser. Instead, you should restrict access in the view, and return 404 if the user is not allowed to access that company.
For example, if the Compagny has a foreign key to User, then you could do:
#login_required
def HomePage_Compagny(request, id) :
compagny = get_object_or_404(Compagny, pk=id, user=request.user)
...
In your views.py file where you wrote the function for the page you should use user=request.user with this given you can apply multiple methods to block users from specific sites.
use the if user.is_authenticated(): method in views.
give users a group and deny access to specific pages
check in the template if the current user is allowed to see the site
If a user visits a url you can redirect him to the main page or display a 404 or tell him that he does not have access rights for this site.
For Example in the template you can display an error message like:
{% if request.user == pageowner %}
the site code
{%else%}
<h1>This is not your Site. Please Go back</h1>
{%endif%}
in the views.py function you would have to define a "pageowner" attribute where you define a user who "owns" or at least created that Page.
I have edit_client view, Client model and a ClientForm. What I need is to edit an existing record from Client but display it as an editable form, and save the updated record. What should be seen in my views.py and my edit_client.html?
You can create a function named : edit_client into your view file.
As an example, you can use a link in your html like this :
<a href="{% "edit_client" client.pk %}> {{ client.name }} </a>
And your function can be :
def edit_client(request, client_id):
client = Client.objects.get(pk=client_id)
clients = Client.objects.all()
if request.method = "POST":
# what you want to edit (name, age etc ...)
client.save()
return render_to_response('index.html', {"clients":clients}, context_instance=RequestContext(request))
else:
return render_to_response('edit_client.html', {"client":client}, context_instance=RequestContext(request))
Note that it will be different if you want to use a form.
I currently have a DetailView for Django's built-in User.
url(
r'^users/(?P<pk>\d+)/$',
DetailView.as_view(
model = User,
template_name = 'doors/users/detail.html'
),
name = 'users_detail'
)
But when I access user in the template, it brings up the current logged in user, not the user with the pk that I pass from DetailUser. Do I need to tell DetailUser to rename the user variable to something else? And if so, how do I do that?
The django.contrib.auth.context_processors.auth sets the {{ user }} template context variable to either request.user or AnonymousUser. So, it overrides the {{ user }} context variable created by your DetailView:
def auth(request):
"""
Returns context variables required by apps that use Django's authentication
system.
If there is no 'user' attribute in the request, uses AnonymousUser (from
django.contrib.auth).
"""
# If we access request.user, request.session is accessed, which results in
# 'Vary: Cookie' being sent in every request that uses this context
# processor, which can easily be every request on a site if
# TEMPLATE_CONTEXT_PROCESSORS has this context processor added. This kills
# the ability to cache. So, we carefully ensure these attributes are lazy.
# We don't use django.utils.functional.lazy() for User, because that
# requires knowing the class of the object we want to proxy, which could
# break with custom auth backends. LazyObject is a less complete but more
# flexible solution that is a good enough wrapper for 'User'.
def get_user():
if hasattr(request, 'user'):
return request.user
else:
from django.contrib.auth.models import AnonymousUser
return AnonymousUser()
return {
'user': SimpleLazyObject(get_user),
'messages': messages.get_messages(request),
'perms': lazy(lambda: PermWrapper(get_user()), PermWrapper)(),
}
You can work around the issue by setting context_object_name. For example, this will enable the {{ user_object }} context variable, set to the user of the DetailView:
url(
r'^users/(?P<pk>\d+)/$',
DetailView.as_view(
model = User,
template_name = 'doors/users/detail.html',
context_object_name = 'user_object'
),
name = 'users_detail'
)
Dig deeper, read the documentation for get_context_object_name().