Django Displaying Menu/Sub Menu - python

I am trying to displaying Menu and Sub Menu in table format like
Menu1
Menu2
SubMenu1
SubMenu2
SubMenu3
Menu3
SubMenu4
SubMenu5
SubMenu6
Menu4
So far, I was able to come up with below code but its not showing any record.
Views.py
def getCompleteMenuList():
return Menu.objects.getMenuListing(id)
#mainMenuObj=Menu.objects.getMenuListing(id)
return render_to_response('manageMenu.html', {'title': menu_title,'name':name,'mainMenu':getCompleteMenuList,},context_instance=RequestContext(request))
Models.py
def getMenuListing(self, id):
mainMenus = self.filter(parent_menu=0,business=id).order_by('order')
result = []
menus = []
for menu in mainMenus:
menus.append(menu)
submenu = self.filter(parent_menu=menu,business=id).order_by('order')
if submenu.exists():
result.append(submenu)
return dict(zip(menus, result))
template.html
{% with mainMenu.items as pop_menus %}
{% for key, value in pop_menus %}
display main menu rows
{% for data in value %}
display sub menu rows
{% endfor %}
{% endfor %}
{% endwith %}
Current Situation I have 5 rows in table with 4 as parent_menu =0 and 1 as parent_menu = 1 (which exists).
When I try to print mainMenus its show 4 menu object.
< Menu: Menu object >, < Menu: Menu object >, < Menu: Menu object >, < Menu: Menu object >
But when I print menu inside for loop it only print 1 Menu object
Menu object
Can you please advise what I am doing wrong or is there any other way to achieve same thing?

This is not the right way of accessing your model methods, firstly you have to have an object of the Class which your method belongs to
Ex:
m = Menu.objects.get(id=foo)
foo is just an example it has to be some value corresponding to your id.
Then call the method you created on the models.py file through the object passing the required arguments
Ex:
menus = m.getMenuListing(id)
Now you have the correct data in the variable menus.
Try it this way.

at this line..
return dict(zip(menus, result))
Your menus and result length are not equals and therefore the zip() function as described here..
The returned list is truncated in length to the length of the shortest
argument sequence.
the dictionary will be truncate to length of menus.
Apart from your html template try unit test with getMenuListing() result.

Related

Formfield displayed based on treatment group

I am programming an experiment with different treatment Groups. For Treatment Group 3 and 4, I want to know the name of the Participants by using a form field. For the Control Group and Treatment Group 1 - 2, the name is irrelevant and thus, there should not be a forms_field.
I ws already thinking of excluding the form field in HTML by using if loops, so if treatment = 3 or 4, display the field. However, I cannot proceed to the next page for the other Treatment Groups since the field shouldn't be blank. Inserting a blank=True is not really an option since Treatment Group 3 and 4 could just skip the name. I want to "force" Treatment Group 3 and 4 to give me their name.
My code is too long to post it here, so I'll just post the relevant passages:
Modelsview
class Subsession(BaseSubsession):
def creating_session(self):
treatmentgroup = itertools.cycle(['ControlGroup','one','two','three', 'four'])
for p in self.get_players():
p.treatmentgroup = next(treatmentgroup)
class Group(BaseGroup):
pass
class Player(BasePlayer):
name = models.StringField(label="Your Name:")
transcribed_text = models.LongStringField()
levenshtein_distance = models.IntegerField()
guthaben = models.CurrencyField(initial=c(0))
cumulative_guthaben = models.CurrencyField()
Pagesview
class Welcome(Page):
form_model = 'player'
def is_displayed(self):
return self.round_number == 1
class Introduction(Page):
form_model = 'player'
def is_displayed(self):
return self.round_number == 1
class Math(Page):
form_model = 'player'
form_fields = ['name']
def is_displayed(self):
return self.round_number == 1
def before_next_page(self):
if self.round_number == 1:
self.player.guthaben = self.player.guthaben + Constants.endowment
def vars_for_template(self):
return {
'treatmentgroup': self.player.treatmentgroup,
'image_path': 'trophy/{}.png'.format(self.round_number)
}
HTML-Page
{% extends "global/Page.html" %}
{% load otree static %}
{% block title %}
The math task
{% endblock %}
{% block content %}
<p align="justify"> In case you have any questions, please open the door and wait for the experimenter to come to your cubicle.
</p>
{% if treatmentgroup == 'four' or treatmentgroup == 'three' %}
{% formfields %}
{% endif %}
{% next_button %}
{% endblock %}
Thanks in advance!
You can modify a django.forms subclass by using its init method. Your code doesn't show how the form gets instantiated, but somewhere you would have
form = Form_class() # unbound and
form = Form_class( request.POST ) # bound
You would modify these to pass hide_name=True if you do not want the name field displayed.
The form itself would include the method
def __init__(self, *args, **kwargs):
self.hide_name = kwargs.pop('hide_name', False)
super().__init__(*args, **kwargs)
self.hide_name is accessible in any method of the form, and form.hide_name in a template that is rendering it. To avoid validation errors you can remove that that field from the form
...
super().__init__(*args, **kwargs)
if self.hide_name:
self.fields.pop('name')

