How to take a dictionary and send a JSON Response - python

I have the following function,
def facebooktest(request):
fb_value = ast.literal_eval(request.body)
fb_foodies = Foodie.objects.filter(facebook_id__in = fb_value.values())
for fb_foodie in fb_foodies:
state = request.user.relationships.following().filter(username = fb_foodie.user.username).exists()
userData = {
'fbid': fb_foodie.facebook_id,
'followState': int(state),
}
Basically I am checking to see which of the user's facebook friends are on my django app. If they are, return the followState. The followState basically returns a 1 or a 0. 1 if the user is already following them on my Django app and 0 if they are not following their facebook friend on my Django app.
I would like to return back a json type dictionary to that user that looks like this:
[{fbid:222222222222, followState: 0}, {fbid:111111111111, followState: 1}, {fbid:435433434534, followState:1}]
EDIT
I have the dictionary structure but I just want to return it like the structure above.

def facebooktest(request):
fb_value = ast.literal_eval(request.body)
fb_foodies = Foodie.objects.filter(facebook_id__in = fb_value.values())
response = []
for fb_foodie in fb_foodies:
state = request.user.relationships.following().filter(username = fb_foodie.user.username).exists()
userData = {
'fbid': fb_foodie.facebook_id,
'followState': int(state),
}
response.append(userData)
return json.dumps(response)

There is a function in the django.forms.models package for that: model_to_dict
from django.forms.models import model_to_dict
model_to_dict(your_model, fields=[], exclude=[])
From the help:
model_to_dict(instance, fields=None, exclude=None)
Returns a dict containing the data in ``instance`` suitable for passing as
a Form's ``initial`` keyword argument.
``fields`` is an optional list of field names. If provided, only the named
fields will be included in the returned dict.
``exclude`` is an optional list of field names. If provided, the named
fields will be excluded from the returned dict, even if they are listed in
the ``fields`` argument.

I think you're looking for this:
return HttpResponse(simplejson.dumps(response_dict), mimetype='application/json')
where 'response_dict' would be your dictionary.

Related

Dynamically pass arguments to objects.filter

I am pretty new to Django and I am trying to get a query set from a filter function. This filter function is supposed to be able to take 1 to 5 arguments and I am not sure how to handle that.
I have not found anything here that might help me, so if you do know of some other question that might help please let me know.
views.py:
#api_view(('Get',))
def update(request, REQUEST):
if request.method == "Get":
requestlist = REQUEST.split('&')
for keys in requestlist:
if 'module' in keys:
module = keys[8:]
if 'value' in keys:
value = keys[6:]
if 'user' in keys:
user= keys[5:]
if 'time1' in keys:
time1 = keys[6:]
if 'time2' in keys:
time2 = keys[6:]
item = Post.objects.filter(name=Name, user=USER, ...)
The full request string will look like name=NAME&value=VALUE&user=USER&time1=FIRSTTIME&time2=SECONDTIME but it could also be any combination of the individual variables like name&time1.
Now I want to be able to do that with one filter method instead of creating like 2^5 for each different szenario.
The full request string will look like name=NAME&value=VALUE&user=USER&time1=FIRSTTIME&time2=SECONDTIME.
This is a query string [wiki], and Django automatically parses this to a dictionary-like QueryDict, you thus should not specify this yourself. You can work with:
if request.method == 'GET':
Post.objects.filter(**request.GET.dict())
I would however advise to only allow specific keys, and thus not all keys, since then the database is less secure: one can use the filtering mechanism to retrieve data.
It thus might be better to work with:
datas = {}
accept_keys = {'module', 'value', 'user', 'time1', 'time2'}
for key, value in request.GET.dict().items():
if key in accept_keys:
datas[key] = value
if request.method == 'GET':
Post.objects.filter(**datas)
In that case the item after the path is the query string, and the separator between the path and the query string is a question mark (?).
The path thus looks like:
urlpatterns = [
# …,
path('some/path/', views.update, name='update'),
# …
]
and you thus query the path with some.host.com/some/path?name=NAME&value=VALUE&user=USER&time1=FIRSTTIME&time2=SECONDTIME.

How to pass multiple key-value pairs as query parameter in Python Django?

I am building a key-value store REST API that will store data in a key value pair. Suppose I want to create an endpoint where I can make a GET request to values/ to get one or more values by passing one or more keys just like this:
/values?keys=key1,key2,key3
I want to know what should I do in urls.py if I want to do this variable length query.
This is my model:
class Data(models.Model):
key = models.CharField(max_length = 100)
value = models.CharField(max_length = 1000)
def __str__(self):
return '{}:{}'.format(self.key, self.value)
You don't need do anything in your url.py. You just need get your query param (in your case it is keys) in your view.py and you can do this like below:
def your_view(request):
keys = request.query_params.get('keys')

How to dynamically modify database request in Django?

I've got a problem with my code. I need to get an instance of a model that looks like this:
class Example(models.Model):
# ...
foo = models.JSONField(default={})
and depending on the user's input (JSON key). For example:
Example.objects.filter(foo__userinput = bar)
How can I manage to don't make JSON key hardcoded?
You can try filter by dict
key = 'foo__%s' % userinput
qfilter = {key: bar}
Example.objects.filter(**qfilter)

Quickbase module add_record() function—file upload parameters?

