Django - JSON response with serialized object - ajax

I am trying to send a serialized object using JSON. Here is my view code:
if request.is_ajax():
resp = {}
if request.POST:
if form.is_valid():
g = form.save()
resp['graph'] = serializers.serialize('json', [g, ])
resp['success'] = True
else:
resp['errors'] = form.errors
resp['success'] = False
return HttpResponse(simplejson.dumps(resp), mimetype='application/javascript')
return render(request, 'graph/inlines/create.html', {'form':form})
The problem is (rather obviously) that the 'graph' object I am trying to return is being serialized twice (once with serializers.serialize and again when I used simplejson.dumps) and the object is being received as a json string.
I tried just doing this:
resp['graph'] = g
But it throws a server error as the object obviously isn't serialized when I try to use simplejson.dumps.
Is there a way I can tell it to ignore this key when dumping the data? Would appreciate any help.

Rather than serializing the graph queryset to json the first time, use serializers.serialize('python', g) to convert it to a Python dictionary first. Then the whole thing will be converted to json at the end.

Related

Django rest framework does model field validation before own validation

I don't understand django rest framework validation process.
The doc say that validation is performed entirely on the serializer class.
However,
In the case of a PositiveIntegerField in a Model, when ModelSerializer receive a negative value, the model validation is processed before the custom ModelSerializer validate_myfield method.
class Blop(models.Model):
quantity = models.PositiveSmallIntegerField()
class BlopSerializer(serializers.ModelSerializer):
def validate_quantity(self, value):
return max(15, value)
class Meta:
model = Blop
if quantity if lesser than zero, validate_quantity is never called...
I've also tried :
to use model "clean" method but rest framework doesn't use it.
to disable min value validator in model by setting min_value to None, but it make rest framework to crash
to force MinValueValidator in model field : validators=[MinValueValidator(-math.inf, 'Minimum value is -Infinity')], it work, but it's too ugly
How can I do to have a serializer ensure non negative value in this case ?
I think your problem is that you are invoking the serializer.is_valid() method with no kwargs or raise_exception=False.
With raise_exception=True the serializer raises ValidationError, if you pass invalid data.
For better understanding, lets take a look at the Serializer.to_internal_value method.
def to_internal_value(self, data):
"""
Dict of native values <- Dict of primitive datatypes.
"""
if not isinstance(data, dict):
message = self.error_messages['invalid'].format(
datatype=type(data).__name__
)
raise ValidationError({
api_settings.NON_FIELD_ERRORS_KEY: [message]
})
ret = OrderedDict()
errors = OrderedDict()
fields = self._writable_fields
for field in fields:
validate_method = getattr(self, 'validate_' + field.field_name, None)
primitive_value = field.get_value(data)
try:
validated_value = field.run_validation(primitive_value)
if validate_method is not None:
validated_value = validate_method(validated_value)
except ValidationError as exc:
errors[field.field_name] = exc.detail
except DjangoValidationError as exc:
errors[field.field_name] = list(exc.messages)
except SkipField:
pass
else:
set_value(ret, field.source_attrs, validated_value)
if errors:
raise ValidationError(errors)
return ret
As you can see here, firstly, the serializer invokes the field.run_validation method, which uses django-fields validators and they raise DjangoValidationError exception and because of that, your validation method is never invoked.

How to convert cqlengine resultset objects into JSON format

I am writing an API which queries a Cassandra 2.1.2 based database and returns results in JSON format. I am using cqlengine for this.
Here is the simplified schema -
class Checkins(Model):
Model.__comment__ = "Table mapping for submit datastore"
changelist = columns.Integer (primary_key= True) # Changelist number
checkin_date = columns.DateTime() # Submit time
stream_name = columns.Ascii (primary_key= True) # Stream-name
creator = columns.Ascii () # Creator
My query is this
clobj = Checkins.objects(changelist=changelist).get()
How do I convert the resultset into a json format ?
You can create dictionaries from models as of cqlengine 0.12. From there you can use the json module to get a JSON format. You do have to be careful because datetimes are not json serializable. Therefore you will need to convert it to a string first (Or look at this question for other ways to fix the datetime serialization problem).
import json
clobj = Checkins.objects(changelist=changelist).get()
clobj_dict = dict(clobj_dict)
clobj_dict['checkin_date'] = str(clobj_dict['checkin_date'])
json_string = json.dumps(clobj_dict)
or you could add it as a property on the class
import json
class Checkins(Model):
# Define your model as before
# ...
#property
def json(self):
# Perform the same thing as before.
json_dict = dict(self)
json_dict['checkin_date'] = str(json_dict['checkin_date'])
return json.dumps(clobj_dict)
# Just call the property.
clobj = Checkins.objects(changelist=changelist).get()
json_string = clobj.json

How to save a set of things over and over (autosave)

