Django JSON format error - json

I am getting this error when I manually entered the data into POST request. But when I do it in the admin page, there is no error. Error at "contact_number" field..
This is the correct format when adding in admin:
{
"name": "Santos",
"email": "san",
"address": "san",
"note": "san",
"contact_number": [
"123455",
"1231231",
"23123123"
]
}
Error at "contact_number" field.
This is the result when adding via postman in POST request:
{
"name": "3123",
"email": "qwe#gmail.com",
"address": "Col",
"note": "noting",
"contact_number": [
"['3123', '123123']"
]
}
views.py
#method_decorator(csrf_exempt)
def phonebook_list(request):
if request.method == 'GET':
phonebooklist = PhoneBook.objects.all()
serialized_data = [pb.to_json() for pb in phonebooklist]
return JsonResponse(serialized_data, safe=False)
elif request.method == 'POST':
data= request.body.decode('utf8')
data= json.loads(data)
try:
new_contact = PhoneBook.objects.create(name=data["name"],address=data["address"],email=data["email"],note=data["note"])
ContactNumber.objects.create(contact_number=data["contact_number"],number=new_contact)
serialized_data = [new_contact.to_json()]
return JsonResponse({"created": serialized_data}, safe=False)
except:
return JsonResponse({"error":"not valid data"}, safe=False)
models.py
class PhoneBook(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=100, default='address')
email = models.CharField(max_length=50, default='email')
note = models.CharField(max_length=100, default='note')
def to_json(self):
contact_numbers = [c.contact_number
for c in self.contact_numbers.all()]
return {
'name': self.name,
'email': self.email,
'address': self.address,
'note': self.note,
'contact_number': contact_numbers
}
def __str__(self):
return self.name
class ContactNumber(models.Model):
number = models.ForeignKey(PhoneBook, related_name="contact_numbers")
contact_number= models.CharField(max_length=30)
def __str__(self):
return self.contact_number

It's ok now, I looped the contact numbers if contactnumber is greater than 1.
contact_number = data['contact_number']
for x in contact_number:
qs = ContactNumber(qs.number_id = new_contact.id, qs.contact_number = x)
qs.save()

Related

How to serialize json to sql?

I have a list of words and I should send requests to an API and get the information about the words. I want to convert the API data which is in JSON format to SQL(my DB is PostgreSQL) format in Django. How can I do that? Do you know any good source to learn to serialize json to sql?
I have just started learning Django.
It is the API's JSON data:
[
{
"word": "hello",
"phonetics": [
{
"text": "/həˈloʊ/",
"audio": "https://lex-audio.useremarkable.com/mp3/hello_us_1_rr.mp3"
},
{
"text": "/hɛˈloʊ/",
"audio": "https://lex-audio.useremarkable.com/mp3/hello_us_2_rr.mp3"
}
],
"meanings": [
{
"partOfSpeech": "exclamation",
"definitions": [
{
"definition": "Used as a greeting or to begin a phone conversation.",
"example": "hello there, Katie!"
}
]
},
{
"partOfSpeech": "noun",
"definitions": [
{
"definition": "An utterance of “hello”; a greeting.",
"example": "she was getting polite nods and hellos from people",
"synonyms": [
"greeting",
"welcome",
"salutation",
"saluting",
"hailing",
"address",
"hello",
"hallo"
]
}
]
},
{
"partOfSpeech": "intransitive verb",
"definitions": [
{
"definition": "Say or shout “hello”; greet someone.",
"example": "I pressed the phone button and helloed"
}
]
}
]
}
]
this is my models.py:
class Words(models.Model):
word = models.CharField(max_length=50)
american_phonetic= models.CharField(max_length=50)
american_audio= models.URLField(max_length = 200)
british_phonetic= models.CharField(max_length=50)
british_audio= models.URLField(max_length = 200)
###########################################################################
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
birth_date = models.DateField('birth date')
field= models.CharField(max_length=50)
location = models.CharField(max_length=30, blank=True)
interest= models.IntegerField() # for example : 1 for science , 2 for art , 3 for sport etc.
education= models.IntegerField() # for example : 1 for highschool , 2 for bachelor , 3 for master and 4 for phd
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
class UserLearned(models.Model):
Profile_id = models.ForeignKey(Profile, on_delete=models.CASCADE)
word_id = models.ForeignKey(Words, models.SET_NULL, blank=True, null=True,)
def __str__(self):
return self.word_id
############################################################################
class Meanings(models.Model):
word_id = models.ForeignKey(Words, on_delete=models.CASCADE)
partOfSpeech = models.CharField(max_length=30)
class Definitions(models.Model):
word_id = models.ForeignKey(Words, on_delete=models.CASCADE)
Meaning_id = models.OneToOneField(Meanings, on_delete=models.CASCADE, primary_key=True)
definition = models.TextField()
def __str__(self):
return self.definition
class Examples(models.Model):
word_id = models.ForeignKey(Words, on_delete=models.CASCADE)
Meaning_id = models.OneToOneField(Meanings, on_delete=models.CASCADE, primary_key=True)
example = models.TextField()
def __str__(self):
return self.example
class Synonyms(models.Model):
word_id = models.ForeignKey(Words, on_delete=models.CASCADE)
Meaning_id = models.ForeignKey(Meanings, on_delete=models.CASCADE)
synonym = models.CharField(max_length=50)
def __str__(self):
return self.synonym
You can use the json library to serialise the json data and vice versa (use json.loads() & json.dumps() methods).
For Example:
import json
data = "{'name': 'Jack', 'age': 30}" #json data
python_dict = json.loads(data) #now it is a python dict
Now you can directly assign the values of the python dict to any model attributes in Django.
Following are some good sources to start learning the library:
https://www.w3schools.com/python/python_json.asp
https://docs.python.org/3/library/json.html

