method reverse django error - python

I'm calling a method using reverse but I have problem argument that I am not able to understand.
My error :
Reverse for 'shopping.views.payment_confirmation' with arguments '(35,)' and keyword arguments '{}' not found.
My url:
url(r'^payment_confirmation/(?P<id>\d+\d{2\})/$', 'payment_confirmation', name='payment_confirmation'),
My view:
def show(request):
...
...
payment.submit(settings.SITE_URL + reverse("shopping.views.payment_confirmation", args=[payment.id]))
My model Payment:
class Payment(models.Model):
...
...
def submit(self, redirect_url):
'''
Sends self as a Payment through PagSeguro API.
Payment instance MUST BE SAVED before calling this method.
'''
if not self.id:
#Temporary to identify which problem caused the crash.
raise ValidationError
#creating a reference if its None
if self.reference is None:
self.reference = configs.PAGSEGURO_REFERENCE_PREFIX + str(self.id)
document = Document()
document.appendChild(self.to_element(document, redirect_url))
response = document2dict(api.submit_payment(document))
try:
self.code = response['checkout']['code']
self.answered_on = datetime.datetime.now()
self.save()
except:
error_str = ""
if type(response["errors"]["error"]) != list:
response["errors"]["error"] = [response["errors"]["error"]]
for error in response["errors"]["error"]:
error_payment = ErrorPayment()
error_payment.code = int(error['code'])
error_payment.payment = self
error_payment.save()
error_str += "[%s: %s]" % (error_payment.code,
error_payment.get_code_display())
raise Exception(error_str)
the error is here payment.submit (settings.SITE_URL + reverse ("shopping.views.payment_confirmation", args = [payment.id]))
I', using this api https://bitbucket.org/leonardosantos/django-pagseguro2/

This line: reverse("shopping.views.payment_confirmation", args=[payment.id]) tells Django to find a url that matches a method called payment_confirmation in the views.py file in the shopping app that will accept a payment ID parameter.
In the error that you shared, the payment.id was 35. The error is saying that either there is no method called payment_confirmation in your shopping.views or the method does not accept a single int as a parameter.
You didn't share a payment_confirmation method in your views file so it seems that that is the issue. You need to add:
def payment_confirmation(payment_id):
#do stuff
to your views.

Related

Python - list comprehension as a decorator (including self)

I have two functions:
job_status is getting a response from boto3 api.
jobs_detailsis a list comprehension that performs job_status on each element of the input list.
I want to change jobs_details into a decorator of jobs_status but below solutions throws inner() takes 1 positional argument but 2 were given error.
Appreciate any comment/alternative approach to my issue. Thanks!
import boto3
class GlueClient:
def __init__(self):
self.glue_client = boto3.client('glue')
#self.envs = envs
def jobs_list(self):
response = self.glue_client.list_jobs()
result = response["JobNames"]
while "NextToken" in response:
response = self.glue_client.list_jobs(NextToken=response["NextToken"])
result.extend(response["JobNames"])
return [e for e in result if "jobs_xyz" in e]
#WHAT IS CURRENTLY
def job_status(self, job_name):
paginator = self.glue_client.get_paginator('get_job_runs')
response = paginator.paginate(JobName=job_name)
return response
def jobs_details(self, jobs):
return [self.job_status(e) for e in jobs]
#WHAT IS EXPECTED
def pass_by_list_comprehension(func):
def inner(list_of_val):
return [func(value) for value in list_of_val ]
return inner
#pass_by_list_comprehension
def job_status(self, job_name):
paginator = self.glue_client.get_paginator('get_job_runs')
response = paginator.paginate(JobName=job_name)
return response
glue_client = GlueClient()
jobs = glue_client.jobs_list()
jobs_status = glue_client.job_status(jobs)
print(jobs)
You want something like:
import boto3
from typing import Callable
def handle_iterable_input(func):
def inner(self, list_of_val):
return [func(self, value) for value in list_of_val]
return inner
class GlueClient:
def __init__(self):
self.glue_client = boto3.client('glue')
#self.envs = envs
def jobs_list(self):
response = self.glue_client.list_jobs()
result = response["JobNames"]
while "NextToken" in response:
response = self.glue_client.list_jobs(NextToken=response["NextToken"])
result.extend(response["JobNames"])
return [e for e in result if "jobs_xyz" in e]
#handle_iterable_input
def job_status(self, job_name):
paginator = self.glue_client.get_paginator('get_job_runs')
response = paginator.paginate(JobName=job_name)
return response
glue_client = GlueClient()
jobs = glue_client.jobs_list()
jobs_status = glue_client.job_status(jobs)
print(jobs)
This is the most basic way to make your decorator handle methods properly, by explicitly handling the passing of self. Note, it assumes the function being decorated will only take a single argument.
If all you want to do is make job_status iterate through a list of job names instead of operating on just one, something like this should work:
def jobs_status(self, job_names):
paginator = self.glue_client.get_paginator('get_job_runs')
return [paginator.paginate(JobName=job_name) for job_name in job_names]
Using a decorator to change what parameters a method expects seems like a bad idea.
Also, naming your class GlueClient would imply that it is a glue client. The fact that it has an attribute named glue_client makes me suspect you could probably choose a clearer name for one or both of them. (However, I'm not familiar with the package you're using.)