looping thru a python list and display results in flask

python function returns a python list
python module function
with open(xml_append_back) as fd1:
doc = xmltodict.parse(fd1.read())
codes = []
for p in doc['Des']['Config']:
codes.append(p['#Id'])
codes.append(pl['#name'])
print(codes)
return codes
codes = ['f2ee4681', 'Conf. no: 1', '89282c5b', 'Conf. no: 2', '3e9dd219', 'Conf. no: 3', '773044b9'] # returned from python to flask template result.html
I call this variable in my templates/flask.html like this
flask file
#app.route('/result',methods = ['POST', 'GET'])
def result():
const_ids=run_d.run_de_selected_configs() # this function returns "codes"
return render_template("result.html",result =
constraint_names_from_form,result1=constraint_ids)
result.html file
{% for key,key1 in result1 %}
<tr class="even"><td>{{ key }}</td><td>{{ key1 }}</td></tr>
should be
<tr class="even"><td>f2ee4681</td><td>Conf. no: 1</td></tr>
{% endfor %}
What am I doing wrong
To answer my own question
I used zip utility in my python code as zip is not available in flask
function returncodes()
-------
---------
return zip(codes,codeNames) # in my case
no change in the flask template
#app.route('/result',methods = ['POST', 'GET'])
def result():
const_ids=run_d.run_de_selected_configs() # this function returns "codes"
return render_template("result.html",result =
constraint_names_from_form,result1=constraint_ids)
now in my result.html
{% for keys,keys2 in result1 %}
<tr class="even"><td>{{keys}}</td><td>{{keys2}}</td></tr>
{% endfor %}
Currently your code is packing all the Id and name values into a single flat list. That doesn't work right when you later need to iterate over it, as you want two values per iteration and you're only getting one.
While there are some ways to iterate over pairs from a list (e.g. zip(*[iter(x)]*2)), I would suggest that you just build a list of tuples directly.
Try changing:
codes.append(planet['#Id'])
codes.append(planet['#name'])
To:
codes.append((planet['#Id'], planet['#name']))

How to make foreign key accept field value instead of its id in django?

