Creating Rest Api in python using JSON? - python

I'm new to python REST API and so facing some particular problems. I want that when I enter the input as pathlabid(primary key), I want the corresponding data assigned with that key as output. When I run the following code i only get the data corresponding to the first row of table in database even when the id i enter belong to some other row.
This is the VIEWS.PY
class pathlabAPI(View):
#csrf_exempt
def dispatch(self, *args, **kwargs):
# dont worry about the CSRF here
return super(pathlabAPI, self).dispatch(*args, **kwargs)
def post(self, request):
post_data = json.loads(request.body)
Pathlabid = post_data.get('Pathlabid') or ''
lablist = []
labdict = {}
lab = pathlab()
labs = lab.apply_filter(Pathlabid = Pathlabid)
if Pathlabid :
for p in labs:
labdict["Pathlabid"] = p.Pathlabid
labdict["name"] = p.Name
labdict["email_id"] = p.Emailid
labdict["contact_no"] = p.BasicContact
labdict["alternate_contact_no"] = p.AlternateContact
labdict["bank_account_number"] = p.Accountnumber
labdict["ifsccode"] = p.IFSCcode
labdict["country"] = p.Country
labdict["homepickup"] = p.Homepickup
lablist.append(labdict)
return HttpResponse(json.dumps(lablist))
else:
for p in labs:
labdict["bank_account_number"] = p.Accountnumber
lablist.append(labdict)
return HttpResponse(json.dumps(lablist))

There are a number of issues with the overall approach and code but to fix the issue you're describing, but as a first fix I agree with the other answer: you need to take the return statement out of the loop. Right now you're returning your list as soon as you step through the loop one time, which is why you always get a list with one element. Here's a fix for that (you will need to add from django.http import JsonResponse at the top of your code):
if Pathlabid:
for p in labs:
labdict["Pathlabid"] = p.Pathlabid
labdict["name"] = p.Name
labdict["email_id"] = p.Emailid
labdict["contact_no"] = p.BasicContact
labdict["alternate_contact_no"] = p.AlternateContact
labdict["bank_account_number"] = p.Accountnumber
labdict["ifsccode"] = p.IFSCcode
labdict["country"] = p.Country
labdict["homepickup"] = p.Homepickup
lablist.append(labdict)
else:
for p in labs:
labdict["bank_account_number"] = p.Accountnumber
lablist.append(labdict)
return JsonResponse(json.dumps(lablist))
As suggested in the comments, using Django Rest Framework or a similar package would be an improvement. As a general rule, in Django or other ORMs, you want to avoid looping over a queryset like this and adjusting each element. Why not serialize the queryset itself and do the logic that's in this loop in your template or other consumer?

You are return the response in for loop so that loop break on 1st entry
import json
some_list = []
for i in data:
some_list.append({"key": "value"})
return HttpResponse(json.dumps({"some_list": some_list}), content_type="application/json")
Try above example to solve your problem

Related

How to use function's return within other function (without using class)

I have a function:
def search_result(request):
if request.method =='POST':
data = request.body
qd = QueryDict(data)
place = qd.values()[2]
indate = qd.values()[3]
outdate = qd.values()[0]
url = ('http://terminal2.expedia.com/x/mhotels/search?city=%s&checkInDate=%s&checkOutDate=%s&room1=2&apikey=%s') %(place, indate, outdate, MY_API_KEY)
req = requests.get(url).text
json_data = json.loads(req)
results = []
for hotels in json_data.get('hotelList'):
results.append(hotels.get('localizedName'))
return HttpResponse(results)
now I want to use func1's return within other function to render template something like this:
def search_page(request):
r = search_result(request)
d = r.content
return render(request,'search.html', {'res':d})
and this actually do not work.
Does any way exist to do what I want (without using class)?
I make post via ajax from template form and my first function works properly and prints result in console. The problems occurs when I try use my response in next function to render it in template. Thats why I ask to help me. Have you any ideas to make my response from first function visible for another function?
You have defined func1 to take the request parameter, but when you call it in your second function you do not pass it any arguments.
If you pass in request it should work.
EDIT: You are looking for the results, so I suppose you can just return them instead of the HttpResponse (maybe we need more information on what you are trying to accomplish)
def func1(request):
......
results = []
for hotels in json_data.get('hotelList'):
results.append(hotels.get('localizedName'))
return results
def funk2(request):
f = funk1(request)
return render(request,'search.html', {'res':f})