I am creating a set of things (each thing has FK to the set) directly with forms. The problem I am having is with the view(s).
I want to create the set for the things and then update all the things over and over using AJAX (Kind of like autosave). In my case the set is a SurveySet and the thing is a Survey.
def screen_many(request):
if not request.is_ajax():
# get an ordered QuerySet of students
students = ids_to_students(request.GET.items())
e_students = ids_to_students(request.GET.items(), 'e')
i_students = ids_to_students(request.GET.items(), 'i')
survey_count = len(students)
# Build a dataset of students with there associated behavior types.
data = [{'student':s.pk, 'behavior_type': 'E'} for s in e_students]
data += [{'student':s.pk, 'behavior_type': 'I'} for s in i_students]
# Use that dataset as initial data for a formset
SurveyFormset = formset_factory(SurveyForm, extra=0)
survey_formset = SurveyFormset(initial=data)
# ... not shown: customizing the crispy form helper
# Make a new survey set...
ss = SurveySet()
ss.user=request.user
ss.save()
if request.is_ajax():
surveyset = get_object_or_404(SurveySet, pk=ss.pk)
surveys = surveyset.survey_set.all()
survey_formset = SurveyFormset(request.POST, instance=surveyset)
if survey_formset.is_valid():
# Create surveys for this surveyset
for form in survey_formset.forms:
saved = form.save(commit=False)
saved.surveyset = ss
saved.save()
HttpResponse('saved.')
formsetWithStudents = zip(survey_formset.forms, students)
c = {
'formsetWithStudents' : formsetWithStudents,
'students' : students,
'survey_count' : survey_count,
'e_students': e_students,
'i_students': i_students,
'survey_formset': survey_formset,
}
c.update(csrf(request))
return render_to_response("reports/screen_many.html", c)
If my URL looks like this: http://127.0.0.1:8000/screen_many/?e_1=13&e_2=12&i_1=14 The view makes 3 survey sets all the while complaining that there is an
UnboundLocalError at /screen_many/
local variable 'ss' referenced before assignment
I feel like I need to make a separate view just for the ajax and I want the SurveySet object to only be created once.
So, in other words. I am filling in forms of a formset which update after clicking "view next form" This is in my template.
$('.next').click(function(){
$(this).parent().hide()
$(this).parent().next().show()
var posting = $.post('/screen_many/', $('form').serializeArray() );
posting.done(function(response){
console.log(response)
});
Or I could send the POST data here:
def save_as_you_go(request):
if request.is_ajax():
# Get the surveyset from POST
ss = request.POST['form-0-surveyset']
surveyset = get_object_or_404(SurveySet, pk=ss)
surveys = surveyset.survey_set.all()
SurveyFormSet = inlineformset_factory(SurveySet, Survey, form=SurveyForm, can_delete=False, extra=0)
survey_formset = SurveyFormSet(request.POST, instance=surveyset)
if survey_formset.is_valid():
for form in survey_formset.forms:
student = form.save(commit=False)
student.surveyset = surveyset
student.save()
return HttpResponse('saved.')
else:
return HttpResponseRedirect('/')
But then I get
[u'ManagementForm data is missing or has been tampered with']
Forgive me if my answer seems naive--I am new to Python and Django, but it looks like you are setting the ss variable in the non-ajax request and then referencing it in the ajax request. Perhaps you can set ss prior to the if statements?
#set ss variable before if statements
ss = SurveySet()
ss.user=request.user
ss.save()
if not request.is_ajax():
###do your non-ajax request stuff
if request.is_ajax():
###do your ajax request stuff

Use JSON result in query using Ruby, Sinatra and PostgreSQL

I am using Ruby and the Plivo api to create a subaccount.
The code is:
AUTH_ID = "my_id"
AUTH_TOKEN = "my_token"
p = RestAPI.new(AUTH_ID, AUTH_TOKEN)
params = {'name' => 'thegreatone'}
response = p.create_subaccount(params)
// up to here is fine and (without my attempts below to access the json response) it works and the account is created.
The JSON response is :
[{"auth_token"=>"ZjgxMGQwMTY2NGY3Nzk3ZmM3ZGE3ZmIxMGQyZWYy",
"message"=>"created",
"api_id"=>"2c1eff4a-b955-11e2-8361-123141011ae6",
"auth_id"=>"SAMZBJOGZKZDIXMMEXNJ"}]
I would like to "extract" the "auth_token" and "auht_id" so that I can insert them into my database.
So I have tried (among other things):
obj = JSON.parse(response)
:user_key = obj['auth_token']
the message in my terminal is:
syntax error, unexpected '=', expecting $end
:user_key = obj['auth_token']
How can I extract these variables and then pass them to my insert query?
I am using postgres with SEQUEL, ruby and sinatra.
You're trying to assign a value to a symbol and the response returns an array:
obj = JSON.parse(response)
:user_key = obj['auth_token']
should be
obj = JSON.parse(response).first
user_key = obj['auth_token']
symbols are not variables, they are constants.
The response is an array containing the code response and then the data, so your code should be
obj = JSON.parse(response).last
user_key = obj['auth_token']
Edit: Turns out the gem already do the parse for you plivo.rb. So the code would be:
obj = response.last
user_key = obj['auth_token']

Django form query

I saw this piece of code and have few questions..If anyone could explain that would be really helpful.
views.py
def search_page(request):
pdb.set_trace()
form = SearchForm()
bookmarks = []
show_results = False
if 'query' in request.GET:
show_results = True
query = request.GET['query'].strip()
if query:
form = SearchForm({'query': query})
bookmarks = Bookmark.objects.filter(title__icontains=query)
variables = RequestContext(request,{'form': form,
'bookmarks': bookmarks,
'show_results': show_results,
'show_tags': True,
'show_user': True})
return render_t7tr o_response('search.html', variables)
form.py
class SearchForm(forms.Form):
query = forms.CharField(label=u'Enter a keyword to search for', widget=forms.TextInput(attrs={'size':32}))
How do the below line of code work?
If 'query' in request.GET
how the 'query' string is in the request.Get?..When I debugged the dictionary contains the value contains the search value I have given.
THe code works fine but I want to understand.
Containment testing on mappings checks the keys.
key in d
Return True if d has a key key, else False.
EDIT:
Django parses the query string and populates request.GET from it.

Resources