Check if a view has a decorator flask - python-3.x

I want to somehow check if a endpoint has a decorator like login_required, is there a way I could do it?
This is how I get all url_rules:
def has_no_empty_params(rule):
defaults = rule.defaults if rule.defaults is not None else ()
arguments = rule.arguments if rule.arguments is not None else ()
return len(defaults) >= len(arguments)
def sitemap():
links = []
for rule in
if "GET" in rule.methods and has_no_empty_params(rule):
url = flask.url_for(rule.endpoint, **(rule.defaults or {}))
links.append((url, rule.endpoint))
return links
This is my navigation bar in which I use these, but I want to somehow not display the views who have the decorator login_required.
{% for url, endpoint in endpoints %}
{% if request.url_rule != endpoint %}
<a href="{{ url }}">
<button class="tablecontent">{{ endpoint.split('.', 1)[1] }}</button>
</a>
{% endif %}
{% endfor %}
I am sorry for the late edit, but if someone is still here, any help would be appreciated. Or maybe I should better hard code the view names in a dictionary?

Related

Hide buttons if user doesn't belong to any of Django groups

My problem is that I want to hide the button from all users who are not in group1 and group2 or in both groups. I did the following thing but it seems doesn't work at all.
My views.py:
def is_group1(user):
return user.groups.filter(name='Group1').exists()
def is_group2(user):
return user.groups.filter(name='Group2').exists()
def employee_list(request):
groups = [g.name for g in request.user.groups.filter(name__in=['Group1', 'Group2'])]
context = {'employee_list': Employee.objects.filter(dept__in=groups)}
return render(request, 'employee_register/employee_list.html', context)
My little example of employee_list.html:
<form>
{% if user.is_group1 %}
<button formaction="{% url 'employee_insert' %}">Add</button>
{% if user.is_group2%}
<button formaction="{% url 'employee_insert' %}">Add</button>
{% else %}
<p>You are not logged</p>
{% endif %}
</form>
Any thoughts how I can implement this ?
In order to hide a button if a user does not belong to a group, you can implement following method:
First, set-up categories using AbstractUser:
class CustomUser(AbstractUser):
class StatusType(models.Model):
VOLUNTEER = "VOLUNTEER"
MANAGER = "MANAGER"
EMPLOYEE = "EMPLOYEE"
STATUS = [
(MANAGER, "Manager"),
(EMPLOYEE, "Employee"),
(VOLUNTEER, "Volunteer"),
]
status_type = models.CharField(
max_length=50,
choices=StatusType.STATUS,
default=StatusType.VOLUNTEER,
verbose_name="Statut")
Then, in your template, add this to toggle the button:
{% if user.status_type == "MANAGER" %}
<form action="{% url 'interviews:advocacy_topic_create' %}" id="topic-create">
<button type="submit">Create</button>
</form>
{% endif %}
You should not create a view depending on each type of user.

django list_filter is not scrollable

