Filter to show "null" relations (where no results related to the item) - django-admin

Quite simply, django filter (standard) give you the option to see "All". I want to create an option to show items which contain "None"
The query would be something like this:
tags = Product.objects.exclude(tag__isnull=True)
My models.py
class Tag(models.Model):
name = models.CharField(max_length=100, blank=False)
def __unicode__(self):
return self.name
class Product(models.Model):
name = models.CharField ("Name", max_length=400)
tag = models.ManyToManyField(Tag, blank=True)
def __unicode__(self):
return self.name
How would I achieve this? I tried a SimpleListFilter, however this just listed all the items in a filter. I want the items to show up in the admin page view. Can an Admin action do this?

You can exclude all which has no tag as :
tags = Product.objects.all().exclude(tag=None)

I've just figured it out- Django does this automatically using "list_filter". But it only works if you use the tag (self name as defined in models.py), and not the way I had it as below.
All I had to do was change
list_filter: ('tag__name')
to
list_filter: ('tag')
That is the stock method of showing Django filters. It allows me to see All & (none)

Related

Change table name/model name dynamically in ruby on rails

I have two tables that have the exact same columns. I wish to change the model name on the fly and pull out data from the one that the user has picked. How do achieve this? I have code as such :-
def display
#active_model = get_active_model(params[:active_model])
versions = #active_model.group(:version).count
end
and get_active_model looks something like this :-
def get_active_model(model_param)
case model_param
when 'Eclipse'
return "Eclipse"
when 'Jdt'
return "Jdt"
end
end
The "#active_model" is the model chosen by the user and can be 'Eclipse' or 'JDT'. When I replace "#active_model" with the model name directly it works. But I want to change it dynamically. I'm fairly new to ROR, so please give me your suggestions!
You can use model name instead of string:
def get_active_model(model_param)
case model_param
when 'Eclipse'
return Eclipse
when 'Jdt'
return JDT
end
end

Using Wikipedia-Client Gem to Update Rails Database

My ruby and Rails is a bit rusty. I have a table in my database called institutes which has some of the columns filled. I want to use the Wikipedia-Client gem to fill some of the others. I want to use the name attribute to find the page on Wikipedia then use page.summary for the description attribute in my table and page.image_urls.first for the picture attribute. At the moment, I'm struggling to work out how I would go about this.
My current code is:
require 'Wikipedia'
Institute.each do |institute|
school = institute.pluck(:name)
page = Wikipedia.find(school)
description = page.summary
picture = page.image_urls.first
Institute.update!(description: description, picture: picture)
end
I'm clearly doing something wrong here to do with the selection and use of the name attribute to find the Wikipedia page, but can't quite work it out. I think even if I were to pluck the name correctly, it wouldn't assign anything to the right id.
If there's also a way to drop the "The" at the beginning of the name in the Wikipedia search if it exists in :name, that would also be helpful as it seems some institutes drop this on Wikipedia.
You can try to use something like this:
#use https://github.com/kenpratt/wikipedia-client
require 'wikipedia'
#select all Institutes through AR model
Institute.all.each do |institute|
#'institute' is an object, so we can get its name by dot operator
school = institute.name
#try to find school as is
#then try to find without 'The'
#and go ahead only if page exists
page = Wikipedia.find(school)
page = Wikipedia.find(school[3..-1].strip) if page.content.nil? and school[0..2].downcase == 'the'
next if page.content.nil?
description = page.summary
picture = page.image_urls.first
#update Institute object
institute.update!(description: description, picture: picture)
end

How to add new Select2 option terms to the server?

In a Rails 4 app I am using Select 2 v4.0 to display a typeahead-style select field. Select2 generates the options from an ajax call to a json API within the app.
This is working great.
I now want to allow users to create a new item if their entry does not already exist in the json.
This is easy to set up on the client side
$('.my-field').select2
tags: true
But what is the best way to handle this on the server?
My original thought was that, if an existing options is selected, the form would return an ID integer, whereas if a new item is selected, a string would be returned. I could then call a setter method in the controllers create method
def create
#object = Object.build(params)
if params[:my_field_id].respond_to?(:to_str)
#object.setter_method = params[:my_field_id]
params[:my_field_id] = nil
end
..
end
But of course even IDs are treated as strings in the params.
Next I thought I could modify the string so that new items can be distinquished. Select2 makes this relatively easy.
$('.my-field').select2
tags: true
createTag: (tag) ->
{
id: '<<<<' + tag.term + '>>>>'
text: tag.term
}
Then in the controller I could do something like
def create
#object = Object.build(params)
regex = my_regex_pattern
if params[:my_field_id].gsub(regex)
term = params[:my_field_id].slice('<<<<').slice('>>>>')
#object.setter_method = term
params[:my_field_id] = nil
end
...
end
So my questions:
Does this seem like a sensible approach, or am I overlooking a
better way?
This approach seems like it could be quite brittle if, for example,
the new item contains '<<<<'. Do I need to worry to about this?
My regex knowledge is poor to none. What is the best source of
information to ensure that my_regex_pattern matches to <<<<a
random string of text>>>>.
Are the slice methods the best way to remove these extra
substrings?
EDIT
After a little playing, it appears that slice might be improved upon as follows:
term = params[:my_field_id].reverse.chomp('<<<<').reverse.chomp('>>>>')
It is a bit unwieldily and not the best readability. Is there a better way?

