Django Json Field - Find objects hat do not have key - python

I have a Model with a JSON Field.
data = JSONField(default=dict)
Is there an efficient way - or queryset filter - to find all instances of this Model that do not have a speicfic key in the json field.
Django documentation includes has_key function for JSON field.
Essentially i'm looking for a way to do not_has_key
My current method:
queryset = MyObj.objects.all()
for obj in queryset:
if 'my_key' not in obj.data:
do_work()
else:
pass
#key_already_exists
Many thanks

Related

Django: Get list of model object fields depending on their type?

Listing fields of models and their objects has been answered successfully here. But i want a generalized way of processing on object fields depending on their types, so that i can serialize them manually in dictionary. e.g: ManyToMany,OneToMany...,FileField,...,Relations_field(Field not present in the model but defined as foreign key in some other model).
I don't know how much of a reasonable demand it is to manually serialize your model objects, but my purposes are more pedagogical than performance oriented.
This is a small function where i am converting model objects to JSON serializable dictionaries.
def obj_to_dict(obj):
fields = obj._meta.get_fields()
obj_dict = {}
# Here I want to process fields depending upon their type:
for field in fields:
if field is a relation:
## DO SOMETHING
elif Field is ManyToMany or OneToMany ... :
## DO SOMETHING
elif field is image field:
## DO SOMETHING
else:
## DO SOMETHING
return obj_dict
The answer here, does give a way but not quite what i want, way for more generalization depending upon fields.
Short Answer: get_internal_type() method is exactly what is required here. It returns a string of Field Type, e.g: "FileField".
Caveat: Reverse relations not locally defined in a model and fields defined as a foreign key to some other model, both are returned as "ForeignKey" with this method.
Detailed:
To process over fields you may need to access the field value,you can do so in all cases through getattr(model_object,field.name) inside the loop.
To differentiate between reverse relations and foreign key you can use auto_created property. As ReverseRelations return True on auto_created property and ForeignKey field don't.
ImageField is just a file field, but it has properties such as width,height,url etc. so it can be checked through getattr(obj,field.name).width property.
You can iterate over the fields as:
def obj_to_dict(obj):
fields = obj._meta.get_fields()
obj_dict = {}
# Here I want to process fields depending upon their type:
for field in fields:
field_val = getattr(obj,field.name)
if field.get_internal_type()=="ForeignKey" and not field.auto_created:
## for foreign key defined in model class
elif field.get_internal_type()=="ForeignKey" and field.auto_created:
## for reverse relations not actually defined in model class.
elif field.get_internal_type()=="ManyToMany"/ "OneToMany" ... :
DO SOMETHING
# for image field
elif field.get_internal_type() == "FileField" and field_val.width:
## DO SOMETHING
else:(for other locally defined fields not requiring special treatment)
## DO SOMETHING
return obj_dict

Filter Django ResourceRelatedField's queryset

In our project we are using ResourceRelatedField for a foreign key field in one of our serializers to comply with JSON:API format. This is how it looks:
types = ResourceRelatedField(
queryset=Type.objects,
many=True
)
The problem that I have is that I want to exclude some of the items from the queryset of this field so that I don't get all the items from the Type model, but a subset.
If I write something like this it doesn't work:
types = ResourceRelatedField(
queryset=Type.objects.exclude(id=13),
many=True
)
Didn't find anything related in the documentation.
Perhaps You can use a SerializerMethodResourceRelatedField? (not tested).
types = SerializerMethodResourceRelatedField(many=True)
def get_types(self, obj):
return Type.objects.exclude(id=13)

Add a virtual field to a django query

I want to add an extra field to a query set in Django.
The field does not exist in the model but I want to add it to the query set.
Basically I want to add an extra field called "upcoming" which should return "True"
I already tried adding a #property method to my model class. This does not work because apparently django queries access the DB directly.
models.py
class upcomingActivity(models.Model):
title = models.CharField (max_length=150)
address = models.CharField (max_length=150)
Views.py
def get(self, request):
query = upcomingActivity.objects.all()
feature_collection = serialize('geojson', query ,
geometry_field='location',
fields= ( 'upcoming','title','address','pk' )
)
This answer is for the case that you do not want to add a virtual property to the model (the model remains as is).
To add an additional field to the queryset result objects:
from django.db.models import BooleanField, Value
upcomingActivity.objects.annotate(upcoming=Value(True, output_field=BooleanField())).all()
Each object in the resulting queryset will have the attribute upcoming with the boolean value True.
(Performance should be nice because this is easy work for the DB, and Django/Python does not need to do much additional work.)
EDIT after comment by Juan Carlos:
The Django serializer is for serializing model objects and thus will not serialize any non-model fields by default (because basically, the serializer in this case is for loading/dumping DB data).
See https://docs.djangoproject.com/en/2.2/topics/serialization/
Django’s serialization framework provides a mechanism for “translating” Django models into other formats.
See also: Django - How can you include annotated results in a serialized QuerySet?
From my own experience:
In most cases, we are using json.dumps for serialization in views and this works like a charm. You can prepare the data very flexibly for whatever needs arize, either by annotations or by processing the data (list comprehension etc.) before dumping it via json.
Another possibility in your situation could be to customize the serializer or the input to the serializer after fetching the data from the DB.
You can use a class function to return the upcoming value like this:
def upcoming(self):
is_upcoming = # some logic query or just basically set it to true.
return is_upcoming
then call it normally in your serializer the way you did it.
fields= ( 'upcoming','title','address','pk' )

Django: How to serialize QuerySet into object instead of array?

I want to serialize a QuerySet into a JSON object instead of JSON array.
For model Day, the serialized QuerySet should be an object with Day.date keys and serialized Days as values.
class DaySerializer(serializers.ModelSerializer):
class Meta:
model = Day
exclude = []
This returns an array of serialized objects:
DaySerializer(Day.objects.all(),many=True).data
{'15.02.2005':{...},
'16.02.2005':{...},
...
}
I'm curious if there is some DRF way to do that.
AFAIK there is not an out-of-the-box way of doing that, but you can override .to_representation() and .to_internal_value() methods of the serializer to achieve that.
These methods enable you to alter how both serialization and de-serialization is done.
See here for details.

Convert Django queryset to dictionnary in a JSON serialization purpose

I'm creating an API and I need to return data in a dictionnary format sothat it can be serialized (by the API mechanism).
The code that currently works is something as simple as:
def mymethod(self):
queryset1 = MyClass.objects.get(...) # Ccontains 1 object, easy to deal with
queryset2 = OtherClass.objects.filter(...) # Contains N objects, hard to deal with !
return {
'qs1_result': queryset1.some_attribute # This works well
}
Returning data from queryset1 is easy because there is 1 object. I just pick the attribute I need and it works. Now let's say that in addition, I want to return data from queryset2, where there are many objects, and that I don't need every attributes of the object.
How would you do that?
I repeat that I do NOT need to make the serialization myself. I just need to return structured data sothat the serialization can be made.
Thanks a lot.
From the Django docs: https://docs.djangoproject.com/en/dev/topics/serialization/#subset-of-fields
Subset of fields
If you only want a subset of fields to be serialized, you can specify a fields argument to the serializer:
from django.core import serializers
data = serializers.serialize('json', SomeModel.objects.all(), fields=('name','size'))
In this example, only the name and size attributes of each model will be serialized.

Categories