Prepopulate 1 form field that is a foreign key

Previously I was letting the user pick from a drop down of colors but I would like to rather pick one for them so I used the following code to determine which colors would be a valid choice and then randomly chose one. I'm trying to get it to pre-populate in the form and I'm getting a name error. Scratching my head like crazy because I tested this code by simply piping choice into a template already. So I know the code functioned properly in that context. Can I not do something that I've done below?
The error I'm getting when I launch my server is Name Error: name 'cur_colors' [at the list comprehension line] is not defined but it clearly is...
class LimitedJobForm(forms.ModelForm):
jobnum = forms.CharField(label='Job Number')
#get colorchoice
cur_jobs = Job.objects.filter(enddate__gte=(datetime.date.today()-timedelta(days=7)))
all_colors = Color.objects.all()
cur_colors = []
for i in cur_jobs:
cur_colors.append(i.color)
aval_colors = [x for x in all_colors if x not in cur_colors]
choice = random.choice(aval_colors)
color = forms.CharField(initial=choice)
You haven't defined an init method for this code to go into, thusly its just reading each line individually as a declaration
Move your code into an init method and it should work fine!
class LimitedJobForm(forms.ModelForm):
jobnum = forms.CharField(label='Job Number')
color = forms.CharField()
def __init__(self, *args, **kwargs):
super(LimitedJobForm, self).__init__(*args, **kwargs)
cur_jobs = Job.objects.filter(enddate__gte=(datetime.date.today()-timedelta(days=7)))
all_colors = Color.objects.all()
cur_colors = []
for i in cur_jobs:
cur_colors.append(i.color)
aval_colors = [x for x in all_colors if x not in cur_colors]
choice = random.choice(aval_colors)
self.fields['color'].initial = choice

What's the Pythonic way to get the 'source' when a function is called?

Given the example below, is there a more elegant solution than passing a string to allow a function to test against and in turn, run the required code?
myfunction(self, "location1")
def myfunction(self, source):
if source == "location1":
qs = MyModel.objects.filter(id = self.object.id)
return qs
elif source == "location2":
qs = AnotherModel.objects.filter(id = self.object.id)
return qs
else:
qs = YetAnotherModel.objects.filter(id = self.object.id)
return qs
This example contains dummy Django queries, but I've had to use this solution on various Python functions throughout my projects.
I think this way is cleaner:
def myfunction(self, source):
models = { "location1": MyModel,
"location2": AnotherModel,
"location3": YetAnotherModel
}
selected = models.get(source, YetAnotherModel)
qs = selected.objects.filter(id = self.object.id)
return qs
I think this one may be ok:
from collections import defaultdict
def myfunction(source):
return defaultdict(lambda: YetAnotherModel.objects.filter(id = self.object.id),
{ "location1": MyModel.objects.filter(id = self.object.id),
"location2": AnotherModel.objects.filter(id = self.object.id) })
[source]
Hope this helps!

Attribute lost when rendering the object to view in Flask

