Getting values from Django model - django

I have an instance of a Django (1.6) model (let's take User for example). I would like to get the field values for that model, like I can do for a QuerySet, by calling QuerySet().values('first_name', 'username'). Is that possible, or should I just create a dictionary with the required fields?
Edit: A bit more insight into why I need this (maybe there are other workarounds). I want to return a Django model as a JSON response (by using json.dumps, not Django's JSON serializer), and so far, I can do that by extending the default Python JSON encoder, and treating Django models specially, by converting them to dictionaries using model_to_dict. The problem is that this doesn't get me the related objects, which I need.
Here's my code, for reference:
class JsonEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, models.Model):
return model_to_dict(obj) # here I'd like to pull some related values
return json.JSONEncoder.default(self, obj)

If you want to pull all related values by default, you can do the following:
def default(self, obj):
if isinstance(obj, models.Model):
d = model_to_dict(obj) # here I'd like to pull some related values
for field in obj._meta.fields:
if field.rel: # single related object
d[field.name] = model_to_dict(getattr(obj, field.name))
return json.JSONEncoder.default(self, obj)
This will go one level deep for single related objects, but not for many-to-many relations or reverse foreign keys. Both are possible, but you'll have to find out which methods/attributes on obj._meta return the specific fields.
If you only want to retrieve specific fields, you'll have to manually specify and fetch these fields.

Related

How can I pass dictionary in Django Rest Framework?

In django, I was able to pass data using dictionary. Like I set the objects in my dictionary and pass it in return render and call the object in frontend (return render(request, 'c.html', context) right? so How can I do this in django rest?
You may return Response in rest framework like this if you are using django rest framework.
context = {'key':'value'}
return Response(context)
Or if you are using a serializer then
return Response(serializer.data)
In Django REST Framework the concept of Serializing is to convert DB data to a datatype that can be used by javascript. Every serializer comes with some field that is going to be processed. For example, if you have a class with the name Employee and its fields as Employee_id, Employee_name, is_admin, etc. Then, you would need AutoField, CharField, and BooleanField for storing and manipulating data through Django. Similarly, serializer also works with the same principle and has fields that are used to create a serializer.
DictField is basically a dictionary field that validates the input against a dictionary of objects. It has the following arguments:
child and allow_empty like this>>>
field_name = serializers.DictField(*args, **kwargs)
for example document = DictField(child=CharField())
you can use serializer like below>>>
from rest_framework import serializer
class Any(object):
def __init__(self, dictonary):
self.dict = dictionary
class AnySerializer(serializers.Serializer):
dictionary = serializers.DictField(
child = serializers.CharField())
you can visit similar problem for understanding through the real problem.
And this link is the complete documentation of your problem. You can check this out.

How can I update two models in one serializer in Django Rest Framework?

I have a database schema that has each object of a certain type being stored across two separate tables (one row in each table, different data in each, with a foreign key from one to the other.)
Unfortunately, Django Rest Framework tends to assume that there is a one to one correspondence between serializers and models, which is not true of my case. How should I be approaching this? It seems like the serializer should return the representation of the object which will be the actual HTTP response of the ajax requests, so using two serializers doesn't seem right. I've looked at extending BaseSerializer (which is how I currently plan to implement this if I don't find better solutions), but certain methods take in an instance, which should contain all the data needed to serialize the object, whereas I have two instances relevant.
Any advice would be super appreciated! Thank you.
Writable nested representations section might help you.
You have 2 models ModelA and ModelB. Create your first model's serializer
class ModelASerializer(serializers.ModelSerializer):
class Meta:
model = ModelA
fields = ('fields',..) #
Then in other model's serializer add the first serializer and override the required methods (like create, update). Something like this:
class ModelBSerializer(serializers.ModelSerializer):
# add the serializer for the foreignkey model
model_a = ModelASerializer()
class Meta:
model = ModelB
fields = ('fields',..) #
def create(self, validated_data):
modela_data = validated_data.pop('model_a')
model_b = ModelB.objects.create(**validated_data)
ModelA.objects.create(model_b=model_b, **modela_data)
return model_b
# override update too ..

Passing a cursor to a Serializer in django-rest-framework?

I'm using Django 1.8 with django-rest-framework v3.2.2. I have a query that involves raw SQL:
#api_view(['GET'])
def total_spending(request, format=None):
code = request.query_params.get('code', None)
query = 'SELECT * FROM vw_presentation_summary WHERE code=%s"
cursor = connection.cursor()
cursor.execute(query, tuple([code]))
cursor.close()
My question is how to take this cursor and turn it into a data object that I can pass to django-rest-framework's Response.
Right now I'm doing it manually, which works OK:
def dictfetchall(cursor):
"Returns all rows from a cursor as a dict"
desc = cursor.description
return [
dict(zip([col[0] for col in desc], row))
for row in cursor.fetchall()
]
def total_spending(request, format=None):
...
return Response(dictfetchall(cursor))
But would it be better to use a Serializer somehow? I'm not clear if Serializers do anything useful other than define the fields you want to return.
Unless you're dealing with some complicated (including nested) representation of your model objects, a serializer is overkill if you're only going to use it for serializing objects. As you've already noticed, all of your fields can be natively serialized without any extra steps.
Serializers are great for shaping your output (renaming fields, grouping them with nested serializers) and doing it consistently. This is especially true when working with Django models, because Django doesn't natively serialize model objects down to Python dictionaries, it prefers the actual model object.
The power of a serializer comes in the deserialization, where it can map fields across models and build out relations for you. It can also do validation across all of these relations, which is something that would usually take a while to do manually.

django-tastypie custom serialization for fetching only one entry

I have a model with a custom json serializer that performs some processing prior to dumping to json.
Now, when fetching a single obj i want to use the custom serializer from the model to fetch the entire object (with the processing mentioned above). When fetching a list i want to use the default serializer to fetch only the headers (render only the model fields).
I looked into three options
overriding obj_get
def obj_get(self, bundle, **kwargs):
obj = ComplexModel.objects.get(pk=kwargs['pk'])
return obj.to_serializable()
i got thrown with
{"error": "The object LONG JSON DUMP has an empty attribute 'description' and doesn't allow a default or null value."}
not sure why this is happening - the field description is nullable, Plus - why tastypie is checking validation for objects already in the database, and... while fetching ??
using dehydrate
def dehydrate(self, bundle):
return bundle.obj.to_serializable()
This is great but the cycle is executed before each object - so i cann't tell if I'm fetching a list or a single object. The result here is the full serizliazed objects whether it's a list or a single entry.
creating a custom serializer
class CustomComplexSerializer(Serializer):
def to_json(self, data, options=None):
if isinstance(data,ComplexModel):
data = data.to_serializable()
return super(CustomComplexSerializer,self).to_json(data)
Same problem here, when fetching one entry the serializer accepts the obj in data.obj, when it's fetching a list it accepts a dict (odd...). I can check if bundle is an instance of dict as well - but testing for the type of ComplexModel felt awkward enough.
So what is the best way to implement a custom serialization for fetching only a single entry ?
Just for future reference, I think i found the right way to do this and it's by using full_dehydrate.
def full_dehydrate(self, bundle, for_list=False):
if not for_list:
return bundle.obj.to_serializable()
return super(ReportResource,self).full_dehydrate(bundle,for_list)

Django Rest Framework Dictionary Field

I'm using Mongodb with mongoengine as a backend for a API in Django.
The framework I'm using to create the api is Django Rest Framework.
I need to store a dictionary in a field in Mongo and the best I've done when the method post is called is to use a charfield and parse the dictionary in the function restore_object.
There is a better way to achieve this goal?
It's better to create a dict field? I don't know how hard this could be.
Thank you.
edited to show some code, notice that I store the dictionary as a dict (DictField) and it's content could change from one object to other.
my mongoengine model is something like:
class MyDoc(mongoengine.Document):
name = mongoengine.StringField(max_length=200)
context = mongoengine.DictField()
and my serializer something like:
class MyDocSerializer(serializers.Serializer):
name = serializers.CharField(max_length=200)
context = serializers.CharField()
url = serializers.HyperlinkedIdentityField(
view_name="drf:mydoc-detail",)
def __init__(self,*args,**kwargs):
super(MyDocSerializer,self).__init__(*args,**kwargs)
def restore_object(self, attrs, instance=None):
# Parse string to dict
# this is so ugly, notice I had to repace ' for " to
# avoid an error parsing the json
context = JSONParser().parse(
StringIO.StringIO(
attrs['context'].replace("'","\"")
)
)
attrs['context'] = context
if instance is not None:
instance.name = attrs['name']
instance.context = context
return instance
return MyDoc(**attrs)
Rather than deal with the dictionary field in the Serializer's restore_object, you'll probably end up with something slightly cleaner, if instead you use a custom field for the dictionary field, that manages converting between the dictionary representation and internal char based storage.
You'll want to subclass serializers.WritableField and override the to_native() and from_native methods.
Relevant docs here.
Note: WritableField class that was present in version 2.x no longer exists. You should subclass Field and override to_internal_value() if the field supports data input.
Update: As of 3.0.4 you can now use serializers.DictField... http://www.django-rest-framework.org/api-guide/fields/#dictfield