I have a search box at the top of my sidemenu. This search bar searches across all views (tasks, lists, and information). The results are shown across these three categories, but lists and information are collapsed by default to make the view easier to read.
Instead, I would like to determine which side menu the user used to search, and collapse the other two categories when returning the results.
So if the user was looking at tasks, the search results would list the tasks, but return lists and information results collapsed. If the user used the search box in lists, the results would list the list items, but collapse tasks and information.
The same function is used to handle all of the search results:
def search(request):
query_string = ''
search_results = SortedDict([])
if ('q' in request.GET) and request.GET['q'].strip():
query_string = request.GET['q']
entry_query = get_query(query_string, ['name', 'notes',])
getquery() searches the database for the query_string
This function is called from the template:
<form method="get" action="{% url search %}" style="display:inline;" >
<input name="q" class="span9" value="{{ request.GET.q }}" id="appendedInputButton" size="16" type="text">
<button class="btn" type="submit">
<i class="icon-search" title="Search"></i>
</button>
</form>
How might I pass either the current url or some other template variable along with this form submission so that I have some template info available in the search function? This would then allow me to pass information to the search results that would tell the template which categories to collapse.
The easiest and most foolproof way is to use separate buttons. If you give each a name and only the appropriate one is shown when a particular view is active, you can tell which view was active from the existence of the button's name in the POST.
The only other route would be to create a hidden field, and set the value of the field appropriately, with JavaScript, when the view changes.
Related
I would like to prefill a form with URL parameters, but I am unsure as to how I should configure my URLs. I need to fill multiple fields, so is using URL parameters still the best method? In the tutorials I have been reviewing, most cases only use 1 or 2 parameters from the GET request. In my view, I am only handling one field currently as I am having trouble with just one parameter. You can see in the form model the other fields I would like to fill. Any help is greatly appreciated!
views.py
def new_opportunity_confirm(request):
form_class = OpportunityForm
account_manager = request.GET.get('account_manager')
form = form_class(initial={'account_manager': account_manager})
return render(request, 'website/new_opportunity_confirm.html', {'form': form})
urls.py
re_path(r'new_opportunity/new_opportunity_confirm/(?P<account_manager>\w+)/$', view=views.new_opportunity_confirm,
name='new_opportunity_confirm'),
new_opportunity_confirm.html
<form action="" method="post" name="newOpportunityForm" id="newOpportunityForm">
{% csrf_token %}
<div class="field">
<label class="label">Account Manager:</label>
<div class="select">
<select name="account_manager" id="account_manager" required>
<option value="{{ form }}">{{ form }}</option>
</select>
</div>
</div>
It depend if you want your parameters to be part of the url or not, and in your case I would suggest not, but let's see both method.
For GET parameters (url?var1=poney&var2=unicorn):
You do not need to configure your url. Django will do the work for you, you just have to configure what is before the interrogation point.
You can then access those with request.GET.get("var1"), or request.GET.get("var1", "default") if you want a default value in case it's not found.
In your template, you can access it with {{ request.GET.var1 }}.
For parameters in the url (url/poney/unicorn):
You need to configure the url to capture the part you want, and you need to have a parameter in the receiving view to get the one in the URL:
def new_opportunity_confirm(request, account_manager):
You can then access it like any other variable, and send it to your template if you want to have access to it there.
Again, that second way does not seem fitting to what you want to achieve.
You were halfway there, you just mixed a little bit of both methods.
I'm using Django for a page in which the user can search for images and add them to a list.
On the top, there is a dropdown with all available lists, and in the pages "body" there is a search form where the user can search for images by tag.
<form action="{% url 'qwe:search' %}" method="get">
{% csrf_token %}
<input type="text" name="q" placeholder="Search..." {% if query_string %} value="{{query_string}}" {% endif %}>
<input type="submit" value="Search">
</form>
On submit, the user gets the same page with a list of search results.
def search(request):
query_string = request.GET["q"]
if (query_string == None):
return HttpResponseBadRequest()
search_results_list = img_search(query_string, max_results=25)
list_list = helpers.get_lists()
context = {"search_results_list" : search_results_list, "query_string" : request.GET["q"], "lists " : list_list }
return render(request, 'qwe/index.html', context)
I want the user to be able to create other lists, so I added a button next to the dropdown. When the user clicks on it, it opens a dialog (div) with a form containing an input for the new lists name.
The Problem:
What is the best way, to submit the form for creating a new list, without losing the search results?
I do this mainly for learning purposes, so every hint is welcome.
Thank you.
The most obvious way that I can think of is to create an <input type="hidden" \> as part of your form, whose value is the query_string. This would allow the server to know, when it receives the form details, what the original search query was.
In fact, assuming search_results_list is serializable (I would guess it is, but your code gives no idea as to what is in it), you could serialize it and send that string as a hidden input - that way you are transmitting the actual search results, rather than just the query that led to them.
I'm trying to add one more action to flask-admin forms.
It has to increment rating (+1) and it works with batch action, but not with single. Please help me find the bug, I've spent a lot of time trying to make this thing work properly.
Here's the code:
I made an html template in templates folder - custom_lists.html
{% extends 'admin/model/list.html' %}
{% block list_row_actions %}
{{ super() }}
<form class="icon" method="POST" action="/admin/user/action/">
<input id="action" name="action" value="approve" type="hidden">
<input name="rowid" value="{{ get_pk_value(row) }}" type="hidden">
<button onclick="return confirm('Are you sure you want to approve selected items?');" title="Approve">
<span class="fa fa-ok glyphicon glyphicon-ok"></span>
</button>
</form>
{% endblock %}
this succeeded with an icon on the list, but if i click to it - it says
Not Found
The requested URL was not found on the server. If you entered the URL
manually please check your spelling and try again.
added to templates folder and added to AdidasView class this:
list_template = 'custom_list.html'
#action('approve', 'Approve', 'Are you sure you want to approve selected items?')
def action_approve(self, ids):
try:
query = Adidas.query.filter(Adidas.id.in_(ids))
count = 0
for image in query.all():
image.rating += 1
count += 1
db.session.commit()
flash(ngettext('Item was successfully approved.',
'%s items were successfully approved.'%count,count))
except Exception as ex:
if not self.handle_view_exception(ex):
raise
flash(gettext('Failed to approve items. %(error)s', error=str(ex)), 'error')
I have not changed the template but I have done it differently as following by setting the column_extra_row_actions variable and defining the action_play function
column_extra_row_actions = [
EndpointLinkRowAction('glyphicon glyphicon-play', 'event.action_play')
]
#expose('/action/play', methods=('GET',))
def action_play(self, *args, **kwargs):
return self.handle_action()
This solution does not seem to apply to this example, but I also struggled with a case where I received a 404 when I using an action on one item via the button, while the batch action worked as expected.
After taking a look at the JS for the batch action I realized that the two HTML forms for individual actions and batch actions are practically identical. The only difference is that when using batch actions there may be more input fields in the form. That implies that if you get a 404 on one, but not the other, there must be an error in your HTML.
In my case I was not aware that Flask-Admin addresses models_with_underscores_in_their_name as modelswithunderscoresintheirname. Therefore instead of
<form class="icon" method="POST" action="/admin/mymodel/action/">
my erroneous code was
<form class="icon" method="POST" action="/admin/my_model/action/">
Note the difference in the action field.
With this change I was able to use the #action API as explained in the Flask-Admin docs.
Hi I have a django application, and I was wondering if there was a better way to display my URLS after submitting a GET request.
urlpatterns = [
...
re_path(r'^reporting/$', ReportView.as_view(), name='report'),
]
When I got to localhost:8000/reporting which displays a form, and click on a radio button and submit, it takes me to:
http://localhost:8000/reporting/?run=2&submit=Search+for+run
I would prefer it if it was something like:
http://localhost:8000/reporting/run=2/
because this page displays another form, which I would like to 'add on' to this:
http://localhost:8000/reporting/run=2/choice=primary/
Is this possible - would I have to have several different URLS relating to different views?
Rather than trying to mangle URLs like that (and I'd challenge the assertion that your way is "cleaner"), you could preserve the existing parameters by outputting hidden fields within the form which would then be sent along with the visible ones:
<form method="GET">
{% for key, value in request.GET.items %}
<input type="hidden" name="{{ key }}" value="{{ value }}">
{% endfor %}
.. rest of form ..
</form>
#Daniel's answer is correct.
But the answer of your question
Is this possible - would I have to have several different URLS relating to different views?
is also YES.
Your ReportView is kind of ListView. I guess it shows all list from Report.
Then you can make DetailView from Report - which shows one report object per page.
It should be like
http://localhost:8000/reporting/2/
And instead of 2, you can add anything you want (Report's title, slug is find) - but it should be UNIQUE so I recommend pk(id) or slug.
For make DetailView, you have to make view (like ReportDetailView), add urls, and make templates for view.
You should check django detailview docs for more information.
I am developing a question-and-answer web application with Flask and Flask-WTForms. Questions can have 1 to 5 tags, and I made a tag editor for users to input their tags:
I've written JavaScript code to serialize the tags into an array. So, in the image above that array looks like this: ["tag1","tag2"], and when tag3 gets added, it looks like this: ["tag1","tag2","tag3"].
I need a way to get that list of tag names to my Flask view function, but I can't figure out how to do that. Any help would be greatly appreciated.
The form:
class AskQuestionForm(Form):
title = StringField('Title', validators=[Required(), Length(min=15, max=200)])
content = TextAreaField('Content', validators=[Required(), Length(min=50, max=30000)])
submit = SubmitField('Submit')
The view function:
#main.route('/ask/', methods=['GET', 'POST'])
def ask_question():
form = AskQuestionForm()
if form.validate_on_submit():
# Code to add a new question
else:
return render_template('ask.html', form=form)
The template (simplified):
<form id="ask-question-form" method="post" action="{{ url_for('main.ask_question') }}">
{{ form.csrf_token }}
<label for="title">Title</label>
<input type="text" name="title" id="title">
<label for="content">Content</label>
<textarea name="content" id="content"></textarea>
<label for="tags">Tags</label>
<input type="text" name="tags" id="add-tag-input">
<span>
<button id="add-tag-button" type="button">Add</button>
</span>
<button type="submit">Submit question</button>
</form>
How can I get the list of tags to my Flask view function? Any help would be appreciated.
Use the TagListField which is used an example of creating custom fields in the wtforms documentation. It will take care of what you are trying to do here. I have slightly modified it because in the original example they are using a comma separated string of tags:
class TagListField(Field):
widget = TextInput()
def _value(self):
if self.data:
return u', '.join(self.data)
else:
return u''
def process_formdata(self, valuelist):
if valuelist:
self.data = [x.strip() for x in valuelist[0].split(' ')]
else:
self.data = []
Burhan's answer was part of my solution, but here is what I had to do:
I added a hidden field to my form and left the tag input without a name so it wouldn't get submitted.
Using JavaScript, I intercepted the form submit and put a comma-separated list of tag names into the hidden field.
I created a TagListField with a process_formdata(self, valuelist) function similar to what was shown above.
In my Flask view function, I retrieved the value of the hidden field and proceeded to use it in making the new question.
If any future readers have any questions about what I did specifically, post a comment.