This is a rather silly issue but I stepped through the function but couldn't figure out what was causing the issue.
I was dynamically adding an attribute to the object I fetched from the db via SQLAlchemy and the objects were appended fine right before the return render_template was called, all but the last appended attribute in the variable from the list of found_survey.questions was lost. I.e. found_survey.questions[0].choices doesn't exist (but it did at one point), but found_survey.questions[-1].choices does.
I cannot seem to figure out what is going on... I thought it might be funky because of the database object (since I didn't commit survey, but I don't intend to, I was just appending the value so it's passed to the view with the correct logic).
Thanks so much for the help; I'm really stuck...
#app.route('/survey/<survey_id>', methods=['GET', 'POST'])
#login_required
def survey(survey_id):
form = UserSubmitForm()
found_survey = Survey.query.filter_by(id=survey_id).first()
if request.method == 'POST' and form.validate_on_submit():
print("input", form.answer_raw.data, form.category_list.data)
user_answer = Answer(note=found_survey.name,
answer_raw=form.answer_raw.data,
timestamp=datetime.utcnow(),
ip=request.remote_addr)
user_answer.user_id = g.user.id
user_answer.survey_id = survey_id
# other processing omitted
db.session.add(user_answer)
elif request.method != "POST":
for q in found_survey.questions:
q.choices = []
text_list = q.choice_text_string.split(',')
value_list = q.choice_value_string.split(',')
for i, text in enumerate(text_list):
q.choices.append((text, value_list[i]))
return render_template('survey.html',
form=form,
survey=found_survey,
is_editing=False)
Wouldn't it just be simpler to do this:
annotated_obj = []
for q in found_survey.questions:
text_list = q.choice_text_string.split(',')
value_list = q.choice_value_string.split(',')
question_choices = {}
for i, text in enumerate(text_list):
question_choices.setdefault(text, []).append(value_list[i])
annotated_obj.append((q, question_choices))

django 1.3 forms validation using clean method to retrieve getlist

I have a form with checkboxes, the form functioning well, in my view i can use request.POST.getlist('list') to retrieve the list of values.
At the moment am trying to do some form validation inside the clean method and when i try to use self.cleaned_data['list'] I get the last value. I cannot retrieve the list of items.
Any idea how i could do that?
forms.py
class SelectList_Form(forms.Form):
list = forms.CharField(required=False)
def clean(self):
super(SelectList_Form, self).clean()
cleaned_data = self.cleaned_data
try:
# TODO: list validation
if cleaned_data['list'].__len__() is 0:
raise forms.ValidationError(_('Must select at least one of the lists below'),)
if cleaned_data['list'].__len__() > 1:
try:
# In here when i print list it only shows me the last value. It doesn't show me the list of values when the box is checked
print cleaned_data['list']
except Main.DoesNotExist:
raise Http404
except forms.ValidationError:
raise
class Posting_Wizard(FormWizard):
def render_template(self, request, form, previous_fields, step, context=None):
if step == 0:
obj = MainI18n.objects.filter(main__is_active=True, language=request.LANGUAGE_CODE).\
exclude(main__parent=None).order_by('main__parent').select_related(depth=1)
category_choices=dict(['%s,%s' % (i.main.slug, i.main.parent.slug), '%s - %s' % (i.main.parent,i.label)] for i in obj)
form.fields['categories'] = forms.CharField(widget=forms.RadioSelect(choices=category_choices.items()))
if step == 1:
category = request.POST.get('0-categories')
pobj = Main.objects.filter(slug=category.split(',')[1], parent=None).get()
cobj = Main.objects.filter(slug=category.split(',')[0], parent=pobj.id).get()
lobj = ListI18n.objects.filter(list__is_active=True, language=request.LANGUAGE_CODE, list__main__slug=category.split(',')[0], list__main__parent=pobj.id).select_related()
list_choices = dict([i.id, i.title] for i in lobj)
if cobj.mainproperties.relation == 'M':
# Here i generate the checkboxes
form.fields['list']=forms.CharField(widget=forms.CheckboxSelectMultiple(choices=list_choices.items()),label="Pick the list",)
else:
form.fields['list']=forms.CharField(widget=forms.RadioSelect(choices=list_choices.items()),label="Pick the list",)
return super(Posting_Wizard, self).render_template(request, form, previous_fields, step, context)
def done(self, request, form_list):
return HttpResponseRedirect(reverse('accounts-registration-wizard-done'))
def get_template(self, step):
return 'listing/post/wizard/wizard_%s.html' % step
First, there are a number of basic Python errors here. There is almost never a need to access the double-underscore functions - they are internal implementation details. Always use the normal len() function instead. And, never use is for comparisons: it's for identity, so should only be used with things you know have the same identity, which basically just means None. So your code should read:
if len(cleaned_data['list']) == 0:
etc.
Now, secondly, I don't understand why you think there could ever be more than one 'element' in list. You've defined it as a CharField, which is a single field containing many characters. Your len is testing the number of characters entered into that field, not the number of fields, however you think you've defined them.

Categories

Resources