I have a long list of elements (50 elements) and I wanted to use that as a list_filter in django admin panel. But when I use this list, on very right side where FILTER panel appears I can see only 20 items and it is not scrollable so rest of 30 is hidden. How can I get those 30 items in FILTER section or How scrolling will be possible so that all 50 items can be viewed.
You can create a custom filter for your field and use a dropdown as selector.
I strongly recommend using https://github.com/mrts/django-admin-list-filter-dropdown which already provide a couple of filters.
If you want to create your own:
admin.py
from django.contrib.admin.filters import RelatedOnlyFieldListFilter
class RelatedOnlyDropdownFilter(RelatedOnlyFieldListFilter):
template = 'filters/related_filter.html'
#admin.register(ModelName)
class YourModelAdmin(admin.ModelAdmin):
list_filter = (
('field', RelatedOnlyDropdownFilter),
)
related_filter.html
{% load i18n %}
<script type="text/javascript">var filter_by_select = function(opt) { window.location = window.location.pathname + opt };</script>
<h3>{% blocktrans with title as filter_title %} By {{ filter_title }} {% endblocktrans %}</h3>
<ul class="admin-filter-{{ title|cut:' ' }}">
{% if choices|slice:"4:" %}
<li>
<select class="form-control"
onchange="filter_by_select(this.options[this.selectedIndex].value)">
{% for choice in choices %}
<option{% if choice.selected %} selected="selected"{% endif %}
value="{{ choice.query_string|iriencode }}">{{ choice.display }}</option>
{% endfor %}
</select>
</li>
{% else %}
{% for choice in choices %}
<li{% if choice.selected %} class="selected"{% endif %}>
{{ choice.display }}</li>
{% endfor %}
{% endif %}
</ul>
I suggest you to use this cool third-party.
django-admin-autocomplete-filter
It's easy to use and user-friendly in case of your problem.
For example look at this. models.py
from django.db import models
class Artist(models.Model):
name = models.CharField(max_length=128)
class Album(models.Model):
name = models.CharField(max_length=64)
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
cover = models.CharField(max_length=256, null=True, default=None)
admin.py
from django.contrib import admin
from admin_auto_filters.filters import AutocompleteFilter
class ArtistFilter(AutocompleteFilter):
title = 'Artist' # display title
field_name = 'artist' # name of the foreign key field
class ArtistAdmin(admin.ModelAdmin):
search_fields = ['name'] # this is required for django's autocomplete functionality
# ...
class AlbumAdmin(admin.ModelAdmin):
list_filter = [ArtistFilter]
"""
defining this class is required for AutocompleteFilter
it's a bug and I am working on it.
"""
class Media:
pass
# ...

MultiValueDictKeyError at /new_search/realme-xt-pearl-blue-64-gb/p/i/realme-xt

I want to capture the url parameters to views.How can I do it?
views.py
def new_search(request,linkadd,text):
serch = request.GET['linkadd']
link = request.GET['text']
html
{% for post in product_names %}
<a id="link" href="{% url 'new_search' linkadd=post.1 text=post.0 %}" value="{{ post.0 }}">{{ post.0 }}</p>
{% endfor %}
urls.py
urlpatterns = [
url(r'^new_search(?P<linkadd>)/(?P<text>)',views.new_search,name='new_search'),
]
I want to get link and text from the url "120.0.0.0:8000/1232-23232-32-2323sdsjdhjas/redmi"
assume :1232-23232-32-2323sdsjdhjas as link and redmi as text
but I get the error like this please suggest me how to do it
MultiValueDictKeyError at /new_search/realme-xt-pearl-blue-64-gb/p/itm731360fdbd273?pid=MOBFJYBE9FHXFEFJ&lid=LSTMOBFJYBE9FHXFEFJNVQVIV&marketplace=FLIPKART&srno=s_1_1&otracker=search&fm=organic&iid=a64429b9-99a5-405b-8edb-9d94934fb991.MOBFJYBE9FHXFEFJ.SEARCH&ssid=iprr3ut7io0000001598430215812&qH=23f6a0071022557e/Realme XT (Pearl Blue, 64 GB)
Please help me..Thanks in advance!!
I suggest doing something like this:
views.py
def new_search(request,linkadd,text):
linkadd = request.GET['linkadd'] # another choice is linkadd = request.GET.getlist('linkadd')
text = request.GET['text'] # another choice is text = request.GET.getlist('text')
context ={
'linkadd':linkadd,
'text':text
}
return render(request,"my_template.html", context)
my_template.html
<a id="link" href="{% url 'my_app:new_search' linkadd=linkadd text=text %}" value="{{linkadd}}">{{text}}</a>
Here we consider app_name is my_app. Please try this.

If statement in method in forms.py not processing

