How to access inital data in django rest framework serializer - python

I would like to auto populate some fields in a Serializer (Not a ModelSerializer)
I need a method I can hook into, that gives me both access to the data passed in, and the ability to manipulate which fields are shown dynamically (but I can see how to do that from the example in the docs)
Essentially, how can I access and manipulate the data that has been passed into the Serializer at it's initialisation.
http://www.django-rest-framework.org/api-guide/serializers/#example

I believe the method you are looking for is .to_internal_value.

Related

How can I load data variables that accessible to all views but get initialised after data available in database?

I'm creating API with Django rest framework. I've one table which will be used as types for the products. Another table which will map that types with the product. consider it as producttypesmapping table. So, I'm creating product type update endpoint. which will only update the producttypesmapping.
The issue is I've used ChoiceField() in the serializer. So I need the tuple of tuples variable to prevent from storing unwanted values. which will be initialized in util.py and to make it dynamic it loads directly by querying the producttypes table. So, I only have to query the data only once.
TAG_CHOICES_TYPE_ONE = []
tags = ProductTypes.objects.filter(tag_type_id=1).values('id', 'value')
for index, item in enumerate(tags):
TAG_CHOICES_TYPE_ONE.append((item["id"], item["value"]))
TAG_CHOICES_TYPE_ONE = tuple(TAG_CHOICES_TYPE_ONE)
But the problem is utils.py executed before the even the producttypes initialized with any data.
First of all, unless you want to attach some additional data about the mapping, your mapping model shouldn't be necessary. Simply use a ForeignKey or a ManyToManyField.
Then, you should consider using a PrimaryKeyRelatedField instead of a ChoiceField. This field takes a queryset as an argument, which will help you limit your choices. If you chose a ChoiceField to be able to get a nice display in the browsable API, you can achieve the same by creating a string representation for your model.

How to know which field is saved when only() has been used in Django?

I am using Django 1.11, in one of my models I have added actions when the model is saved.
However I don't want these actions to be done when only a part of the model is saved.
I know that update_fields=('some_field',) can be used to specify which field must be saved.
But, when the object has been fetched in the database using the methods only() or defer() I don't see any information about the fields updated in the save() method, update_fields is empty.
Thus my question: How can I get the fields saved by Django when only some fields have been fetched ?
When you use defer or only to load an instance, the get_deferred_fields() method returns a list of field names that have not been loaded; you should be able to use this to work out which ones will be saved.

Django-rest-framework: Validate a ListSerializer

I receive a number of similar objects as an input for my API, and I deserialize them using my own serializer with the parameter many=True like this:
serializer = MySerializer(data=request.data, many=True)
The serializer is an instance of ListSerializer.
Then I need to make sure that there are certain combinations of objects in that list. However, I don't seem to find a way to write a .validate() method on the ListSerializer of replace it by my own ListSerializer implementation.
Is there a way to do this validation in the serializer, or do I have to iterate over the deserialized objects and check them?
The Django REST frameworks documentation has a section on customizing ListSerializer behavior.
This entails creating a custom subclass of ListSerializer. You would probably want to create some custom validation in your subclass.

Django pre-save signal

I have a pre-save signal for one of my models. This pre-save signal does some background API activity to syndicate new and updated objects to service providers and return meaningless data for us to store as references in the places of the original data.
The new and update methods are different in the API.
Ideally, if a user were to perform an update they would be clearing the meaningless data from a field and typing over it. My signal would need to know which fields were updated to send changes for just those fields, as sending all fields in an update would send meaningless references as the raw data in addition to the updates.
The pre-save signal has the argument update_fields. I searched for some details and found that this argument may include all fields when an update is performed.
Regarding update_fields as the docs have little information on this
When creating an object, does anything get passed to update_fields?
When updating an object, do all fields get passed to update_fields, or just the ones that were updated?
Is there some other suggestions on how to tackle this? I know post_save has the created argument, but I'd prefer to operate on the data before it's saved.
When creating an object, does anything get passed to update_fields?
No.
When updating an object, do all fields get passed to update_fields, or just the ones that were updated?
Depends who is calling the save() method. By default, Django doesn't set update_fields. Unless your code calls save() with the update_fields argument set, it will rewrite all the fields in the database and the pre_save signal will see update_fields=None.
My signal would need to know which fields were updated to send changes for just those fields.
Unless you are controlling what calls the save() method on the object, you will not get this information using update_fields. The purpose of that argument is not to let you track which fields have changed - rather it is to facilitate efficient writing of data when you know that only certain columns in the database need to be written.

Where to store field data and how to provide access to it?

Forms have Fields, Fields have a value. However, they only get a value after the form has been submitted.
How should I store this value? Should I give every field a value attribute, field.value,
leave it as None prior to posting, and fill it in afterwords?
Omit it completely, and dynamically add it?
Store it on the form instead, like form.data['field'].
Create a a wrapper class FieldWithData to avoid any inconsistent states (if you have an object of this type, you know it has data) and allows me to set the data in the initializer rather than accessing attributes directly (although I guess this isn't so different from using a setter)
How should I provide access to the field data through the Form object? Options:
form.fields['name'].value (how it's presently being stored internally)
form.data['field'] (create a proxy "data" class that retrieves the real data off the field, or re-arrange the internals to actually store the data like this)
form.field.value - looks fairly nice, but then I'd have two references to the same field, one as form.field and one as form.fields['field'] which I need internally so that I can iterate over them
Too many design decisions. Driving me nuts. This is what sucks about solo'ing a project.
It really depends on how you interact with the structures in question. Do you manipulate Form and Field objects prior to assigning them values? Do you need to frequently iterate over all the given Fields? Do you need Form once it's been submitted? Etc.
I'd suggest writing some/all of the code that uses Form and figure out how you want to interact with Form data, and what your ideal interface would look like.
I would keep a form's definition and the form's values from submission separate. I.e. I would not have a value attribute on the Field(Definition) objects.
To work with submitted values, I would probably use a dict. You could let the Form class handle the creation of this dict:
# assuming my_form is a Form object and request represents the HTTP request
form_values = my_form.values_from_request(request)
print(form_values["Name"])
The values_from_request method would iterate through the Form's Field(Definition)s to get the submitted data from the HTTP request. The method could also do stuff like validation and data type conversion.

Categories

Resources