django rest api json data category subcategory

I am trying to access subcategories according to parent id. When i am checking subcategories api it's showing all data with all parent id. I am unable to filter subcategories according to parent id. I am trying to get json data according to parent id.
If our parent id is 7 so i need all subcategories which one's has parent id 7. Please guide how i can do its.
models.py
class Category(models.Model):
name = models.CharField(max_length=254, unique=True)
status = models.BooleanField(default=True)
def __str__(self):
return self.name
class SubCategory(models.Model):
name = models.CharField(max_length=254, unique=True)
id_parent = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
price = models.IntegerField()
status = models.BooleanField(default=True)
def __str__(self):
return self.name
json
[
{
"id": 1,
"name": "IT Servic",
"price": 2000,
"status": true,
"id_parent": 7
},
{
"id": 2,
"name": "Web Development",
"price": 1000,
"status": true,
"id_parent": 8
},
{
"id": 3,
"name": "Digital Marketing",
"price": 3000,
"status": true,
"id_parent": 7
},
{
"id": 4,
"name": "RO Repair",
"price": 3444,
"status": true,
"id_parent": 9
}
]
serializers.py
class CategorySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Category
fields = '__all__'
class SubCategorySerializer(serializers.ModelSerializer):
class Meta:
model = SubCategory
fields = '__all__'
lookup_field = 'id_parent'
views.py*
class CategoryViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated,)
serializer_class = CategorySerializer
def get_queryset(self):
user = self.request.user
if user.is_authenticated:
if user is not None:
if user.is_active and user.is_superuser:
return Category.objects.all()
raise PermissionDenied()
raise PermissionDenied()
raise PermissionDenied()
class SubCategoryViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated,)
def get_queryset(self):
user = self.request.user
if user.is_authenticated:
if user is not None:
if user.is_active and user.is_superuser:
return SubCategory.objects.all()
raise PermissionDenied()
raise PermissionDenied()
raise PermissionDenied()
serializer_class = SubCategorySerializer
You should take a look at filtering.
Basically, you can either do your filtering "manually" in the get_queryset()
def get_queryset(self):
id_parent = self.request.query_params.get('id_parent')
queryset = super().get_queryset()
if id_parent:
queryset = queryset.filter(id_parent=id_parent)
return queryset
Or use a third-party library such as django-filter
you can add a custom action to your viewset like this, assuming you can set the appropriate urls/routes
#action(detail=False, methods=['GET'])
def get_sub_categories(self, request, *args, **kwargs):
category_id = self.request.query_params.get("category_id", None)
queryset = self.get_queryset()
filtered_sub_categories = queryset.filter(id_parent=category_id)
serializer = self.get_serializer(filtered_sub_categories, many=True)
return Response(serializer.data)

How to Solve Django rest-framework JSON parse Error

