I'm having some difficulty figuring out the following problem. I apologize if this writeup is slightly confusing, but I'll try to explain it as best as I can.
I'm relatively new to rails, and I'm trying to implement a query on my site. One portion of my site allows users to select a State from a dropdown menu when filling out a form.
Another portion of the site, (the portion that implements the query) allows users to query for a form based on the State associated with it. The page is essentially only 4 dropdown boxes, and a submit button. This query should allow users to find forms from multiple States by selecting the desired States from the available dropdown menus. Meaning a user can query for forms from 4 different states, and it would return all forms where the state on the form matches the state from one of the four dropdown menus.
So, a user can select "Georgia" from state_1 (name of dropdown), "Texas" from state_2, "California" from state_3, and "Ohio" from state_4. Once a user submits their search, I would like to return all the forms available that match the user's dropdown selections.
I'm running into some issues at present. here is the code I currently have:
def self.search(params)
form = self.scoped
form = form.where(:state => params[:state_1]) if params[:state_1].present?
form = form.where(:state => params[:state_2]) if params[:state_2].present?
form = form.where(:state => params[:state_3]) if params[:state_3].present?
form = form.where(:state => params[:state_4]) if params[:state_4].present?
form
end
The issue i am running into is the following: If I run a query with only a selection on state_1, then it returns all of the fields associated with that state (which is excellent); however, if I try to run a query with selections on multiple dropdown menus (for example, "Georgia" on state_1 and "Texas" on state_2) no forms are returned.
Again, I sincerely apologize if this is confusing, and I'm grateful for your time. I would appreciate any help and I'll do my best to respond to any questions as prompt as possible. Thank you so much!
If you have both :state_1 and :state_2 set, then you'll be doing this:
form = form.where(:state => params[:state_1]).where(state => params[:state_2])
And that's saying
state = 'TX' AND state = 'GA'
Each time you call .where, you're appending another condition with a conjunction (i.e. AND). I think you're after this:
states = [:state_1, :state_2, :state_3, :state_4].map { |k| params[k] }.reject(&:blank?)
form = form.where(:state => states) if(!states.empty?)
That will turn into SQL sort of like this:
state IN ('TX', 'GA')
and that seems to be what you're after. The map will extract the param values with for the specified state keys and then the reject will filter out the blank ones (i.e. false, nil, empty, or all whitespace).
Related
I have a list in sharepoint online.
And in this list, i have a person field.
When i call the API endpoint to get all the items in the list, i get an LookupId value for the person field.
I tried to get the user by using the value of the lookupid, but it don't work because the id is not recognized.
The lookupid is a int (eg: 21) instead of a guid.
Is there something missing in the configuration of the person field or in my calls to Microsoft Graph API ?
When a user signs into a SharePoint site collection for the first time, a ListItem is created in a hidden User Information List. The LookupId in a PersonOrGroup field refers to the ListItem in this list. The URL for the User Information List for SharePoint Online should be:
https://{yourTenant}.sharepoint.com/{yourSiteCollection}/_catalogs/users/detail.aspx
Since the User Information List is a generic SharePoint list, you can query the list via Graph. First, get the list id for the User Information List. An easy way to get the list id is to view the source for the User Information Site via Chrome and search for 'listId'. You should find a result like this:
"listId":"{yourListIdIsHere}"
Copy the id. By using the copied id, the id of your root site and the LookupId, you can get the ListItem in the User Information List:
https://graph.microsoft.com/v1.0/sites/{siteId}/lists/{pasteCopiedListId}/items/{lookUpId}?$expand=Fields
The ListItem contains information about the user, such as the email, which can be used to identify the Azure user:
https://graph.microsoft.com/v1.0/users/{eMail}
Question: How could i get the hidden User Information List from Microsoft Graph?
If you do not want to use the 'trick' with Google Chrome to get the id, there is another way to get the site. Typically, if you want to get the id for any site, you would call:
https://graph.microsoft.com/v1.0/sites/{siteId}/lists
However, you will not find the id of the User Information List, even if you include hidden sites. I do not know why. An additional problem seems to be, that you cannot filter lists by their name:
https://graph.microsoft.com/v1.0/sites/{siteId}/lists?$filter=name eq 'users'
The query returns an error, that the provided filter statement is not supported. The only way to get the list without knowing the id seems to by using the property displayName of the list. However, the displayName is based on your localization. So, since I am from Germany, I can get the site by using the query:
https://graph.microsoft.com/v1.0/sites/{siteId}/lists?$filter=displayName eq 'Benutzerinformationsliste'
You will need to replace Benutzerinformationsliste with your localized name. For EN replace it with 'User Information List'.
This returns the expected result:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('xxx')/lists(id,name,displayName)",
"value": [
{
"#odata.etag": "\"xxx\"",
"id": "xxx",
"name": "users",
"displayName": "Benutzerinformationsliste"
}
]
}
As you can see, the name of the list is 'users', so why the first filter statement does not work is a little mystery to me. Maybe someone here knows and can help out.
Some of the queries above don't work at the moment.
What I finally found as a good solution - after trying many many queries - is that you can do this by following the few steps below:
1- Get the GUID of the user information list.
Using the title of the list "User Information List" or the name "users" in the parameter "$filter" does not work.
Don't forget 'system' among the properties you select if you want to retrieve the hidden system-lists.
GET https://graph.microsoft.com/v1.0/sites('{site_id}')/lists?select=id,name,system
2- Filter the previous result in order to pick up the ID of the targeted list named 'users'.
By the way, applying this restriction "$filter=name eq 'users'" does not work.
You will get an exception. So you must do the filtering part by writing a few lines of code.
3- Once you've got the list identifier, then select all the items you want. And voilĂ ! The word 'Fields' must be in pascal case (uppercase the first letter ).
GET https://graph.microsoft.com/v1.0/sites('{site_id}')/lists('users_list_id')/items?$select=Fields&$expand=Fields
As #QuestionsPS1991 mentioned, the people field in fact refers to the hidden user list. With the lookupid, we can get the user via below methods:
Get user by id
Get user property by expanding lookup field
//////////// updated
By default, MS Graph does not return this user list. You may hard code the list id or follow ##QuestionsPS1991 suggestion. Below is my test:
I need to search for a text within a particular workspace. I need all items and fields, except comments.
I'm using php-wrapper for Podio API and Search in space function:
$attributes = array(
"query" => $query,
"ref_type" => "item", // I need just items, not tasks, statuses etc.
"search_fields" => "title"
);
$items = PodioSearchResult::space( $space_id, $attributes );
If search_fields parameter will be removed, it will search not only in titles, but in all fields. However, it will also search in comments left for each item and return that items as a result. But I need just results based on fileds values.
Of course, it is possible to list all the fields needed in search_fields. But there is a dozen of apps with a dozen of different fields each in that space. Moreover, fields could be added, edited or removed by workspace users. So it looks like a very rough and hard-coded solutiuon to list all the fields.
Is there another way to avoid comments in search results?
Podio doesn't have specific method to avoid only comments. But instead of hardcoding all the fields, you can query dynamically "Get app values" call and use the result in "search_fields".
I want to hide the search user interface, but when I do so, the api based row selection fails. Works fine if searching is enabled. When I read the docs, I thought I was disabling the UI, but it is obviously the search feature instead.
I actually have DataTables for schools and school districts, and want to only display the schools from a specific district when used clicks on district table to select a district. User can also select a school from the school table
// DataTable Initialization for school table
dTable = $tblSchools.DataTable({
select: {
style: 'single',
items: 'row',
},
paging: false,
searching: true, // selecting rows only works when enabled - makes sense
info: false,
destroy: true
});
// snippet from event handler on 'select' event of district table
var dTable = $tblSchools.DataTable();
var district = '123'; // real code messier, console.log(district) shows it works
// district number is always column 1
// the next line is what fails (silently, no exception)
dTable.column(1).search(district, false, false).draw();
Environment, jQuery 1.9.1, DataTables 1.10.12, select plugin 1.2.0
Is there some setting I have overlooked to hide the search UI without disabling the search function entirely.
If I have to do this a different way, would appreciated being pointed to a simple equivalent way that allows me to hide the DataTables search UI, but show schools based on district.
Is there some setting I have overlooked to hide the search UI without
disabling the search function entirely
Yes. Remove the f flag from the dom defaults :
dTable = $tblSchools.DataTable({
dom: 'lrtip',
...
})
Now the filter input / "search UI" is removed but you can still perform searches by code.
Whats the best way of performing the save because at the moment. When it comes to editing, I'm not getting the saved responses to populate the form. Other fields such as drop downs are fine. Is there somehthing I should do in the view to make this work? Here is my view:
def populateaboutme(request):
extractlinkedindata(request)
if request.method == "POST":
form = AboutMeForm(request.POST)
if form.is_valid():
today = datetime.date.today()
currentYYMMDD = today.strftime('%Y-%m-%d')
model_instance = form.save(commit=False)
model_instance.save()
request.session["AboutMe_id"] = model_instance.pk
StoreImage(settings.STATIC_ROOT, str(request.session["fotoloc"]), '.jpg', str(request.session["AboutMe_id"]))
return redirect('/dashboard/')
else:
myid = request.session["AboutMe_id"]
if not myid:
form = AboutMeForm()
else:
aboutme = AboutMe.objects.get(pk=int(myid))
form = AboutMeForm(instance=aboutme)
return render(request, "aboutme.html", {'form': form})
Here are the models:
class AboutMe(models.Model):
MyRelationshipIntent = models.CharField(max_length=50)
and the forms:
class AboutMeForm(ModelForm):
class Meta:
model = AboutMe
exclude = ()
MyRelationshipIntent = forms.MultipleChoiceField(choices=RELATIONSHIPINTENT_CHOICES,widget=forms.CheckboxSelectMultiple())
RELATIONSHIPINTENT_CHOICES = (
('JL', 'Just Looking'),
('FL', 'Looking for friendship'),
('FN', 'Looking for fun'),
('FL', 'Looking for a relationship'),
)
You want to use the initial option on the form:
form = AboutMeForm(initial={'name': aboutme.name})
The instance= you are using is what you need to use when saving to tell django this isn't a new object:
if request.method == 'POST':
form = AboutMeForm(request.POST, instance=aboutme)
Now using instance can give the initial values as well, but only when using a modelform, and you still need it for the saving part.
Edit
It took me a while to notice it because I was focusing on the form, but the problem you are having stems, essentially, from the fact that you are using a CharField where you should be using a ManyToManyField. I mean - how would four checked boxes be translated into one CharField and vice-versa? Django can't just guess it. It makes no sense.
You can use a CharField if you somehow add a method to translate it to the checkboxes. But it's also a wrong approach so don't. Instead, I'll give you two solutions, and you'll choose the one you see fit.
The most natural thing to do would be to use a ManyToMany field here, and then tell the django form to use the checkbox field for it (the default would be a multiselect, and if you want you can use a client side plugin to make that look nice as well). Your models would look something like this:
class Intent(models.Model):
relationship = models.CharField(max_length=50)
class AboutMe(models.Model):
intents = models.ManyToManyField(Intent)
Then you just create four Intent instances for each of the values in your RELATIONSHIPINTENT_CHOICES:
rels = ('Just Looking',
'Looking for friendship',
'Looking for fun',
'Looking for a relationship')
for i in rels:
new = Intent(relationship=i)
new.save()
This is especially good if you think that you might want to add more options later on (and you can create a model on the admin site to ease that proccess instead of the script I wrote up there). If you don't like that solution and you're sure your options would remain the same, another good solution that might suit you is creating a boolean field for each option. Like this:
class AboutMe(models.Model)
jl = models.BooleanField(verbose_name='Just Looking')
fl = models.BooleanField(verbose_name='Looking for friendship')
fn = models.BooleanField(verbose_name='Looking for fun')
fl = models.BooleanField(verbose_name='Looking for a relationship')
Then you don't even need the widget, because checkbox is the default for boolean fields. After doing this, using form(instance=aboutme) and form(initial={'jl': aboutme.jl}) would both work. I know those might look a little scary and more complex than your simple CharField, but this is the right way to go.
p.s.
Other python tips to keep in mind:
Don't name your class "AboutMe". That should be the view, not the model. It makes more sense (to me at least) to make it an extension of the built-in User, name it User or give it a similar fitting name (Profile or Account or the sort)
Field names should not look like class names (check out PEP8 for more conventions). So it should be my_relationship_intent. However, that's also a long and wearying name. relationship_intent or simply intents is a lot better.
I am using "MvcContrib.Mvc4" to show my grid on a page in my project.
I need to have a grid with some columns which are from filtered data (From Source table), and have 3 in-line editable column, like StartDate, EndDate, Notes and need to insert them into new table(The Destination Table)
I can use the Html.EditorFor(c=>c.StartDate) in my columns, and edit them on the grid, but I don't know how to track the changes and save their updates into data base!
Also I have the column of "Notes" which is not in the model, but I need to insert it into new table with the other changed data (To the destination table)
After I edited data, in the source of page, the value is not changed.
I need to give the user the ability of editing (these three columns) on many rows and after submitting the "Save" button, Save bulk changes from grid into another new table!
I am thinking of a way to get changes and send them all to server by client side code like Jquery or Ajax, But I could not find any good example of this on internet.
I know how to check boxes on the grid and get the selected ids form the page, but I don't know how to get changed Text fields and Dates from grid.
I appreciate any help or sample code!
Here are some codes
#Html.Grid(Model.Enrolments).WithModel(new EnrolmentGrid()).Columns(column =>
{
column.For(i => Html.EditorFor(x => i.EndDate)).Named("End Date");
column.For(i => Html.EditorFor(x => i.StartDate)).Named("Start Date");
column.For(i => Html.Editor("Notes", new { /*Not sure if this is correct*/ value = i.EnrolmentId, #class = "Notes" })).Named("Notes");
}).Attributes(#class => "full-grid-style")}