Django rest api csv to json - 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

Related

Django REST framework export to 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)

How do we POST data in django rest framework using function based views?

I am new to django rest framework (DRF) and I need to POST some data using function based views (FDV). I successfully used GET method using this way but have no idea how to use POST method to add values to database.
# app/models.py
class Item(models.Model):
name = models.CharField(max_length=50)
quantity = models.IntegerField()
price = models.FloatField()
# app/urls.py
urlpatterns = [
path('', views.get_data_list, name='list'),
path('post_val/', views.post_data, name='post_val'), # need to implement
]
# app/serializers.py
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ('id', 'name', 'quantity','price')
# app/views.py
from django.http.response import JsonResponse
from rest_framework.parsers import JSONParser
from .models import Item
from .serializers import ItemSerializer
from rest_framework.decorators import api_view
#api_view(['GET',])
def get_data_list(request):
if request.method == 'GET':
items = Item.objects.all()
items_serializer = ItemSerializer(items, many=True)
return JsonResponse(items_serializer.data, safe=False)
#api_view(['POST',])
def post_data(request):
#TO DO
If I want to add this new data like this one {name:"Television", quantity:15, price:999.99} to Item table using POST method, How do we do it in FDV?
Try this
#api_view(['POST',])
def post_data(request):
serializer = ItemSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
On a side note, you can use DRF's Response object for returning the response. It will automatically convert to JSON or XML based on your config.
Import it via
from rest_framework.response import Response
django-rest-framework puts the posted data in request.data
So in short you can retrieve your data from there and create your object:
#api_view(['POST',])
def post_data(request):
item_serializer = ItemSerializer(data=request.data)
if item_serializer.is_valid():
item = item_serializer.save()

Is there a way how to save json with flask_sqlalchemy with sqlite backend

I am trying to save data in form of JSON (returned as result from POST request)
def get_data(...):
...
try:
_r = requests.post(
_url_list,
headers=_headers
)
return _r.json()
except Exception as ee:
print('Could not get data: {}'.format(ee))
return None
Into a table in SQLITE database as backend.
def add_to_flight_data(_data):
if _data:
try:
new_record = FlightData(data=_data)
db.session.add(new_record)
db.session.commit()
print('Data instertedto DB!')
return "Success"
except Exception as e:
print('Data NOT instertedto DB! {}'.format(e))
pass
This is my simple flask code
import os
import time
import auth
import json
import requests
import datetime
from flask import Flask
from flask_marshmallow import Marshmallow
from flask_sqlalchemy import SQLAlchemy
# from safrs.safrs_types import JSONType
project_dir = os.path.dirname(os.path.abspath(__file__))
database_file = "sqlite:///{}".format(os.path.join(project_dir, "2w.sqlite"))
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = database_file
db = SQLAlchemy(app)
ma = Marshmallow(app)
class FlightData(db.Model):
id = db.Column(db.Integer, primary_key=True)
created = db.Column(db.DateTime, server_default=db.func.now())
json_data = db.Column(db.JSONType, default={})
def __init__(self, data):
self.data = data
It seems like there is perhaps no option to save JSON in sqlite
json_data = db.Column(db.JSONType, default={})
Please ADVISE
Thanks.
I believe that you should be using db.JSON, not db.JSONType as there is no such column type in sqlalchemy.
Regardless of that, SQLite has no JSON data type, so sqlalchemy won't be able to map columns of type db.JSON onto anything. According to the documentation only Postgres and some MySQL are supported. There is support for JSON in SQLite with the JSON1 extension, but sqlalchemy will not be able to make use of it.
Your best bet then is to declare the column as db.Text and use json.dumps() to jsonify the data on write. Alternatively modify your get_data() function to check for a JSON response (check the Content-type header or try calling _r.json() and catching exceptions), and then return _r.content which will already be a JSON string.
Use json.loads() to read data back from the db.

__str__ returned non-string (type list)

I am having a django app in which I am storing the json variable.I have stored the json variable through admin and I am trying to print it in shell.My main aim is to pass this variable to a webpage with ajax method.But first when I was trying to print it in shell I get this error
__str__ returned non-string (type list)
My models.py is of this form
from django.db import models
from django.utils import timezone
from jsonfield import JSONField
# Create your models here.
class newgrid(models.Model):
data = JSONField()
def __str__(self):
return self.data
My JSON variable is of this form
[{"col":1,"row":1,"size_x":1,"size_y":1},{"col":2,"row":1,"size_x":1,"size_y":1},{"col":3,"row":1,"size_x":1,"size_y":1},{"col":4,"row":1,"size_x":1,"size_y":1},{"col":1,"row":2,"size_x":1,"size_y":1},{"col":2,"row":2,"size_x":1,"size_y":1},{"col":3,"row":2,"size_x":1,"size_y":1},{"col":4,"row":2,"size_x":1,"size_y":1},{"col":1,"row":3,"size_x":1,"size_y":1},{"col":2,"row":3,"size_x":1,"size_y":1},{"col":3,"row":3,"size_x":1,"size_y":1},{"col":4,"row":3,"size_x":1,"size_y":1},{"col":5,"row":1,"size_x":1,"size_y":1}]
In shell I ran following commands
from testforweb.models import newgrid
newgrid.objects.all()
It initially returned this
<QuerySet [<newgrid: newgrid object (1)>]>
But then I added
def __str__(self):
return self.data
Just to see the actual JSON variable.But I am getting the error
How to see the actual JSON variable which I inserted through admin coz I need to send it to webpage as it is
Edit 1
My updated models.py
from django.db import models
from django.utils import timezone
from jsonfield import JSONField
import simplejson as json
# Create your models here.
class newgrid(models.Model):
data = JSONField()
def __str__(self):
json.dumps(self.data)
The __str__ function must return a string:
def __str__(self):
return json.dumps(self.data)
The JSON field will actually decode the JSON into native python types (lists and dictionaries).
The __str___ method is always expected to return a string.
If you want a string representation of the json, you should use json.dumps(self.data) or similar to serialise the data field as the return value of __str__.
Use
def __str__(self):
return '%s' % (self.data)
Instead of
def __str__(self):
return json.dumps(self.data)

