I start with def start method, it calls go_adder to add the num value 5 times in the adder.html until num equals 5. After that, the adder method should return ready=1
In views.py
def start(request):
num=0
ready_or_not=go_adder(num)
return HttpResponse("Ready: %s "%str(ready_or_not))
def go_adder(num):
ready=0
if num<5:
return render_to_response('adder.html',{'num':num})
elif num==5:
ready=1
return ready
def check_post(request,num):
if request.method == 'POST':
num+=1
return adder(num)
When I try to run this snippet code, it works until my "num=5", Then I get that error :
'int' object has no attribute 'status_code'
Exception Location: C:\Python27\lib\site-packages\django\middleware\common.py in process_response, line 94
and Traceback says:
C:\Python27\lib\site-packages\django\core\handlers\base.py in get_response
response = middleware_method(request, response) ...
▶ Local vars
C:\Python27\lib\site-packages\django\middleware\common.py in process_response
if response.status_code == 404: ...
▶ Local vars
How can I fix that error ? Could you please help me ?
The django views need to return an HttpResponse object. You are doing that while num < 5, but then you return an int when num == 5:
def adder(num):
ready=0
if num<5:
num+=1
# This renders the template and returns and HttpResponse; good
return render_to_response('adder.html',{'num':num})
elif num==5:
ready=1
# DONT RETURN AN INT HERE. RETURN AN HttpResponse
return ready
If all you want for when num==5 is to return a plain text response of the number 1, then you can return an HttpResponse and set the content type:
elif num==5:
ready=1
return HttpResponse(str(ready), content_type="text/plain")
Update 1
Based on our conversation, you have suggested that you want the view to constantly pass along the count value no matter what, and that you are POST-ing the num value in the actual form. If the number is less than 5 it should return one kind of template, otherwise it should return another kind of template.
You can combine your two different views into one that will handle both the original GET request when the page is first loaded, and the POST request submitted by your form. Just make sure to point your form at that same page.
def check(request):
num = 0
if request.method == 'POST':
num = int(request.POST.get('num'))
return adder(num)
def adder(num):
if num < 5:
num += 1
tpl_name = 'adder.html'
else:
tpl_name = 'print.html'
return render_to_response(tpl_name, {'num':num})
check() is your single view.
adder() is the helper function that will add the value, check it, and return an HttpResponse object based on that value. You must always return this from your view to the client.
Both templates will be passed the context containing the value of num
Update 2
You said that you are actually passing in your num through the url and not through the POST form. Small adjustment to the last example. You don't even need an adder() anymore. You only need a single view.
Set your url to have an optional num pattern:
urls.py
(r'^checker/(?P<num>\d+)$', 'myapp.views.check')
views.py
def check(request, num=0):
num = int(num)
if num < 5:
num += 1
tpl_name = 'adder.html'
else:
tpl_name = 'print.html'
return render_to_response(tpl_name, {'num':num})
Your "checker" url now has an optional number. If it is not passed in the url, it will be a value of 0 in the view. If you send it as a POST request, it will add and return a different template.
Related
here is the image of error that i am getting in the browser
I am new to python and hardly tried to figure out the problem of usese of variable from another if statement in the same function
here is my code:
def post(self, request, **kwargs):
selected_membership_type = request.POST.get('membership_type')
user_membership = get_user_membership(request)
user_subscription = get_user_subscription(request)
selected_membership_qs = Membership.objects.filter(
membership_type=selected_membership_type)
if selected_membership_qs.exists():
selected_membership = selected_membership_qs.first()
'''
==========
VALIDATION
==========
'''
# selected_membership = selected_membership_qs.first()
if user_membership.membership == selected_membership:
if user_subscription == None:
messages.info(request,"You already have this membership.Your \
next payment is due {}".format('get this value from stripe'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
The problem is the following:
if selected_membership_qs.exists():
selected_membership = selected_membership_qs.first()
You are only assigning selected_membership if the if is True.
So in your case you are getting the Variable referenced before assignment error because the if is False.
Therefore selected_membership is never assigned.
If you do something like this
selected_membership = None
if selected_membership_qs.exists():
selected_membership = selected_membership_qs.first()
it should work.
I'm making a big mess trying to access the object that I passed from the view to the form.
class PrenotaForm(forms.ModelForm):
ORARI_CHOICES = ()
def __init__(self, *args, **kwargs):
DICT_ORARI_CHOICES = kwargs.pop('ORARI_CHOICES_NEW', {})
ORARI_CHOICES_NEW = []
for key, value in DICT_ORARI_CHOICES.items():
temp = [key,value]
ORARI_CHOICES_NEW.append(temp)
super(PrenotaForm, self).__init__(*args, **kwargs)
self.ORARI_CHOICES = ORARI_CHOICES_NEW
print("EEEEEEEEEEEEEEE" + str(self.ORARI_CHOICES))
print(ORARI_CHOICES)
I don't understand why inside the init the ORARI_CHOICES is populated as shown in console output:
EEEEEEEEEEEEEEE[['è uguale', 'Indifferente'], ['845', '08:45'], ['900', '09:00'], ['915', {'label': '09:15', 'disabled': 'disabled'}], ['930', {'label': '09:30', 'disabled': 'disabled'}], ['945', '09:45'], ['1000', '10:00'], ['1015', '10:15'], ['1030', '10:30'], ['1045', '10:45'], ['1100', '11:00'], ['1115', '11:15'], ['1130', '11:30'], ['1145', '11:45']]
but outside the init the ORARI_CHOICE is still empty:
print(ORARI_CHOICES)
since the print does not output nothing.
How can I override the ORARI_CHOICES = () and make it avalable globally in the class after every GET request performed in the view?
if request.method == 'GET':
size_gruppi = 30
print("gruppi size is : " + str(size_gruppi))
ORARI_CHOICES = (
('è uguale', "Indifferente"),
('845', "08:45"),
('900', "09:00"),
('915', "09:15"),
('930', "09:30"),
('945', "09:45"),
('1000', "10:00"),
('1015', "10:15"),
('1030', "10:30"),
('1045', "10:45"),
('1100', "11:00"),
('1115', "11:15"),
('1130', "11:30"),
('1145', "11:45"),
)
orari_map = map(list,ORARI_CHOICES)
orari_dict = dict(ORARI_CHOICES)
print(orari_dict)
counter = 0
for key in orari_map:
if key[0] != 'è uguale':
tot_in_fascia = sum(filter(None, Iscritto.objects.filter(fasce_orarie=key[0]).aggregate(Sum('size_adulti'), Sum('size_giovani')).values()))
print(tot_in_fascia)
if tot_in_fascia >= size_gruppi:
print("fascia " + key[0] + " è al completo ")
orari_dict.update({key[0]: {'label': key[1], 'disabled': 'disabled'}})
form = PrenotaForm(ORARI_CHOICES_NEW = orari_dict)
return render(request, "prenota.html", {'form': form, 'posti_liberi': posti_disponibili, 'giovani_iscritti': giovani_iscritti})
You should set ORARI_CHOICES as a class/static attribute.
class PrenotaForm(forms.ModelForm):
ORARI_CHOICES = []
def __init__(self, *args, **kwargs):
DICT_ORARI_CHOICES = kwargs.pop('ORARI_CHOICES_NEW', {})
# ORARI_CHOICES_NEW = []
for key, value in DICT_ORARI_CHOICES.items():
temp = [key,value]
self.__class__.ORARI_CHOICES.append(temp)
super(PrenotaForm, self).__init__(*args, **kwargs)
print("EEEEEEEEEEEEEEE" + str(self.ORARI_CHOICES))
Now, PrenotaForm.ORARI_CHOICES is already accessible. PrenotaForm.ORARI_CHOICES will always be accessible, but it returns empty list, untill you do not create instance of PrenotaForm. After instance creation of PrenotaForm, __init__ method will be called and data will be added inside ORARI_CHOICES.
So I am implementing this answer: Country/State/City dropdown menus inside the Django admin inline, but the def render piece of code needs to be redone.... I have managed to redo it, but I am struggling to find a replacement (or the correct code) for the self.render_options method (which was deprecated on 1.11) of the Widget class.
I am on Django 2.1.
What should I change?
Here is my code:
class StateChoiceWidget(widgets.Select):
def render(self, name, value, attrs=None, renderer=None):
self.choices = [(u"", u"---------")]
if value is None:
value = ''
model_obj = self.form_instance.instance
if model_obj and model_obj.country:
for m in model_obj.country.state_set.all():
self.choices.append((m.id, smart_text(m)))
else:
obj = State.objects.get(id=value)
for m in State.objects.filter(country=obj.country):
self.choices.append((m.id, smart_text(m)))
final_attrs = self.build_attrs(attrs)
output = ['<select%s>' % flatatt(final_attrs)]
for option in self.choices:
output.append('<option value="%s">%s</option>' % (option[0], option[1]))
output.append('</select>')
return mark_safe(''.join(output))
Original poster updated the sample code, so now it doesn't show the code in the question: see previous revision https://stackoverflow.com/revisions/52174508/1
So I figured out the answer. Will post it here in case someone runs into the same issue.
class StateChoiceWidget(widgets.Select):
def render(self, name, value, attrs=None, renderer=None):
self.choices = [(u"", u"---------")]
if value is None or value == '':
value = ''
model_obj = self.form_instance.instance
if model_obj and model_obj.country:
for m in model_obj.country.state_set.all():
self.choices.append((m.id, smart_text(m)))
else:
obj = State.objects.get(id=value)
for m in State.objects.filter(country=obj.country):
self.choices.append((m.id, smart_text(m)))
final_attrs = self.build_attrs(attrs)
s = widgets.Select(choices=self.choices)
select_html = s.render(name=name,value=value,attrs=attrs)
return mark_safe(''.join(select_html))
flask + wtforms
Hello, I have some problems with the transfer of data into a form
def edit_comment(n):
idlist = str(n)
if (r.exists('entries:%s' %idlist) != True):
return abort(404)
if 'user_id' not in session:
return abort(401)
if (g.user['group_access'] == '1'):
return abort(403)
form = EditForm(idlist)
return render_template('edit_comment.html',idlist = idlist, r = r, form = form)
...
class EditForm(Form):
edit_title = TextField("Title",validators = [Required()] ,default =r.hget('entries:%s' %idlist, 'title'))
edit_text = TextAreaField("Text",validators = [Required()],default =r.hget('entries:%s' %idlist, 'text'))
...
Traceback (most recent call last):
File "run.py", line 129, in <module>
class EditForm(Form):
File "run.py", line 130, in EditForm
edit_title = TextField("Title",validators = [Required()] ,default =r.hget('entries:%s' %idlist, 'title'))
NameError: name 'idlist' is not defined
here there are clear problems with data transmission. tried to pass through the constructor, but so far No results
You need to set the default value on the EditForm instance. Right now it' set at import time - clearly not what you want, even if the variable was defined. Actually, you don't even need the default field for it - just set it directly:
form = EditForm()
form.edit_title.data = r.hget('entries:%s' % idlist, 'title')
form.edit_text.data = r.hget('entries:%s' % idlist, 'text')
return render_template('edit_comment.html', idlist=idlist, r=r, form=form)
Note: Usually it's a good idea to have your view function to have a structure similar to this:
form = EditForm()
if form.validate_on_submit():
# do whatever should be done on submit, then redirect somewhere
return redirect(...)
elif request.method == 'GET':
# Populate the form with initial values
form.edit_title.data = ...
form.edit_text.data = ...
return render_template(..., form=form)
That way whatever the user entered is preserved in case the validation fails, but if he opens the form for the first time it's populated with whatever default data (e.g. the current values from your db) you want.
I am creating a custom widget for a datetime field:
class MySplitDateTimeWidget(forms.SplitDateTimeWidget):
def format_output(self, rendered_widgets):
mytimeid = self.widgets[1].attrs['id'] #####NEED HELP HERE
temp = "javascript:$('%s').val(new Date().getHours());" % mytimeid
temp1 = 'Now' % temp
return mark_safe(u'%s %s<br />%s %s %s' % \
(_('Date:'), rendered_widgets[0], _('Time:'), rendered_widgets[1],
temp1
))
I need the "id" attribute of the widget, however self.widgets doesn't include the "id" attribute in attrs. It includes every other attribute though. I'm not sure where this attribute comes from?
I was just grappling with the exact same thing; hopefully this is useful for other people. The "id" attr is set via:
Form is asked to render itself
Form iterates through its fields
For each field, the form calls its custom __getitem__() which wraps the field as a BoundField
The BoundField, in the as_widget() method, is what actually sets the "id" attribute (see also the auto_id() method)
The MultiWidget then performs its render() method, which renders each of its child widgets and then joins them with format_output()
So, to answer your question, you want to get the ID in the render() method and not the format_output() method:
class MySplitDateTimeWidget(forms.SplitDateTimeWidget):
def render(self, name, value, attrs=None):
widgets_html = super(MySplitDateTimeWidget, self).render(name, value, attrs)
# attrs['id'] is the ID of the entire widget, append the prefix to chose the sub-widget
mytimeid = attrs['id'] + '_0'
temp = "javascript:$('%s').val(new Date().getHours());" % mytimeid
temp1 = 'Now' % temp
return mark_safe(widgets_html + ' ' + temp1)
def format_output(self, rendered_widgets):
return mark_safe(u'%s %s<br />%s %s' % (_('Date:'), rendered_widgets[0], _('Time:'), rendered_widgets[1]))
Unless you've overwritten it, the ID should be:
id_[name]
So try:
mytimeid = 'id_'+self.widgets[1].attrs['name']