What is wrong with this JSON?
when trying to send a POST request with POSTMAN getting JSON PARSE ERROR.
Error from Postman
{
"detail": "JSON parse error - Expecting ',' delimiter: line 5 column 13 (char 82)"
}
JSON Data sending From Postman
{
"menu_name": "indian_menu",
"slug": "indianmenu",
"item_name": [
"category": "indianmenu",
]
}
rest_framework Serializers
class MenuCardSerializer(serializers.ModelSerializer):
class Meta:
model = MenuCard
fields = '__all__'
read_only_fields = ('menu_name', )
class MenuSerializer(serializers.ModelSerializer):
category = MenuCardSerializer(required=True, many=True)
class Meta:
model = Menu
fields = '__all__'
def create(self, validated_data):
category = validated_data.pop('category')
menu = MenuCard.objects.create(**validated_data)
for choice in category:
Menu.objects.create(**choice, category=menu)
rest_framework API_VIEWS
#api_view(['GET', 'POST', 'PUT', 'DELETE', ])
def simple_menu(request, slug):
print("simple menu slug : " + slug)
if request.method == 'GET':
category_list = Menu.objects.all()
serializer = MenuSerializer(category_list)
return JsonResponse(serializer.data)
elif request.method == 'POST':
serializer = MenuSerializer(data=request.data, many=False)
data = {}
if serializer.is_valid():
serializer.save()
data["success"] = "item Catagory Created"
return JsonResponse(data=data, status=status.HTTP_200_OK)
return JsonResponse(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
You JSON from postman is not a valid one, you can easily check it with any JSON validator.
In your first example it should be a dict not list as oz19 mentioned.
The same problem in the second one, the correct one is something like this:
{
"menu_name":"Indian Menu",
"slug":"indianmenu",
"item_name":[
{
"category":"Indian Menu",
"item_name":"dal",
"price":"22.30",
"stock":"10"
}
]
}
The error possibly comes from the data you are entering on Postman. On item_name you probably wanted to create a dict, but it is a list.
Change:
{
...
"item_name": [ "category": "indian_menu"]
}
By:
{
...
"item_name": { "category": "indian_menu" }
}

django REST framework, validate json data

The server comes with json format:
{
"type": "string",
"object": {
"lead_id": int,
"form_name": "string",
"answers": [
{
"lead_id": int,
"key": "string",
}
...
]
},
"group_id": int,
"secret": "string"
}
How to use django REST framework to validate this json?
ru version
class AnswersSerializer(serializers.Serializer):
lead_id = serializers.IntegerField(required=True)
key = serializers.CharField(max_length=100)
class ObjectSerializer(serializers.Serializer):
lead_id = serializers.IntegerField(required=True)
form_name = serializers.CharField(max_length=100)
answers = serializers.ListField(child=AnswersSerializer())
class UpdateGroup(serializers.Serializer):
group_id = serializers.IntegerField(required=True)
type = serializers.CharField(max_length=100)
secret = serializers.CharField(max_length=100)
object = serializers.DictField(child=, default={})
Example:
# serializers.py
from rest_framework import serializers
class VkObjectSerializer(serializers.Serializer):
"""
is 'object'
"""
lead_id = serializers.IntegerField()
group_id = serializers.IntegerField()
user_id = serializers.IntegerField()
form_id = serializers.IntegerField()
class VkBaseSerializer(serializers.Serializer):
"""
Base serializer
"""
type = serializers.CharField(max_length=200)
object = VkObjectSerializer()
group_id = serializers.IntegerField()
secret = serializers.CharField(max_length=200)
# view.py
from rest_framework.generics import CreateAPIView
from rest_framework.response import Response
from .serializers import VkBaseSerializer
class VkCallbackView(CreateAPIView):
serializer_class = VkBaseSerializer
def create(self, request, *args, **kwargs):
"""
Method is validate json in view
"""
valid_ser = self.serializer_class(data=request.data)
if valid_ser.is_valid():
return Response('True')
return Response('False')
Valid data:
>>> valid_ser.data
{
"type": "str",
"object": {
"lead_id": 123,
"group_id": 12345,
"user_id": 12352,
"form_id": 1
},
"group_id": 5123,
"secret": "str"
}
The answers were very helpful:
Django Rest Framework ListField and DictField - how to set model json
How to validate a json object in django - validate data in view
You can use django rest framework to write you own validators like so,
class MultipleOf(object):
def __init__(self, base):
self.base = base
def __call__(self, value):
if value % self.base != 0:
message = 'This field must be a multiple of %d.' % self.base
raise serializers.ValidationError(message)
You can find more details here
Hope this helps!

Return only funded fields in response(Django Rest SearchFilter)

I have ViewSet which have SearchFilter in filter_backends and two search_fields. How to return JSON represents the only field results?
For example if i send response for search with "jo" substring i will have only one field for this search(funded user name or full name), not both user name and email in each JSON object:
{
[{
"username": "jonh";
},
{
"fullname": "Jonh";
},
{
"username": "jo";
},
{
"fullname": "Johnson";
}
]
}
viewsets.py:
class UserViewSet(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet):
queryset = User.objects.all()
permission_classes = (IsUserOrReadOnly,)
filter_backends = (filters.SearchFilter,)
search_fields = ('^username', '^fullname',)
def get_serializer_class(self):
if hasattr(self, 'action') and self.action == 'list':
return UserListSerializer
return UserDetailSerializer
serializers.py:
class UserListSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email', 'fullname')
I would create a Serializer factory function that takes the search params as an an argument:
def generate_user_list_serializer(search_terms):
class UserListSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = tuple(search_terms)
return UserListSerializer
Then in your view, have the serializer generated on the fly:
def get_serializer_class(self):
# make sure that the fields are available
validated_params = [p for p in self.query_params if p in Myfields]
return generate_user_list_serializer(self.query_params)