WTForms DateTimeField returning True not matter input

I am struggling to understand why WTForms always validates my input even when it doesn't match the default input format stated in the docs. The docs say the default format is
class wtforms.fields.DateTimeField(default field arguments, format='%Y-%m-%d %H:%M:%S')
but my code always returned true
from wtforms import Form, validators
from wtforms.fields import DateTimeField
class InputForm(Form):
timestamp = DateTimeField('TimeStamp', validators=[validators.DataRequired()])
form = InputForm(timestamp='lmao')
form.validate()
# True
Can someone explain this behavior to me?
To put it simply, whether the value you pass to the field can be coerced to a datetime isn't being checked as the validator that you have supplied only checks for existence of the data, not the type.
The DateTimeField does ensure that a value can be coerced to a datetime, but only if the value comes from a form. As you can see below, passing a value in to the form constructor via kwargs (timestamp='lmao') isn't passed through the same test.
Looking at the definition of the DateTimeField, the only method that has custom handling to do with the field being a datetime field is the process_formdata() method (also _value() but that is used by widgets to render fields):
class DateTimeField(Field):
"""
A text field which stores a `datetime.datetime` matching a format.
"""
widget = widgets.TextInput()
def __init__(
self, label=None, validators=None, format="%Y-%m-%d %H:%M:%S", **kwargs
):
super(DateTimeField, self).__init__(label, validators, **kwargs)
self.format = format
def _value(self):
if self.raw_data:
return " ".join(self.raw_data)
else:
return self.data and self.data.strftime(self.format) or ""
def process_formdata(self, valuelist):
if valuelist:
date_str = " ".join(valuelist)
try:
self.data = datetime.datetime.strptime(date_str, self.format)
except ValueError:
self.data = None
raise ValueError(self.gettext("Not a valid datetime value"))
When you instantiate a Form object, the form's process() method is called which calls the process() method of each of the forms fields and passes the formdata (which in this case is None) and a value for the field if one can be found (in this case, 'lmao').
As you can see, there is no process() method defined on the DateTimeField definition above, so it calls Field.process():
def process(self, formdata, data=unset_value):
"""
Process incoming data, calling process_data, process_formdata as needed,
and run filters.
If `data` is not provided, process_data will be called on the field's
default.
Field subclasses usually won't override this, instead overriding the
process_formdata and process_data methods. Only override this for
special advanced processing, such as when a field encapsulates many
inputs.
"""
self.process_errors = []
if data is unset_value:
try:
data = self.default()
except TypeError:
data = self.default
self.object_data = data
try:
self.process_data(data)
except ValueError as e:
self.process_errors.append(e.args[0])
if formdata is not None:
if self.name in formdata:
self.raw_data = formdata.getlist(self.name)
else:
self.raw_data = []
try:
self.process_formdata(self.raw_data)
except ValueError as e:
self.process_errors.append(e.args[0])
try:
for filter in self.filters:
self.data = filter(self.data)
except ValueError as e:
self.process_errors.append(e.args[0])
In this method, the parameter data is 'lmao', and formdata is None. You can see that the call to process_formdata() is guarded by the if formdata is not None: conditional, and so the custom handling for the field defined on DateTimeField is only run on data that comes from a form.
from werkzeug import MultiDict
form = InputForm(formdata=MultiDict([("timestamp", "lmao")]))
print(form.timestamp.raw_data) # ['lmao']
print(form.timestamp.process_errors) # ['Not a valid datetime value']
print(form.validate()) # False
This means that you are responsible for the validity of values that you pass in to your form fields through kwargs to the form constructor.

