Wednesday, 24 January 2024

python vars, isinstance, object vs dict, django convert model to dict

 https://www.w3schools.com/python/ref_func_isinstance.asp


isinstance is best to see if an object is a class 


x = isinstance(myObj, myclass)



vars can covert object to dict but not if the object is instance of class

https://stackoverflow.com/questions/61517/python-dictionary-from-an-objects-fields

vars(x)


If object is instnace of class for example django model class or some class

you can use django framework method or python method below

https://stackoverflow.com/questions/21925671/convert-django-model-object-to-dict-with-all-of-the-fields-intact


1. instance.__dict__

instance.__dict__

which returns

{'_foreign_key_cache': <OtherModel: OtherModel object>,
 '_state': <django.db.models.base.ModelState at 0x7ff0993f6908>,
 'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
 'foreign_key_id': 2,
 'id': 1,
 'normal_value': 1,
 'readonly_value': 2}

This is by far the simplest, but is missing many_to_manyforeign_key is misnamed, and it has two unwanted extra things in it.


2. model_to_dict

from django.forms.models import model_to_dict
model_to_dict(instance)

which returns

{'foreign_key': 2,
 'id': 1,
 'many_to_many': [<OtherModel: OtherModel object>],
 'normal_value': 1}

This is the only one with many_to_many, but is missing the uneditable fields.


3. model_to_dict(..., fields=...)

from django.forms.models import model_to_dict
model_to_dict(instance, fields=[field.name for field in instance._meta.fields])

which returns

{'foreign_key': 2, 'id': 1, 'normal_value': 1}

This is strictly worse than the standard model_to_dict invocation.


4. query_set.values()

SomeModel.objects.filter(id=instance.id).values()[0]

which returns

{'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
 'foreign_key_id': 2,
 'id': 1,
 'normal_value': 1,
 'readonly_value': 2}

This is the same output as instance.__dict__ but without the extra fields. foreign_key_id is still wrong and many_to_many is still missing.


5. Custom Function

The code for django's model_to_dict had most of the answer. It explicitly removed non-editable fields, so removing that check and getting the ids of foreign keys for many to many fields results in the following code which behaves as desired:

from itertools import chain

def to_dict(instance):
    opts = instance._meta
    data = {}
    for f in chain(opts.concrete_fields, opts.private_fields):
        data[f.name] = f.value_from_object(instance)
    for f in opts.many_to_many:
        data[f.name] = [i.id for i in f.value_from_object(instance)]
    return data

While this is the most complicated option, calling to_dict(instance) gives us exactly the desired result:

{'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
 'foreign_key': 2,
 'id': 1,
 'many_to_many': [2],
 'normal_value': 1,
 'readonly_value': 2}

6. Use Serializers

Django Rest Framework's ModelSerializer allows you to build a serializer automatically from a model.

from rest_framework import serializers
class SomeModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = SomeModel
        fields = "__all__"

SomeModelSerializer(instance).data

returns

{'auto_now_add': '2018-12-20T21:34:29.494827Z',
 'foreign_key': 2,
 'id': 1,
 'many_to_many': [2],
 'normal_value': 1,
 'readonly_value': 2}

difference between object and dict
https://www.quora.com/What-is-the-difference-between-a-dictionary-and-an-object-in-Python#:~:text=%C2%B7%204y-,Objects%20are%20more%20general%20than%20dictionaries.,these%20variables%20can%20be%20anything.

In Python, a dictionary and an object are both types of data structures, but they serve different purposes.

A dictionary is a built-in data type that stores key-value pairs. The keys are unique and immutable, while the values can be of any data type. Dictionaries are commonly used for mapping and accessing data based on keys.

On the other hand, an object in Python is an instance of a class. Classes are used to create user-defined data types, and objects are instances of these data types. Objects can have attributes (variables) and methods (functions) associated with them, allowing for more complex data structures and behaviors.

In summary, a dictionary is a built-in data structure for storing key-value pairs, while an object is an instance of a user-defined data type with attributes and methods.



!!remeber in python dict is instance of objec too :


dict instances are objects too. But their keys are just not exposed as as attributes.


https://stackoverflow.com/questions/17761202/is-python-dict-an-object


No comments:

Post a Comment