I'm using Firebase and want to get a list of all my users, using pagination parameters. Everywhere I've used pagination, I always passed 2 arguments: perPage and page. Simple and all-powerful. A generic function looked like this:
const list = someTable.getAll().skip(perPage*page).limit(page)
const total = someTable.countAll()
return { list, total }
But in Firebase, the function is like this:
const listResult = getAuth().listUsers(perPage, nextPageToken)
// listResult.pageToken needs to be passed to the next call to see the next page
// note that THERE'S NO PAGE PARAMETER!!! WTF!!!!
return listResult
This sucks, because I can't simply choose a page to get, I can only get the next page!!
This seems like absolutely horrible design and I can't comprehend why anyone would make their list function like this.
In any case, my question is: is there a way to get "page 4, with 20 results per page" using listUsers()? Or do I need to simply abandon pagination in the users table display?
Related
I'm refactoring code in a Django view. I'm working with a view with the below arguments:
def title_views(request, key, group, sort):
group = get_object_or_404(Group, group=group, main_id = key)
default_sort = sort
I know by default each view should have the request argument. But in terms of key, group, sort, where can I expect these items to be passed? Is it through the template that the view is called in? I come here for help because the documentation isn't that clear on this, at least in my experience.
Thanks!
These are URL parameters. Likely the URL that links to this view looks like:
path('<str:key>/<str:group>/<str:sort>/', title_views)
or with a regex, something like:
re_path(r'(?P<key>\w+)/(?P<title>\w+)/(?P<sort>\w+)/')
If you thus visit a page like foo/bar/qux/ it will pattern match on the path, and thus call the function with 'foo' for key, 'bar' for title, and 'qux' for sort.
Usually the URL parameters thus contain data that determine how to filter, order and render the content.
I am experimenting using elasticsearch in a dummy project in django. I am attempting to make a search page using django-elasticsearch-dsl. The user may provide a title, summary and a score to search for. The search should match all the information given by the user, but if the user does not provide any info about something, this should be skipped.
I am running the following code to search for all the values.
client = Elasticsearch()
s = Search().using(client).query("match", title=title_value)\
.query("match", summary=summary_value)\
.filter('range', score={'gt': scorefrom_value, 'lte': scoreto_value})
When I have a value for all the fields then the search works correctly, but if for example I do not provide a value for the summary_value, although I am expecting the search to continue searching for the rest of the values, the result is that it comes up with nothing as a result.
Is there some value that the fields should have by default in case the user does not provide a value? Or how should I approach this?
UPDATE 1
I tried using the following, but it returns every time no matter the input i am giving the same results.
s = Search(using=client)
if title:
s.query("match", title=title)
if summary:
s.query("match", summary=summary)
response = s.execute()
UPDATE 2
I can print using the to_dict().
if it is like the following then s is empty
s = Search(using=client)
s.query("match", title=title)
if it is like this
s = Search(using=client).query("match", title=title)
then it works properly but still if i add s.query("match", summary=summary) it does nothing.
You need to assign back into s:
if title:
s = s.query("match", title=title)
if summary:
s = s.query("match", summary=summary)
I can see in the Search example that django-elasticsearch-dsl lets you apply aggregations after a search so...
How about "staging" your search? I can think if the following:
#first, declare the Search object
s = Search(using=client, index="my-index")
#if parameter1 exists
if parameter1:
s.filter("term", field1= parameter1)
#if parameter2 exists
if parameter2:
s.query("match", field=parameter2)
Do the same for all your parameters (with the needed method for each) so only the ones that exist will appear in your query. At the end just run
response = s.execute()
and everything should work as you want :D
I would recommend you to use the Python ES Client. It lets you manage multiple things related to your cluster: set mappings, health checks, do queries, etc.
In its method .search(), the body parameter is where you send your query as you normally would run it ({"query"...}). Check the Usage example.
Now, for your particular case, you can have a template of your query stored in a variable. You first start with, let's say, an "empty query" only with filter, just like:
query = {
"query":{
"bool":{
"filter":[
]
}
}
}
From here, you now can build your query from the parameters you have.
This is:
#This would look a little messy, but it's useful ;)
#if parameter1 is not None or emtpy
#(change the if statement for your particular case)
if parameter1:
query["query"]["bool"]["filter"].append({"term": {"field1": parameter1}})
Do the same for all your parameters (for strings, use "term", for ranges use "range" as usual) and send the query in the .search()'s body parameter and it should work as you want.
Hope this is helpful! :D
I have to make dashboard like view in flask-admin that will use data retrieved from external API. I have already written a functions that get date ranges and return data from that range. I should use BaseView probably but I don't know how to actually write it to make filters work. This is example function that i have to use: charts = generate_data_for_dashboard('164', '6423FACA-FC71-489D-BF32-3A671AB747E3', '2018-03-01', '2018-09-01'). Those params should be chosen from 3 different dropdowns. So far I know only how to render views with pre coded data like this :
class DashboardView(BaseView):
kwargs = {}
#expose('/', methods=('GET',))
def statistics_charts(self):
user = current_user
company = g.company
offices = Office.query.filter_by(company_id=company.id)
self.kwargs['user'] = user
self.kwargs['company'] = company
charts = generate_data_for_dashboard('164', '6423FACA-FC71-489D-BF32-3A671AB747E3', '2018-03-01', '2018-09-01')
self.kwargs['chart1'] = charts[0]
self.kwargs['chart2'] = charts[1]
return self.render('stats/dashboard.html', **self.kwargs)
But I need some kind of form to filter it. In addition date filter dropdown should have dynamic options : current_week, last_week, current_month, last_month, last_year. Don't know where to start.
You should use WTForms to build a form. You then have to decide if you want the data to be fetched on Submit or without a reload of the page. In the former case, you can just return the fetched information on the response page in your statistics_charts view. But if you want the data to update without a reload, you'll need to use JavaScript to track the form field changes, send the AJAX request to the API, and then interpret the resulting JSON and update your dashboard graphs and tables as needed.
I have not used it, but this tutorial says you can use Dash for substantial parts of this task, while mostly writing in Python. So that could be something to check out. There is also flask_jsondash which might work for you.
Admin actions can act on the selected objects in the list page.
Is it possible to act on all the filtered objects?
For example if the admin search for Product names that start with "T-shirt" which results with 400 products and want to increase the price of all of them by 10%.
If the admin can only modify a single page of result at a time it will take a lot of effort.
Thanks
The custom actions are supposed to be used on a group of selected objects, so I don't think there is a standard way of doing what you want.
But I think I have a hack that might work for you... (meaning: use at your own risk and it is untested)
In your action function the request.GET will contain the q parameter used in the admin search. So if you type "T-Shirt" in the search, you should see request.GET look something like:
<QueryDict: {u'q': [u'T-Shirt']}>
You could completely disregard the querystring parameter that your custom action function receives and build your own queryset based on that request.GET's q parameter. Something like:
def increase_price_10_percent(modeladmin, request, queryset):
if request.GET['q'] is None:
# Add some error handling
queryset=Product.objects.filter(name__contains=request.GET['q'])
# Your code to increase price in 10%
increase_price_10_percent.short_description = "Increases price 10% for all products in the search result"
I would make sure to forbid any requests where q is empty. And where you read name__contains you should be mimicking whatever filter you created for the admin of your product object (so, if the search is only looking at the name field, name__contains might suffice; if it looks at the name and description, you would have a more complex filter here in the action function too).
I would also, maybe, add an intermediate page stating what models will be affected and have the user click on "I really know what I'm doing" confirmation button. Look at the code for django.contrib.admin.actions for an example of how to list what objects are being deleted. It should point you in the right direction.
NOTE: the users would still have to select something in the admin page, otherwise the action function would never get called.
This is a more generic solution, is not fully tested(and its pretty naive), so it might break with strange filters. For me works with date filters, foreign key filters, boolean filters.
def publish(modeladmin,request,queryset):
kwargs = {}
for filter,arg in request.GET.items():
kwargs.update({filter:arg})
queryset = queryset.filter(**kwargs)
queryset.update(published=True)
I want to implement search functionality, So my requirement is I want to search some keyword in body tag in all content page. I do not know how I can search keyword in body tag in Sitecore. Please guide me?
As Anton outlined, the concept of searching the Body tag is wrong for Sitecore. You want to think in terms of Content in fields of Items. Sitecore's ContentSearch is how you can achieve this.
Sitecore comes with default indexes out-of-the-box that you should use for the search. You should rebuild these via the Index Manager in the Content Editor and then base your search on the basic example I've outlined for you below.
public IEnumerable<Item> Search(string searchterm)
{
string indexName = "sitecore_web_index";
using (var index = ContentSearchManager.GetIndex(indexName).CreateSearchContext())
{
var predicate = PredicateBuilder.True<SearchResultItem>();
IQueryable<SearchResultItem> query = index.GetQueryable<SearchResultItem>().Where(i => i.Content.Contains(searchterm)).Filter(predicate);
var searchResults = query.GetResults();
foreach (var hit in searchResults.Hits)
{
yield return hit.Document.GetItem();
}
}
}
jRobbins's answer is sensible (he get's my upvote). However, it is technically possible to index the content of the body tag. I would be cautious with this. I've seen it working well, but I've also seen it completely destroy the performance of a site.
The approach involves the creating a computed field in your index. You populate the computed field by making a web request to your newly published page and scraping the response body tag.
Here's are a couple of module that more or less does that:
https://github.com/efocus-nl/sitecorewebsearch
https://github.com/hermanussen/sitecore-html-crawler
If you can accept something a little less accurate, then you could loop through each of the components on your page and extract content from their datasources. That approach is discussed in this video:
http://www.techphoria414.com/Blog/2012/May/Sitecore_Page_Editor_Unleashed