How to remove the choice field based on relationships between instances in the database in Django - django-forms

I'm new to django and I would like to ask a question about a case that I can't solve if for example I have many categories, in these categories I can have one or more fixed sections eg. section = [a, b, c, d, e] so if I have a module showing these options but I already have section "b" in category "1" how can I remove option "b" from the list so as to have a maximum of one category consisting of 5 non-repeated sections

class SectionForm(forms.ModelForm):
class Meta:
model = Section
fields = ["nome"]
def __init__(self, *args, **kwargs,):
section_pk = kwargs.pop('section_pk', None)
super(CategotyForm, self).__init__(*args, **kwargs)
key = Section.objects.filter(category=section_pk).values_list()
list_key = list(key)
exist_section = []
total_section = ['Section A','Section B','Section C','Section D','Section E']
for i in range(len(list_key)):
exist_section.append(list_key[i][1])
choice = list(set(total_section)- set(exist_section))
for i in range(len(choice)):
choice[i] = choice[i].title()
dict_choice = []
A = 'Section A'
B = 'Section B'
C = 'Section C'
D = 'Section D'
E = 'Section E'
label = ''
for i in range(len(choice)):
if choice[i] == 'Section A':
label = A
if choice[i] == 'Section B':
label = B
if choice[i] == 'Section C':
label = C
if choice[i] == 'Section D':
label = D
if choice[i] == 'Section E':
label = E
dict_choice.append(label)
new_choice = list(zip(dict_choice, choice))
self.fields["name"] = forms.ChoiceField(choices=new_choice)

Related

I want to add functionality in Quicksearch box to search using any data column not just name

I want to quicksearch using any column name(like description, Status) current search is being performed using Name only
class ApplicationList(APIView):
permission_classes = (IsAuthenticated,)
# parser_classes = (JSONParser,)
def post(self, request, format=None):
# Get a list of fields dynamically
fields = list()
for f in Application._meta.fields:
if f.is_relation:
continue
fields.append(f.name)
queryset = Application.objects_with_sprint_name.all()
# Looking for a specific bubble?
if 'bubble' in request.data:
if request.data['bubble'] == '4-1':
queryset = queryset.filter(assessment_phase__id=request.data['bubble']).exclude(attributes__contains={'application_disposition':'Removed'})
else:
queryset = queryset.filter(assessment_phase__id=request.data['bubble'])
# Providing a search query?
if 'search' in request.data:
q_search = request.data['search']
# Build the query
q = get_query(q_search, fields)
queryset = queryset.filter(q)
if 'filter' in request.data:
q = get_filter(request.data['filter'])
if q:
queryset = queryset.filter(q)
page = int(request.data.get('page', 1))
per_page = int(request.data.get('per_page', 25))
# Sorting
sort_by = request.data.get('sort_by', 'name') or 'name'
sort_dir = request.data.get('sort_dir', 'asc') or 'asc'
if sort_dir == 'desc':
sort_dir = '-'
else:
sort_dir = ''
# Is this an actual field or do we need to sort by the attributes__*?
if sort_by not in fields:
sort_by = 'attributes__' + sort_by
queryset = queryset.order_by('{0}{1}'.format(sort_dir, sort_by))
# Do a little data massaging
untreated_data = queryset.values()
data = list()
for app in untreated_data:
this_app = {}
for k, v in app.items():
if k == 'attributes':
continue
if k == 'sprint_name':
this_app[k] = v
this_app['sprint'] = v
continue
this_app[k] = v
this_app.update(app['attributes'])
data.append(this_app)
start = (page-1) * per_page
end = (page) * per_page
response = {
'total_rows': len(data),
'data': data[start:end],
}
return Response(response)
def get_query(query_string, search_fields):
''' Returns a query, that is a combination of Q objects. That combination
aims to search keywords within a model by testing the given search fields.
'''
query = None # Query to search for every search term
terms = normalize_query(query_string)
for term in terms:
or_query = None # Query to search for a given term in each field
for field_name in search_fields:
q = Q(**{"%s__icontains" % field_name: term})
if or_query is None:
or_query = q
else:
or_query = or_query | q
if query is None:
query = or_query
else:
query = query & or_query
return query
def get_filter(filter_dict):
available_fields = [ field.name for field in Application._meta.fields ] \
+ ApplicationManager.annotated_fields
query = None
if filter_dict is None:
return query
for field_name, val in filter_dict.items():
query_field = field_name
# Quicksearch box
if field_name == '_quicksearch_':
q = Q(name__icontains=val)
if query is None:
query = q
else:
query = query & q
continue
# Figure out if this field is part of the model
# or in the attributes json field
if query_field not in available_fields:
query_field = 'attributes__{0}'.format(query_field)
if isinstance(val, list):
q = None
#
# # Are we looking for null or blank?
if '#is_null_or_blank#' in val:
val.remove('#is_null_or_blank#')
q = Q(**{"%s__isnull" % query_field: True}) | \
Q(**{query_field: ''}) | \
Q(**{query_field: []})
#
# # Loop through the list and create some "OR" expressions
for v in val:
tmp = Q(**{"%s__contains" % query_field: v})
if q is None:
q = tmp
q = q | tmp
elif val.startswith('#bool#'):
bval = val[6:].lower() == 'true'
q = Q(**{"%s" % query_field: bval})
else:
q = Q(**{"%s__icontains" % query_field: val})
# # Add to our master query of all fields
if query is None:
query = q
else:
query = query & q
return query
# Quicksearch box
if field_name == 'quicksearch':
q = Q(name__icontains=val) | Q(attributes__icontains=val), I got the field wrong which I corrected and for foreign key relationship django foreignkey contains query helped