I have created a checkbox for content filtering of products based on category.So when the user clicks on any checkbox only the books with that category should be shown.In the view I am passing the value of checkbox field(category name) obtained from the template but upon filtering, the foreign key is expecting pk(id) instead of field value.I am getting error like this,invalid literal for int() with base 10: '<category name>'.So is it possible to make foreign key accept value instead of id?
Models.py,
class Add_cat(models.Model):
category = models.CharField("Name",max_length=25,unique=True)
def __unicode__(self):
return u'{0}'.format(self.category)
class Add_prod(models.Model):
book = models.CharField("Book Name",max_length=40)
author = models.CharField("Author",max_length=30)
price = models.PositiveIntegerField("Price")
image = models.ImageField(upload_to='images',null=True)
cat = models.ForeignKey(Add_cat,on_delete=models.PROTECT)
Template file,
{% for i in products %}
<input type="checkbox" name="cat_name" value="{{i.cat}}">{{i.cat}}<br>
{% endfor %}
Views.py,
def welcome_user(request):
if 'cat_name' in request.GET:
filter_category = request.GET.get('cat_name')
my_products = Add_prod.objects.filter(cat__in = filter_category)
context = { "products":my_products}
else:
my_products = Add_prod.objects.all()
context = { "products":my_products}
return render(request,"welcome-user.html",context)
You can check in the category field itself:
my_products = Add_prod.objects.filter(cat__category__in=filter_category)
Have a look at the documentation on how this works.
Above, is only applicable if filter_category is a list. If it is a string you can filter like following:
my_products = Add_prod.objects.filter(cat__category=filter_category)
There are two things wrong with your code
You need to look up the field rather than the foreign key
By using __in you are looking the category is equal to any one of the characters in the filter_category.
Hence to fix, use the field lookup and remove the __in
Add_prod.objects.filter(cat__category=filter_category)
You can try this,it will help you:
Add_prod.objects.filter(cat__category = filter_category)

Django- Using Parameters To Display Entry

My database is setup something like.
class comments(models.Model):
min = models.FloatField()
max = models.FloatField()
comment = models.CharField(max_length=255)
In my view, I grab a float value from the user. I want to take that value use the Min/Max as parameters and if that float value is between the Min/Max, display the comment that's associated to it. At times there might be more then 1 match, however for now I cant even figure out how to do the first step.
Use the filter() method of a model manager with a combination of __lte/__gte lookups:
def comments(request):
value = float(request.GET['value'])
return render(request, 'comments.html',
{'comments': comments.objects.filter(min__lte=value,
max__gte=value)})
And then in the comments.html:
{% for comment in comments %}
<div>{{ comment.comment }}</div>
{% endfor %}

sqlite db called from flask only returns variables, not values

I have a flask app that queries a sqlite db:
#app.route('/<subject_id>')
def subject_id_lookup(subject_id):
entries = query_db('select visitdt, cvnotes from exam where id = ?',
[subject_id], one=True)
return render_template('show_results.html', entries = entries)
I am using flask functions largely unchanged from the docs including query_db()
def query_db(query, args=(), one = False):
"""Queries the database and returns a list of dictionaries"""
cur = g.db.execute(query, args)
rv = [dict((cur.description[idx][0], value)
for idx, value in enumerate(row)) for row in cur.fetchall()]
return (rv[0] if rv else None) if one else rv
Finally here is my show_results.html file:
{% extends "layout.html" %}
{% block body %}
<ul class=entries>
{% for entry in entries %}
<li><h2>{{ entry }}</h2>
<br>
{% else %}
<li><em>No entry here</em>
{% endfor %}
</ul>
{% endblock %}
The query runs fine but the nothing is returned except the variable names visitdt & cvnotes. When I change the line above to <li><h2>{{ entry.cvnotes }}</h2>, it returns nothing. How can I modify my query to show results from my subject_id_lookup() function?
The issue is that query_db returns different things depending on whether you specify one=True or one=False.
>>> query_db(your_query, [some_id], one=True)
{visittd: "a value", cvnotes: "some notes"}
>>> query_db(your_query, [some_id], one=False)
[{visittd: "a value", cvnotes: "some notes"}] # Note the wrapping list
When you enumerate over a dictionary the result is the keys in the dictionary - when you enumerate over a list, the result is the entries in the list.
>>> for thing in query_db(your_query, [some_id], one=True):
... print thing
visitdt
cvnotes
>>> for thing in query_db(your_query, [some_id], one=False):
... print thing
{visittd: "a value", cvnotes: "some notes"}
If you want to use the same template and you know there is only going to be one value returned for one id (or if you are fine with dealing with more than one value) simply remove the one=True keyword argument in subject_id_lookup. entries will then be a list of one dictionary containing the keys visitdt and cvnotes - when you iterate over it in your template each entry will be a result dictionary (rather than a key in the single result dictionary) and {{ entry.cvnotes }} will work.

Categories

Resources