Django REST framework export to json - json

So I'm new to Django REST framework I used it on an app called Myana EDMS. I want to export all the data from the API to the CSV file so I can upload it to Wordpress.
The GET looks like this http://X.X.X.X/api/documents/37/metadata/ I have around 6000 documents and I want them all in one json file.

Create a serializer specifying all the fields you need, then setup a ListView and the corresponding URL, then visit the URL and you should have your JSON. e.g.
# serializers.py
class DocumentSerializer(ModelSerializer):
class Meta:
model = Document
fields = ('field1', 'field2') # etc. for all fields
# views.py
class DocumentListView(ListAPIView):
queryset = Document.objects.all() # or whatever queryset has your 6,000 documents
serializer = DocumentSerializer(queryset, many=True)

Related

Django rest api csv to json

I would like to create a django rest api that receives a csv file and then response the file in a json format. How do I achieve this without using models and anything related with databases? I don't want to use a database because it's assumed that the csv files will have different structure every time
This is my first django project and I've seen lots of tutorials, even I did the first tutorial from django website but I can't understand how to do this task without the database.
Thanks!
since you have not tried anything on your own Here is how you can do it
views.py
from rest_franework.generics import CreateAPIView
class ReadCSVView(CreateAPIView):
# permission_classes = [IsAuthenticated]
serializer_class = ReadCSVSerializer
queryset = ''
def perform_create(self, serializer):
file = serializer.validated_data['file']
decoded_file = file.read().decode()
io_string = io.StringIO(decoded_file)
reader = csv.reader(io_string)
next(reader) # incase you want to skip first row else remove this
return reader
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
final_data = []
for row in self.perform_create(serializer):
if row[0]=="jack":
#do your logic here
final_data.append(row)
return Response(final_data, status=status.HTTP_201_CREATED)
just create one serializers to read csv.
serializers.py
from rest_framework import serializers
class ReadCSVSerializer(serializers.Serializer):
file = serializers.FileField()
now go to your urls.py and call the view class this way
urlpatterns = [
path("read-csv",views.ReadCSVView.as_view(),name="csv")]
hope this clarifies your doubt

DRF: can you deserialize one JSON key:value pair into multiple fields

In my API I have a module, which collects JSON objects obtained via POST request. JSON objects I'm receiving look more or less like this:
{
"id": "bec7426d-c5c3-4341-9df2-a0b2c54ab8da",
"data": {
"temperature": -2.4,
// some other stuff is here as well ...
}
}
The problem is requirement that I have to save both: records from data dictionary and whole data dictionary as a JSONField. My ORM model looks like this:
class Report(BaseModel):
id = models.BigAutoField(primary_key=True)
data = JSONField(verbose_name=_("Data"), encoder=DjangoJSONEncoder, blank=True, null=True)
temperature = models.DecimalField(
max_digits=3,
decimal_places=1,
)
# other properties
Is there any neat way to get both properties in one attempt to deserialize JSON object? Currently I use nested serializers formed like this:
class DataSerializer(serializers.ModelSerializer):
temperature = serializers.DecimalField(
source="temperature", write_only=True, max_digits=3, decimal_places=1
)
class Meta:
model = Report
fields = ("temperature")
class ReportSerializer(serializers.ModelSerializer):
id = serializers.UUIDField(source="uuid", read_only=True)
data = DataSerializer(source="*")
class Meta:
model = Report
fields = ("id", "data")
which obviously does not pass whole data dictionary to validated_data, which means I have to update the JSON field elsewhere (not good since I would like to have both data and temperature at null=False in ORM model). Any good ideas on how to fix this using DRF serializers would be appreciated.
I believe you should be able to override validate method for your serializer where you can "store initial data JSON field" and do the default validation by calling super()... method.
More info https://www.django-rest-framework.org/api-guide/serializers/#validation
Also, there are object-level validation functions available, you can take a look there as well for the initial posted data
https://www.django-rest-framework.org/api-guide/serializers/#object-level-validation
Also, you can override the method run_validation to access the initially passed data object.

Why json parsing serializer is not working for nested json in Django Rest Framework?