I need to alter my code so that it shows highest to lowest

In my code so far I have done it so that the average is shown and the students can be sorted in alphabetical order. However, I need to alter my code so that the results can be stored from highest to lowest but i am struggling with this.
In my text file it looks like this:
name,3,4,5
2name,5,6,7
3name,3,4,5
where each name is different
This is my code so far:
class Student:
def __init__(self, name, marks):
self.name = name
self.marks = marks
def avg_mark(self):
return sum(self.marks)/len(self.marks)
def __str__(self):
return '{0}: {1}, {2}'.format(self.name, self.marks, self.avg_mark())
def load_grades(filename):
fd = open(filename, 'r')
f = {}
for line in fd:
split = line.split(',')
key = split[0]
marks = [int(n) for n in split[1:]]
try:
f[key] += marks
except KeyError:
f[key] = marks
students = []
for key, values in f.items():
students.append(Student(key, values[-3:]))
return students
def sort_by_name(students):
def get_name(student):
return student.name
students = sorted(students, key=get_name)
return students
def sort_by_avg(students):
def get_avg(student):
return student.avg_mark()
students = sorted(students, key=get_avg)
return students
again = True
while again:
class_num = input ('Which class do you want to view 1,2 or 3?')
print('please input a, b or c')
print('a)Alphabeically')
print('b)average')
print('c)highest to lowest')
sort = input ('how would you like to view it:')
if class_num =="1" and sort =="a":
students = load_grades('class1.txt')
students = sort_by_name(students)
elif class_num =="1" and sort =="b":
students = load_grades('class1.txt')
students = sort_by_avg(students)
for student in students:
print(student)
Again=input('Do you want to view another class yes or no?')
again = (Again=='yes')
print('bye')
I want it so that when c is pressed the the numbers are sorted from highest to lowest.
Thanks

Making this function infinitely nesting based off a table