rails modle base search with check boxes

I am working on search functionality in rails and I want a common search method for all the site. For that I am creating a method in app controller with two parameters one is modleName and another one is fieldsArray. but am not able to make it. Please help me.
I want that I set a variable in model that on which columns I need a search as like (attr_accessible) and then I need a element which I call in view files and it gets all the columns with labels and check boxes which I set in model. and I get a result with the specific column name which I enter in search box and which columns I have selected, columns would be multiple selected.
Please help.
Thanks
Hope this helps:
Create a utility class which has your generic search method.
class Util
# modelName is a string, fields would be an array of strings, keyword is string as well
# You could either call fire search from here or from individual models
def search(modelName, fields, keyword)
query = ""
fields.size.each_with_index do |field, index|
query += "#{field} like #{keyword} "
query += " OR " if index < fields.size
end
modelName.constantize.where(query)
# Or create search method in all ur models which you want to search and
modelName.constantize.search(fields, keyword)
end
end
I haven't included the model search methods as its self explanatory as to what the method should look like.
Let me know if this helps

How Do I pass the list value for paginate to render properly?

I want to display all the project's tasks in a page, given that the user can have many projects. In such a case, a user will select any one project from the drop-down list box and I find that project instance using :
def proj = params.managersProject // this is the choice made by the manager
def project = Project.findByName("$proj")
Now I have all the details in project instance. Now I need to display the tasks of that particular project. Since it have so many tasks, I need to paginate it. But for paginating to work properly, I guess we need to pass the params like this :
Project.list(params) // which will be passed on to the views for rendering.
But in my case, I couldn't able to call that list() method on project instance, that I got earlier. How do I solve this?
Edit:
After got answer from tim_yates, I tried this:
def tasks = Tasks.findAllByProject( project, params )
def size = tasks.size()
params.max = Math.min(params.max ? params.int('max') : 10,100)
return [tasksInstanceList: Tasks.findAllByProject(project,params), tasksInstanceTotal: size]
This returns the result, but when I click on the next button I don't see any table being rendered. After that when I click on prev button, I couldn't see anything. I clearly know that there is some problem with tasksInstanceList, I'm not sure whether the params is passing into it or not. But when I click on prev and next button I can clearly see my browsers add changing from :
http://localhost:8080/app/controller?offset=0&max=10
to:
http://localhost:8080/app/controller?offset=10&max=10
In view file I have this code:
<g:paginate total="${tasksInstanceTotal}"/>
Since I'm very new to grails, I need some help.
Thanks in advance.
Can you use:
def proj = params.managersProject // this is the choice made by the manager
def project = Project.findByName("$proj")
def tasks = Task.findByProject( project, params )
Where the max and offset are in the params map?
I may not be the perfect expert on pagination (I typically trip a bit over it myself) but if its the project's Tasks hasmany property you're trying to paginate through, Project.list() probably isn't what you want.
If your params has a .max and .offset (as in, you're using the < g:paginate > tag and you provided it with a task listing controller action), what I typically do is use a criteriaBuilder with the somewhat-obscured PagedResultList return type. I'm guessing there's a better way to go about it, but something like
def yourProjectInstance = Project.get(params.yourProjectId)
def taskPagedResult = Task.createCriteria().list(max: params.max as Integer, offset: params.offset as Integer) {
eq('project', yourProjectInstance)
//optionally, if you're using sortableColumn here as well, you can do
//order(params.sort, params.order)
}
render view: 'taskPagedTable', model: [taskList: taskPagedResult, taskCount: taskPagedResult.totalCount()]
Should put a list of params.max Tasks in your view's taskList, but still give you the total number of tasks for that project in the taskCount variable.
Hope that helps!
Reference: http://blog.jeffshurts.com/2010/04/grails-pagination-and-criteriabuilder/
EDIT:
My guess is that what's missing here is the action attribute for your paginate tag, especially if hitting the URL precisely is producing the proper results for you.
You need to point your paginate tag at whatever controller action has your code block.
One other thing I can think of looking at your controller code is your size variable might be misleading; it's going to be the same as whatever params.max was. This is where the PagedResultList portion of my answer comes into play. Either that, or you could have size be equal to
def size = Tasks.countByProject(project)
That way your g:paginate tag's total property will be accurate.

Resources