I am implementing json API using Django Rest Framework.
Since sqlite is being used for database, json data is stored as string and when the data is requested, serializer parse the string and convert into json and sent to client side. This implementation worked for simple json file as shown in left picture. However, this cannot work for nested json as shown right picture.
Can anyone tell me how I should revise serializer in order to work for nested json also?
serializer.py
class strToJson(serializers.CharField):
def to_representation(self,value):
x=JSON.loads(value)
return x
class summarySerializer(serializers.ModelSerializer):
project=serializers.CharField(read_only=True,source="html.project")
version = serializers.CharField(read_only=True, source="html.version")
id = serializers.IntegerField(read_only=True, source="html.pk")
json = strToJson()
class Meta:
model=summary
fields=('id','project','version','json')
model.py
class summary(models.Model):
html = models.ForeignKey(html, on_delete=models.CASCADE,related_name='summaries')
keyword = models.CharField(max_length=50, default='test')
json = models.TextField(default='test')

Difference between JSONParser and JSONRenderer

I was going through django rest framework tutorial on serialization in which I got stuck at JSONRenderers and JSONParsers.Below is the code mentioned there:
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from django.utils.six import BytesIO
snippet = Snippet(code='foo = "bar"\n')
snippet.save()
snippet = Snippet(code='print "hello, world"\n')
snippet.save()
serializer = SnippetSerializer(snippet)
serializer.data
# {'pk': 2, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}
content = JSONRenderer().render(serializer.data)
content
# '{"pk": 2, "title": "", "code": "print \\"hello, world\\"\\n", "linenos": false, "language": "python", "style": "friendly"}'
stream = BytesIO(content)
data = JSONParser().parse(stream)
I know JSONParser is used for deserializing the data and JSONRenderer is used for serializing it , but I still don't have a sound understanding of the difference between serializing and deserializing of a data. Can someone provide me a clear understanding of this.(Answer with an example is highly appreciated.)
And also how does JSONRenderer and JSONParser work?
I will start with viewsets. View and viewsets are classes in DRF, where most of application logic happens.
Eg. ModelViewSet is class responsible for CRUD operations in response to POST, PUT, PATCH, GET, DELETE HTTP methods.
Lets take look at default create method from https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/mixins.py this method create instance of your model, from data (if they are valid) send via HTTP POST method and persist them to database.
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
This is whats happening here.
self.get_serializer() create new instance of serializer (you set serializer class before), it takes request.data as argument. request.data is (this is importent) dictionary. Dictionary is generic python data structure.
serializer.is_valid() method checks if request.data are valid. If yes you can access serializer.data - also a dictionary.
serializer.save() method creates and persist actual instance of your model (Snippet) to database.
You can directly access instance like this
instance = serializer.save()
Then you return Response object populated with serializer.data back to client.
As you can see, there is no Form data,JSON, XML, HTML etc. in viewset. You work with python data types and serializer is reponsible of "translating" dictionary to instance of your specific model and backwards.
But client send data (in your case) in HTTP request in form of JSON.
JSONParser is responsible of converting JSON to dictionary. Parsing is implemented inside request class https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/request.py , please notice that is not standard django HttpRequest model.
You can set multiple parsers, then request will choose proper one according to HTTP request header: Content-type.
Second thing is, you have to return serializer.data back to client in form of JSON, not dictionary. Thats what JSONRenderer does. It convert dict to JSON and its implemented inside Response class https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/response.py. Also you can set multiple renderers and then the proper one is choose according to accepted media type http header.
Example of full viewset definition might be:
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
class SnippetViewSet(viewsets.ModelViewSet):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
renderer_classes = (JSONRenderer, )
parser_classes = (JSONParser,)

django: form to json

I am trying to serialize my form into the json format. My view:
form = CSVUploadForm(request.POST, request.FILES)
data_to_json={}
data_to_json = simplejson.dumps(form.__dict__)
return HttpResponse(data_to_json, mimetype='application/json')
I have the error <class 'django.forms.util.ErrorList'> is not JSON serializable. What to do to handle django forms?
Just in case anyone is new to Django, you can also do something like this:
from django.http import JsonResponse
form = YourForm(request.POST)
if form.is_valid():
data = form.cleaned_data
return JsonResponse(data)
else:
data = form.errors.as_json()
return JsonResponse(data, status=400)
JsonResponse: https://docs.djangoproject.com/en/dev/ref/request-response/#jsonresponse-objects
Form.cleaned_data: https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.Form.cleaned_data
Form.errors.as_json(): https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.Form.errors.as_json
You may want to look at the package called django-remote-forms:
A package that allows you to serialize django forms, including fields
and widgets into Python dictionary for easy conversion into JSON and
expose over API
Also see:
How to cast Django form to dict where keys are field id in template and values are initial values?