I finally solved my problem to make a dropdown menu in world of warcraft off of a table.
Now I need it to be able to nest as far down as the user supplies. How would I do this?
Here is the function I currently use:
local info = UIDropDownMenu_CreateInfo()
if level == 1 then
for a,b in pairs(menuList) do
info.text = b[1]
info.hasArrow = b[2]
UIDropDownMenu_AddButton(info, level)
end
elseif level == 2 then
for a,b in pairs(menuList[UIDROPDOWNMENU_MENU_VALUE][3]) do
info.text = b
info.func = OnClick
UIDropDownMenu_AddButton(info, level)
end
end
Here is the table example used:
testMenuList = {Greetings = {"Greetings", true, {"hi", "hello", "good day"}}, Farewells = {"Farewells", true, {"bye", "goodbye", "later"}}}
It can setup currently up to 2 levels down. The first and submenus.
Can anyone help me out?
Here is the solution:
function IOLib_CreateDropDown(parent, name, title, width, anchor, posX, posY, menuList, OnClick)
local dropDown = CreateFrame("Button", name, parent, "UIDropDownMenuTemplate")
--_G[name].list = menuList
dropDown.list = menuList
-- dropDown.Func = OnClick
dropDown:ClearAllPoints()
dropDown:SetPoint(anchor, posY, posX)
local function initialize(self, level)
local info = UIDropDownMenu_CreateInfo()
if level ~= nil then
info = UIDropDownMenu_CreateInfo()
info.text = title
info.isTitle = true
UIDropDownMenu_AddButton(info, level)
if level == 1 then
for a,b in pairs(menuList) do
info = UIDropDownMenu_CreateInfo()
info.text = b[1]
info.hasArrow = b[2]
info.func = OnClick
if info.hasArrow then _menuLists[b[1]] = b[3] end
UIDropDownMenu_AddButton(info, level)
end
elseif level > 1 then
--print(#_menuLists[UIDROPDOWNMENU_MENU_VALUE][2])
--for x=1, #_menuLists[UIDROPDOWNMENU_MENU_VALUE] do
for a,b in pairs(_menuLists[UIDROPDOWNMENU_MENU_VALUE]) do
info = UIDropDownMenu_CreateInfo()
info.text = b[1]
info.hasArrow = b[2]
if info.hasArrow then _menuLists[b[1]] = b[3] end
info.func = OnClick
UIDropDownMenu_AddButton(info, level)
end
end
end
end
UIDropDownMenu_Initialize(dropDown, initialize)
UIDropDownMenu_SetWidth(dropDown, width) -- Use in place of dropDown:SetWidth
UIDropDownMenu_SetButtonWidth(dropDown, width + 24)
UIDropDownMenu_SetSelectedID(dropDown, 1)
UIDropDownMenu_JustifyText(dropDown, "LEFT")
return dropDown
end
Here is an example of the table used with this function:
testMenuList = {{"Greetings", true, {{"Hi", true, {{"H", true, {{"Amazing", false, nil}}},{"i", false, nil}}},
{"Hello", false, nil}}},
{"Farewells", true, {{"Bye", false, nil},
{"Goodbye", false, nil}}},
{"Test", false, nil}}

using a string (from gets) directly as a variable name

Starting out my Towers of Hanoi assignment, I have
a = [6,5,4,3,2,1]
b = []
c = []
puts "Type a, b, or c"
from = gets.chomp
# the user types a lower-case a
popped = from.pop
Now this obviously fails because pop is not a string method.
So other than
if from == a
popped = a.pop
elsif from == b
popped = b.pop
, is there a nice ruby shortcut to get the pop I intend?
You can use eval:
a = [6,5,4,3,2,1]
b = []
c = []
puts "Type a, b, or c"
from = gets.chomp
popped = eval(from).pop
But eval is typically seen as a bad idea for security, performance, and debugging reasons.
options = {
:a => [6,5,4,3,2,1]
:b => []
:c => []
}
puts "Type a, b, or c"
from = gets.chomp
popped = options[from.to_sym].pop
I have to strongly advise you avoid the use of the method using eval above, as it allows the user to input arbitrary code. Use a hash instead to store all your options.

dropdown select box with "filter as you type" in shoes

Question: Does anyone have an example of a "filter as you type" dropdown control using Shoes?
Examples: If you are looking for examples of what i am talking about, see these.
http://docs.jquery.com/Plugins/Autocomplete
Jquery: Filter dropdown list as you type
I've never seen one in the wild. Here's the code for one I started working on a while back before getting distracted. It's extremely rough, but maybe you can take it from here:
class Dropdown < Widget
def initialize (list, opts = {})
#max_items = opts[:max_items] || 5
#min_letters = opts[:min_letters] || 3
#width = opts[:width] || 280
#fill = opts[:background] || white
#highlight = opts[:highlight] || yellow
#match_anywhere = opts[:match_anywhere].nil? ? true : opts[:match_anywhere]
#ignore_case = opts[:ignore_case].nil? ? true : opts[:ignore_case]
#entries = list
#text_box = edit_line :width => #width do |box|
if box.text.length >= #min_letters
update_list(box.text)
else
#list.clear if #list
#list = nil
end
end
end
def update_list(search)
search.downcase! if #ignore_case
choices = []
#entries.collect do |x|
temp = #ignore_case ? x.downcase : x
if #match_anywhere
choices << x if temp.include?(search)
else
choices << x if temp.index(search) == 0
end
break if choices.length == #max_items
end
#list.clear if #list
#list = nil
app.append do
#list = stack :width => #width do
background #fill
choices.each do |choice|
f = flow { para choice }
f.click do
#text_box.text = choice
#list.clear if #list
#list = nil
end
f.hover {|h| h.contents.first.fill = #highlight }
f.leave {|l| l.contents.first.fill = nil }
end
end
end unless choices.nil?
#list.move(0,0)
#list.displace(0, #text_box.height + #text_box.top)
end
end
Shoes.app(:width => 500, :height => 500) do
dropdown ['Breed', 'Green', 'Greetings', 'Phoning', 'Ponies', 'Reed', 'Trees'], {:max_items => 3}
para 'Ponies are awesome!'
para 'Bananas are yellow.'
para 'Sometimes I like to eat bananas, but never ponies.'
end
Try the "jquery options filter", based on real select box and matching in the mid of option texts:
http://plugins.jquery.com/project/jquery_options_filter
for diyism

Resources