Django Testing - TypeError: argument of type model is not iterable

I'm getting an error when running python manage.py test:
TypeError: argument of type 'Course' is not iterable
Here are my tests:
def test_course_list_view(self):
resp = self.client.get(reverse('courses:list'))
self.assertEqual(resp.status_code, 200)
self.assertIn(self.course, resp.context['courses'])
self.assertIn(self.course2, resp.context['courses'])
def test_course_detail_view(self):
resp = self.client.get(reverse('courses:detail', args=[self.course.pk]))
self.assertEqual(resp.status_code, 200)
self.assertIn(self.course, resp.context['course'])
Here is my view that I'm testing:
def course_list(request):
courses = Course.objects.all()
return render(request, 'courses/course_list.html', {'courses': courses})
def course_detail(request, pk):
course = get_object_or_404(Course, pk=pk)
return render(request, 'courses/course_detail.html', {'course': course})
Confused because i'm not getting an error in test_course_list_view but test_course_detail_view does throw an error?
assertIn does what the name implies: it asserts that argument one is in argument two. But in your test for the detail view, you are passing resp.context['course'] as your argument two, which is not a list or container, it is a single instance.
You need to compare that the two are equal, not that one is in the other.
self.assertEqual(self.course, resp.context['course'])

__init__() takes exactly 4 arguments (1 given)