The code below is part of the Python Quickbase module which has not been updated in quite a while. The help text for one of the function shown below is not clear on how to pass the parameters to upload a file (the value of which is actually base64 encoded).
def add_record(self, fields, named=False, database=None, ignore_error=True, uploads=None):
"""Add new record. "fields" is a dict of name:value pairs
(if named is True) or fid:value pairs (if named is False). Return the new records RID
"""
request = {}
if ignore_error:
request['ignoreError'] = '1'
attr = 'name' if named else 'fid'
request['field'] = []
for field, value in fields.iteritems():
request_field = ({attr: to_xml_name(field) if named else field}, value)
request['field'].append(request_field)
if uploads:
for upload in uploads:
request_field = (
{attr: (to_xml_name(upload['field']) if named else upload['field']),
'filename': upload['filename']}, upload['value'])
request['field'].append(request_field)
response = self.request('AddRecord', database or self.database, request, required=['rid'])
return int(response['rid'])
Can someone help me in how I should pass the parameters to add a record.
Based on the definition you provided, it appears that you you need to pass an array of dictionaries that each provide the field name/id, filename, and the base64 encoding of the file for the uploads parameter. So, if I had a table where I record the name of a color to the field named "color" with the field id of 19 and a sample image to the field named "sample image" with the field id of 21, I believe my method call would be something like:
my_color_file = #base64 encoding of your file
my_fields = {'19': 'Seafoam Green'}
my_uploads = [{'field': 21, 'filename':'seafoam_green.png', 'value': my_color_file}]
client.add_record(fields=my_fields, uploads=my_uploads)
Or, if you're using field names:
my_color_file = #base64 encoding of your file
my_fields = {'color': 'Seafoam Green'}
my_uploads = [{'field': 'sample_image', 'filename':'seafoam_green.png', 'value': my_color_file}]
client.add_record(fields=my_fields, named=True, uploads=my_uploads)
client is just the object you instantiated earlier using whatever constructor this module has.

iterate over django form results (not in a template)

I am trying to iterate over form results and I can't help but think that I am re-inventing the wheel here.
filterlist = []
if request.POST:
form = FilterForm(request.POST)
if form.is_valid():
for key, value in form.cleaned_data.iteritems():
filterlist.append(key)
filterlist.append(value)
This works, but seems very awkward and creates lots of other problems. For example the values come back with u' so I have to use value.encode("utf8") but then if a value is None it throws in error. So now I have to check if it is None, if not then encode. There has to be a better way.
EDIT: What I am trying to do.
I am trying to filter what is shown on a page. The problem I am running into is that if a value is empty (the user don't fill the box because they only want to filter against one object) then I get no results. For example a user wants to search for all books by the author name "Smith" but doesn't want to search against a genre.
results = Books.objects.filter(author=author, genre=genre)
The user would get no results because this is an AND search. But, if a user put in "Smith" for the author and "mystery" for the genre then it works exactly like I want it to, only giving results where both are true.
So, I am trying to eliminate the empty stuff by iterating over the form results. Like I said I am probably re-inventing the wheel here.
In Python 3 use:
for key, value in form.cleaned_data.items():
If the field names are the same in the model and the form, try this:
filter = {}
if request.method == 'POST':
form = FilterForm(request.POST)
if form.is_valid():
for key, value in form.cleaned_data.iteritems():
if value:
filter[key] = value
results = Books.objects.filter(**filter)
Python is one of the few languages having named parameters. You can assemble a dict with the non-empty form fields and pass it to the filter method using the kwargs unpacking operator **.
For example:
kwargs = {"author": "Freud"}
results = Books.objects.filter(**kwargs)
Is the same as:
results = Books.objects.filter(author="Freud")
I think the problem is that by default the Model form is not valid if a form field does not have a value entered by the user, if you don`t require the field every time from the user you need to set the required field to false in the ModelForm class in forms.py as shown in the code below. Remember that the field is set false only in the model form not in the model itself
class myForm(forms.ModelForm):
myfield_id = forms.CharField(required=False)
myfield_foo = forms.CharField(required=False)
myfield_bar = forms.CharField(required=False)
myfield_name = forms.CharField(required=False)
class Meta:
model = myModel
exclude = ('myfield_ex','myfield_file')
fields = ['myfield_id','myfield_foo','myfield_bar','myfield_name',]
After you have the form entered by the user what you need is use the Q object which can be used to create complex queries as described in the manula page here
https://docs.djangoproject.com/en/1.7/topics/db/queries/#complex-lookups-with-q
A simple example code would look like
if form.is_valid():
qgroup = []
for key,value in form.cleaned_data.iteritems():
if value:
q_name = Q(**{"%s"%format(filterKey[key]) : value})
qgroup.append(q_name)
q = None
# can use the reduce as shown here qgroup = reduce(operator.or_, (Q(**{"{0}".format(filterKey[key]): value}) for (key,value) in form.cleaned_data.iteritems()))
for key,value in form.cleaned_data.iteritems():
if value:
q_name = Q(**{"%s"%format(filterKey[key]) : value})
qgroup.append(q_name)
for x in qgroup:
q &= x ### Or use the OR operator or
if q:
resultL = myModel.objects.filter(q).select_related()
The filterKey can look something on the lines of
filterKey = {'myfield_id' : "myfield_id",
'myfield_foo' : "myfield_foo__icontains",
'myfield_bar' : "myfield_bar__relative_field__icontains",
}

Categories

Resources