How to output Django queryset as JSON?

I want to serialize my queryset, and I want it in a format as this view outputs:
class JSONListView(ListView):
queryset = Users.objects.all()
def get(self, request, *args, **kwargs):
return HttpResponse(json.dumps({'data': [['bar','foo','bar','foo'],['foo','bar','foo','bar']]}, indent=4), content_type='application/json')
I simply don't know how to output the queryset instead of the manual data in the example.
I've tried
json.dumps({"data": self.get_queryset()})
and
serializers.serialize("json", {'data': self.get_queryset()})
but it won't work. What am I doing wrong? Do I need to make a custom JSON Encoder?
You can use JsonResponse with values. Simple example:
from django.http import JsonResponse
def some_view(request):
data = list(SomeModel.objects.values()) # wrap in list(), because QuerySet is not JSON serializable
return JsonResponse(data, safe=False) # or JsonResponse({'data': data})
Or another approach with Django's built-in serializers:
from django.core import serializers
from django.http import HttpResponse
def some_view(request):
qs = SomeModel.objects.all()
qs_json = serializers.serialize('json', qs)
return HttpResponse(qs_json, content_type='application/json')
In this case result is slightly different (without indent by default):
[
{
"model": "some_app.some_model",
"pk": 1,
"fields": {
"name": "Elon",
"age": 48,
...
}
},
...
]
I have to say, it is good practice to use something like marshmallow to serialize queryset.
...and a few notes for better performance:
use pagination if your queryset is big;
use objects.values() to specify list of required fields to avoid serialization and sending to client unnecessary model's fields (you also can pass fields to serializers.serialize);
It didn't work, because QuerySets are not JSON serializable.
1) In case of json.dumps you have to explicitely convert your QuerySet to JSON serializable objects:
class Model(model.Model):
def as_dict(self):
return {
"id": self.id,
# other stuff
}
And the serialization:
dictionaries = [ obj.as_dict() for obj in self.get_queryset() ]
return HttpResponse(json.dumps({"data": dictionaries}), content_type='application/json')
2) In case of serializers. Serializers accept either JSON serializable object or QuerySet, but a dictionary containing a QuerySet is neither. Try this:
serializers.serialize("json", self.get_queryset())
Read more about it here:
https://docs.djangoproject.com/en/dev/topics/serialization/
For a efficient solution, you can use .values() function to get a list of dict objects and then dump it to json response by using i.e. JsonResponse (remember to set safe=False).
Once you have your desired queryset object, transform it to JSON response like this:
...
data = list(queryset.values())
return JsonResponse(data, safe=False)
You can specify field names in .values() function in order to return only wanted fields (the example above will return all model fields in json objects).
To return the queryset you retrieved with queryset = Users.objects.all(), you first need to serialize them.
Serialization is the process of converting one data structure to another. Using Class-Based Views, you could return JSON like this.
from django.core.serializers import serialize
from django.http import JsonResponse
from django.views.generic import View
class JSONListView(View):
def get(self, request, *args, **kwargs):
qs = User.objects.all()
data = serialize("json", qs)
return JsonResponse(data)
This will output a list of JSON. For more detail on how this works, check out my blog article How to return a JSON Response with Django. It goes into more detail on how you would go about this.
If the goal is to build an API that allow you to access your models in JSON format I recommend you to use the django-restframework that is an enormously popular package within the Django community to achieve this type of tasks.
Django Rest Framework Website
Github
It include useful features such as Pagination, Defining Serializers, Nested models/relations and more. Even if you only want to do minor Javascript tasks and Ajax calls I would still suggest you to build a proper API using the Django Rest Framework instead of manually defining the JSON response.
Another way to turn queryset into JSON, is appending necessary elements to an empty list with loop. It provides to design customizable JSON.
queryset = Users.objects.all()
output = []
for query in queryset:
output.append('id': query.id, 'name': query.name, etc...)
return JSONResponse(output, safe=False)
Try this:
class JSONListView(ListView):
queryset = Users.objects.all()
def get(self, request, *args, **kwargs):
data = {}
data["users"] = get_json_list(queryset)
return JSONResponse(data)
def get_json_list(query_set):
list_objects = []
for obj in query_set:
dict_obj = {}
for field in obj._meta.get_fields():
try:
if field.many_to_many:
dict_obj[field.name] = get_json_list(getattr(obj, field.name).all())
continue
dict_obj[field.name] = getattr(obj, field.name)
except AttributeError:
continue
list_objects.append(dict_obj)
return list_objects
from django.http import JsonResponse
def SomeFunction():
dict1 = {}
obj = list( Mymodel.objects.values() )
dict1['data']=obj
return JsonResponse(dict1)
Try this code for Django