form.py
class InvoiceForm(ModelForm,):
def __init__(self,em,first,last):
self.email=em
self.first=first
self.last=last
super(InvoiceForm,self).__init__(self,em,first,last)
self.fields['email']=forms.ChoiceField(choices=[x.email for x in AuthUser.objects.filter(email=em)])
self.fields['first']=forms.ChoiceField(choices=[x.first_name for x in AuthUser.objects.filter(first_name=first)])
self.fields['last']=forms.ChoiceField(choices=[x.last_name for x in AuthUser.objects.filter(last_name=last)])
total_credits_ordered=forms.IntegerField(label=mark_safe('<br/> total_credits_ordered'))
total_mobile_cr_ordered=forms.IntegerField(label=mark_safe('<br/> total_mobile_cr_ordered'))
total_cloud_cr_ordered=forms.IntegerField(label=mark_safe('<br/> total_cloud_cr_ordered'))
invoice_currency=forms.CharField(label=mark_safe('<br/> invoice_currency'),max_length=100)
invoice_currency_code=forms.IntegerField(label=mark_safe('<br/>invoice_currency_code '))
invoice_country=forms.CharField(label=mark_safe('<br/> invoice_country'),max_length=100)
invoice_note=forms.CharField(label=mark_safe('<br/> invoice_note'),max_length=100)
class Meta:
model=Invoices
fields=['total_credits_ordered','total_mobile_cr_ordered','total_cloud_cr_ordered','invoice_currency','invoice_currency_code','invoice_country','invoice_note']
views.py
def test(request):
from app.tests import model_tests
m = model_tests()
print "assf"
try:
if request.method=="POST":
print "sff"
m.create_user_types()
cform=CustomerForm(request.POST)
if cform.is_valid():
em=cform.cleaned_data['email']
username=email
password = cform.cleaned_data['password']
first=cform.cleaned_data['first']
last=cform.cleaned_data['last']
companyname=cform.cleaned_data['company_name']
companyaddr=cform.cleaned_data['company_addr']
companystate=cform.cleaned_data['company_state']
companycountry=cform.cleaned_data['company_country']
id=m.create_customer(username,email,password,first,last,companyname,companyaddr,companystate,companycountry)
print "SFsfg"
iform=InvoiceForm(email,first,last)
print "ggg"
if iform.is_valid():
tco=iform.cleaned_data['total_credits_ordered']
tmco=iform.cleaned_data['total_mobile_cr_ordered']
tcco=iform.cleaned_data['total_cloud_cr_ordered']
ic=iform.cleaned_data['invoice_currency']
icc=iform.cleaned_data['invoice_currency_code']
c=iform.cleaned_data['invoice_country']
inote=iform.cleaned_data['invoice_note']
id_i=m.create_invoices(id,tco,tmco,tcco,ic,icc,c,inote)
pform=PaymentForm()
print "dsf"
pform=PaymentForm(request.POST)
if pform.is_valid():
tpm=pform.cleaned_data['total_payment_made']
ps=pform.cleaned_data['payment_status']
pt=pform.cleaned_data['payment_type']
m.create_payment(id_i,tpm,ps,pt)
return HttpResponse("test successful")
else:
print "d"
cform=CustomerForm()
iform=InvoiceForm()
pform=PaymentForm()
return render(request, 'test.html', {'cform': cform,'iform':iform,'pform':pform})
except Exception as e:
return HttpResponse("Exception : %s" %(e))
return HttpResponse("Tests Successfull...")
It is showing:
Exception : __init__() takes exactly 4 arguments (1 given)
but I have passed parameters to the form.
We don't have the stacktrace in the question but problem is probably here:
else:
print "d"
cform=CustomerForm()
iform=InvoiceForm()
pform=PaymentForm()
Here you are creating objects without passing any parameters. Since the instance itself is always passed, the message says that it misses the other parameters which are em,first,last
I suggest that you remove everything after the else part since it does nothing useful or a warning like this to avoid silent errors:
else:
print("Unsupported method "+request.method)

attribute error 'function' object has no attribute 'has_header'

i have been encountered by this error
'function' object has no attribute 'has_header'
my url file contans
url(r'^HighDefs/$', list_HighDefs),
and i have a view defined with the name
list_HighDefs
in views file. I dont know whats wrong.
the view contains
def list_HighDefs(request):
user_logger = Logger()
user_logger.log_stack()
if user_object:
email = user_object.email
uname = user_object.first_name+' '+user_object.last_name
try:
row = allapps_models.highdef.objects.filter(user_email=email, show_status=1)
except Exception:
return error_page(request)
highdefs = []
for m in row:
order_product = int(m.m_id)
state = m.state
try:
category = checkout_models.state.objects.get(pk=product).premature.category.all()
category = category[0].pk
except:
category = 0
if int(category) == 2:
if state != 's':
highdefs.append(m)
return render_to_response('main/HighDefs.html',{'request': request, 'highdefs': highdefs, 'uname' :uname, 'email': email}, context_instance=RequestContext(request))
else:
return(login)
Your view must return an HttpResponse object.
It does this for one branch of your if statement:
return render_to_response(...)
But not in the else branch.
return(login)
If login is a view function that returns an HttpResponse object, then you can change your return statement to
return login(request)
However, I suspect you want to redirect the user to your login page instead. In that case, change your code to:
from django.http import HttpResponseRedirect
return HttpResponseRedirect('/login/')
where /login/ is the url of your login page.
The last line of your view is return login (don't know why you're wrapping your returns in parentheses, it's unnecessary). But presumably login is a function, and you're not calling it. I expect you mean to do return login() or return login(request).

Categories