I'm having some trouble getting this validation to work. I want the form to only submit if there's a valid .yaml, .yml, or .json at the end of the URL I'm submitting.
forms.py:
class TemplateForm(FlaskForm):
template_url = URLField( 'Template URL', validators=[InputRequired(), URL(message='error')])
submit = SubmitField('Add Template')
def validate_filetype(self, field):
form = TemplateForm
template_path = form.template_url
ext = os.path.splitext(template_path)[1]
if ext not in ('.json', '.yml', '.yaml'):
raise ValidationError('Invalid File Type')
views.py:
#apps.route('/new-template', methods=['GET', 'POST'])
#login_required
#admin_required
def new_template():
"""Add a new app."""
form = TemplateForm()
if form.validate_on_submit():
template_location = form.template_url.data
flash("added template: " + template_location)
template_path = urlparse(template_location).path
ext = os.path.splitext(template_path)[1]
flash("Extension = " + ext )
if ext == '.json':
flash('var = .json')
template_filename = wget.download(template_location, out='app/storage/templates/json')
flash(template_filename)
elif ext in ('.yml', '.yaml'):
flash('var = .yaml')
return redirect(url_for('apps.index'))
return render_template('apps/new_template.html', form=form)
new_index.html:
{% extends 'layouts/base.html' %}
{% import 'macros/form_macros.html' as f %}
{% import 'macros/check_password.html' as check %}
{% block scripts %}
{% endblock %}
{% block content %}
<div class="ui stackable centered grid container">
<div class="twelve wide column">
<a class="ui basic compact button" href="{{ url_for('apps.index') }}">
<i class="caret left icon"></i>
Back to dashboard
</a>
<h2 class="ui header">
New App Template
<div class="sub header">Add a new app template</div>
{% set flashes = {
'error': get_flashed_messages(category_filter=['form-error']),
'warning': get_flashed_messages(category_filter=['form-check-email']),
'info': get_flashed_messages(category_filter=['form-info']),
'success': get_flashed_messages(category_filter=['form-success'])
} %}
{{ f.begin_form(form, flashes) }}
{{ f.render_form_field(form.template_url, extra_classes=novalidate) }}
{{ f.render_form_field(form.submit) }}
{{ f.end_form() }}
</h2>
</div>
</div>
{% endblock %}
No matter what I do I can't get the raise ValidationError('Invalid File Type') to work. I'm trying to just use https://test.com and it won't throw the validation error.
Please let me know if there's anything else I should attach to provide more information. Everything is importing correctly so I'm pretty sure it's not a dependency issue.
This is the boiler plate I'm using: https://github.com/hack4impact/flask-base
This resolved it. Thank you #ngShravil.py I needed to use a custom validator and separate it into it's own method (outside of the class).
def validate_filetype(form, field):
template_path = field.data
ext = os.path.splitext(template_path)[1]
if ext not in ('.json', '.yml', '.yaml'):
raise ValidationError('Invalid File Type')
class TemplateForm(FlaskForm):
template_url = URLField( 'Template URL', validators=[InputRequired(), URL(message='error'), validate_filetype])
submit = SubmitField('Add Template')

why the flash message is not appear

When i log in the flash message is not diplayed.
How can i fix it?
#app.route('/Login', methods=['GET','POST'])
def show_login():
if request.method == 'POST':
resp = make_response('your email is ' + request.form['email'])
resp.set_cookie('email_user', request.form['email'])
session['username'] = request.form['email']
flash("login is success", "success")
return redirect(url_for('show_profile', username= session['username']))
if 'username' in session:
username = session['username']
return redirect(url_for('show_profile', username=username))
return render_template('inihtml.html')
Can't see your template file? Have you added below code in your template file? flash is just saving the message in session (behind the scene) and you can access that by function get_flashed_messages(). As you are using category as well (Success in your case), so you have to give with_categories = true.
Below code should work for you if you haven't got already in your .html file.
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<ul class=flashes>
{% for category, message in messages %}
<li class="{{ category }}">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}

Resources