I want to verify user permission in template. If a user has permission he/she will be able to access the template. After writing the below code and I granted the user permission, when I view the page it will fall on the {% else %} statement. showing that the user don't have permission. How can I go about this?
#CREATED A GROUP IN DJANGO ADMIN CALLED 'Premium'
Class Paid(models.Model):
#models here
class Meta:
permissions=(
("view_film","Can view film"),
)
view
def eyo(request):
return render_to_response('eyo.html',context_instance=RequestContext(request))
template
{% block content %}
{% if perms.paid.can_view_film %}
<form action='https://www.test.com/checkout' method='post'>
<input name='submit' type='submit' value='Checkout' />
</form>
{% else %}
<p> yo broke! </p>
{% endif %}
Are you passing perms in your template?
Are you setting perms.paid.can_view_film either explicitly in your view or via the admin interface?
Is the user a part of a group that has the perms.paid.can_view_film permission?
Are you sure the app name is 'paid'? That's supposed to be the app name, not the model name.
Django Perms
I'm doing some conditional rendering based on permissions in a Django project I'm currently working on. A small example of this is a particular icon. Basically if a user has a delete permission, they see one icon, if they don't, they see another. This is how it's done in my templete:
{% if perms.List.can_delete_list %}
<li><span class="fui-search"></span></li>
{% else %}
<li><span class="fui-new"></span></li>
{% endif %}
If the logged in user has can_delete_list, they view one thing. If not, they view something else. Does this help?
Related
I'm new to Django and I'm trying to develop an apllication that deals with learning objects metadata. One of the functions of the system is to view the L.O. metadata in browser.
I have an HTML template that lists the result of the query from the database. Each result come along with a "Visualize Metadata" button, that when clicked, should display the metadata of that object in browser. So I want my button to pass the object ID back to my view, so i can make another query by the specific ID and print the results on the screen.
This is my template .html
{% if objects %}
<ul>
{% for object in objects %}
<li>
{{ object.General.title }}
<form action='visualize' method='POST' name='id' value="{{object.General.id}}">
{% csrf_token %}
<button type="submit" >Visualize Metadata </button>
</form>
</li>
{% endfor %}
</ul>
{% else %}
<p>No results found.</p>
{% endif %}
And this is my views.py function
def visualize_lom_metadata(request):
if request.method == 'POST':
objID = request.POST.get('id')
return HttpResponse(objID)
For now i just want to see if that's possible by printing the objID in the screen. But when I try to do that,it just returns "None". Anyone knows how to retrieve data from template.html to my Django views.py?
I believe that all your forms should have different names and ids, and that submit button must be bound to that form.
It would also help if you in your visualize_lom_data would print entire request.POST to see what you get back from template.
I am looking for some kind of example with flask using a required form on the home page of my site that requires the user to select an option before being allowed onto the rest of the site. The form is used for selecting a collection out of my mongo db database. I need to know what collection the user wants to use before going anywhere else on the site. Once this done I need to make sure I can use this information on my other route and views on my site.
What you want is to implement a login infrastructure.
using flask, you have a base template, where every other template is extending, what you can do is something like the following:
base.html:
{% if current_user.is_authenticated %}
<content>
{% block content %}
{% endblock %}
</content>
{% else %}
<login-form>
{% block content %}
{% endblock %}
</login-form>
{% endif %}
using this code, the content is shown only and only if the user is authenticated. in login-form HTML you should have a form to ask the credentials needed to authenticate the user and then allow them access to rest of the site.
in other template files, you continue to use the same practice:
dashboard.html:
{% extends 'base.html' %}
{% block content %}
<YOUR HTML CONTENT>
{% endblock %}
the content of dashboard.html is only shown to the user, if they are logged in(current_user.is_authenticated = True)
this is because dashboard.html is shown inside the content block of base.html witch is only shown or rendered if that condition is met.
you can use anything else instead of is_authenticated like the collection being selected or anything like that. the procedure to do it is the same.
I have been trying to figure out why my Flask form will not properly validate my select field choices even though the choices are coming from the select field options.
My assumption is that the select option when passed back from the server is unicode and is being compared to the choice which is a string, however, I thought coerce=str would fix that. I printed out the form data and request data which is the output below. Why isn't it working?
My code is attached below, removed csrf token key from the output dict. It seems like a very simple thing, but I can't figure it out.
forms.py
class PlatformForm(FlaskForm):
platform_options = [('test', 'Test'), ('test2','Test2')]
platforms = wtforms.SelectField('Platforms', choices=platform_options, coerce=str, validators=[DataRequired()])
views.py
#app.route('/', methods=['POST', 'GET'])
def index():
form = forms.PlatformForm()
if form.is_submitted():
print form.data
print request.form
if form.errors:
print form.errors
return render_template('home.html', form=form)
index.html
{% extends "base.html" %}
{% block content %}
<h4>Select a Platform</h4>
<form method="POST">
{{ form.csrf_token }}
<select class="custom-select" name="platform">
{% for value, text in form.platforms.choices %}<br>
<option value="{{ value }}">{{ text }}</option>
{% endfor %}
</select>
<button id="submit_inputs" type="submit" class="btn btn-default">Submit</button>
</form>
{% endblock %}
output
{'platforms': 'None'}
ImmutableMultiDict([('platform', u'test')])
{'platforms': [u'Not a valid choice']}
EDIT:
I figured out the problem. It's the way I'm creating the Select drop down through HTML and Jinja. Iterating through the choices and creating option tags doesn't seem to instantiate anything in the form data itself when passed back into Python. Changing that whole for loop to just
{{form.platforms}}
created a select drop down field that actually works.
You have a name mismatch. In the form, you named your select field platforms (plural). In the HTML, you use platform (singular).
I recommend that instead of manually rendering the fields in your template, you let WTForms generate the HTML for you. For the form label, you can use {{ form.platforms.label }}, and for the actual field {{ form.platforms() }}. You can pass any attributes you want to field to have as keyword arguments.
I think something might be going wrong because of the way you are rendering the form in your html file. If my hunch is right, try this:
{% extends "base.html" %}
{% block content %}
<h4>Select a Platform</h4>
<form method="POST">
{{ form.hidden_tag() }}
Select: {{ form.plaforms}}
{{ form.submit(class="btn btn-default") }}
</form>
{% endblock %}
and then try if form.validate_on_submit() in your views.py file
taken from this stack overflow answer by pjcunningham:
"validate_on_submit() is a shortcut for is_submitted() and validate().
From the source code, line 89, is_submitted() returns True if the form
submitted is an active request and the method is POST, PUT, PATCH, or
DELETE.
Generally speaking, it is used when a route can accept both GET and
POST methods and you want to validate only on a POST request."
I'm building a website using Django 1.8.4 and I use django-registration-redux to handle users login and logout.
When all users are logged out, I manually enter a user's profile page, which contains users info and link to edit the profile:
url(r'^users/(?P<slug>\w+)/$', UserProfileDetailView.as_view(), name="profile")
problem is, when I visit a user's page (i.e. /users/james/) it recognizes me as user "james" logged in (is_authenticated) , and show logout and edit profile button, but it shouldn't! it should only show public info. (when I click edit button, it asks me for login credits, so that part works fine)
How can I avoid this situation (showing edit profile, logout, etc. from either random logged in or anonymous users) and only show them to logged in owners of account?
viws.py
class UserProfileDetailView(DetailView):
model = get_user_model()
slug_field = "username"
template_name = "user_detail.html"
def get_object(self, queryset=None):
user = super(UserProfileDetailView, self).get_object(queryset)
UserProfile.objects.get_or_create(user=user)
return user
user_detail.html
<h2>{{ object.username }}'s Profile</h2>
{% if object.userprofile.bio %}
<div>
<b>Bio:</b>
{{ object.userprofile.bio }}
</div>
{% endif %}
{% if object.username == user.username and user.is_authenticated %}
<p><a href='{% url "edit_profile" %}'>Edit My Profile</a></p>
{% endif %}
#footer
{% if user.is_authenticated %}
Logout |
<b>{{ user.username }}</b>
{% else %}
Register |
Login
{% endif %}
The "user" variable in your template's context is being overwritten by the current record being viewed.
Try changing
{% if object.username == user.username and user.is_authenticated %}
to
{% if object == request.user and request.user.is_authenticated %}
I have an application in Django with a routine which would be available only to the admin. What I want to do is add a button to perform the routine in this application's section of the admin app.
Am I supposed to make a template for it, and if that's the case, how do I add a html template for an app in the admin. Or maybe there's a command to simply add a button?
Messing with the admin forms can be complicated but i've commonly found that adding links, buttons, or extra info is easy and helpful. (Like a list of links to related objects witout making an inline, esp for things that are more viewed than edited).
From Django docs
Because of the modular design of the admin templates, it is usually
neither necessary nor advisable to
replace an entire template. It is
almost always better to override only
the section of the template which you
need to change.
This will add a list over the top of the form.
Place in templates/admin/[your_app]/[template_to_override]:
{% extends "admin/change_form.html" %}
{% block form_top %}
{% for item in original.items %}
{{ item }}
{% endfor %}
{% endblock %}
Django1.10:
1) Override admin/submit_line.html:
{% load i18n admin_urls %}
<div class="submit-row">
{% if extra_buttons %}
{% for button in extra_buttons %}
{{ button }}
{% endfor %}
{% endif %}
{% if show_save %}<input type="submit" value="{% trans 'Save' %}" class="default" name="_save" />{% endif %}
{% if show_delete_link %}
{% url opts|admin_urlname:'delete' original.pk|admin_urlquote as delete_url %}
<p class="deletelink-box">{% trans "Delete" %}</p>
{% endif %}
{% if show_save_as_new %}<input type="submit" value="{% trans 'Save as new' %}" name="_saveasnew" />{% endif %}
{% if show_save_and_add_another %}<input type="submit" value="{% trans 'Save and add another' %}" name="_addanother" />{% endif %}
{% if show_save_and_continue %}<input type="submit" value="{% trans 'Save and continue editing' %}" name="_continue" />{% endif %}
</div>
This assumes, of course, that button's string representation is an appropriate browser input or button element, and is marked safe with django.utils.safestring.mark_safe. Alternatively, you could use the safe template filter or access the attributes of button directly to construct the <input>. In my opinion, it's better to isolate such things to the python level.
2) Override MyModelAdmin.change_view:
def change_view(self, request, object_id, form_url='', extra_context=None):
extra_context = extra_context or self.extra_context()
return super(PollAdmin, self).change_view(
request, object_id, form_url, extra_context=extra_context,
)
This method enables you to add buttons to any ModelAdmin easily. Alternatively to step (1), you could extend admin/change_form.html and override block submit_row. This would be slightly more verbose due to extra tags required in the template.
If you want the extra action available across all of your models (or a specific subset) then subclass ModelAdmin with the desired functionality (an example would be to add archiving to your models. You could even add an override for delete--and the other default buttons--so that the mode is archived instead of deleted; this would require some template modifications)
You can also use django-admin-tools, which allows you to easily customize the admin front page like a dashboard. Using a LinkList, you can point to some view method and check if the user is authenticated. It goes like thies:
# dashboard.py (read more about how to create one on django-admin-tools docs)
class CustomIndexDashboard(Dashboard):
"""
Custom index dashboard for captr.
"""
def init_with_context(self, context):
self.children.append(modules.LinkList(
_('Tasks'),
children=[
['Your task name', '/task']
]
))
# urls.py (mapping uri to your view function)
urlpatterns += patterns('yourapp.views',
(r'^task$', 'task'),
)
# views.py
def task(request):
if request.user.is_authenticated():
update_definitions_task.delay() # do your thing here. in my case I'm using django-celery for messaging
return redirect('/admin')
You might consider adding a custom admin action for this kind of object (similar to the built in 'delete'), if appropriate. Some benefits include: "pure Django", not having to mess with templates, and being able to act on multiple objects at once.
Django’s admin lets you write and register “actions” – simple
functions that get called with a list of objects selected on the
change list page. If you look at any change list in the admin, you’ll
see this feature in action; Django ships with a “delete selected
objects” action available to all models.
https://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/
I got the idea from this article on how to add a custom action button, which is another answer all together. I was able to get by with the simpler built-in actions though.
https://medium.com/#hakibenita/how-to-add-custom-action-buttons-to-django-admin-8d266f5b0d41
Don't mess with the admin pages.
Create an "application" for this. Yes, your function is just a "routine". That's okay. Many smaller applications are a good thing.
This application has nothing new in models.py. No new model. Zero lines of code.
This application has a useful URL in urls.py. Something that can be used to display this admin page. One URL. Not many lines of code (less than a dozen.)
This application has one view function in views.py. On "GET", this view function presents the form. On "POST", this view function does the "routine". This is the "heart" of your application. The GET -- of course -- simply returns the template for display. The POST does the real work, and returns a final status or something.
This view function is protected with a decorator so that only an admin can execute it.
See http://docs.djangoproject.com/en/1.2/topics/auth/#django.contrib.auth.decorators.user_passes_test. You want to write a test for being an admin. lambda u: u.is_staff is probably it.
This application has one template, presented by the GET and POST. That template has your form with your button. The one you can't add to admin easily.
The tests.py is a test case with two users, one who is an admin and one who is not an admin.
No messing with built-in admin pages.