django rest api json data category subcategory - json

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)

Related

Putting if else conditions in Django Rest Framework API View while searching

I was writing API with DRF and what I want is to change queryset, if the search will return no results.
from rest_framework.generics import ListAPIView
from rest_framework import filters
from .models import Item
from .serializer import ItemSerializer
from .pagination import ItemPagination
class SearchItemApi(ListAPIView):
serializer_class = ItemSerializer
filter_backends = [filters.SearchFilter]
search_fields = ['name',]
pagination_class = ItemPagination
def get_queryset(self):
return Item.objects.all()
Here is the serializer:
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ('id', 'name',)
And this APIView will show these results on the page:
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"name": "Blue Jeans",
},
{
"id": 2,
"name": "Red Jeans",
}
]
}
And I want to make something like this:
def get_queryset(self):
if api_data["count"] == 0:
return Item.objects.filter(*some filter*)
else:
return Item.objects.all()
How can I add a condition to return other queryset, if the search will bring zero results?
You need to check the queryset result
def get_queryset(self):
qs = super().get_queryset()
if qs.count() == 0:
return Item.objects.filter(*some filter*)
else:
return Item.objects.all()

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

Return nested JSON from Models with relations in Django

models.py (simplified)
class Author(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
def get_books(self):
return Book.objects.filter(author=self.pk)
class Book(models.Model):
name = models.CharField(max_length=255)
pages = models.IntegerField()
author = models.ForeignKey(Author, on_delete=models.CASCADE)
def __str__(self):
return f'{self.name} from {self.author}'
class Paragraph(models.Model):
name = models.CharField(max_length=255)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
def __str__(self):
return f'{self.name} from {self.book}'
I want to return all the instances in a json file with this structure:
[
{
"name": 'Dumas',
"books": {
"name": "The count of Montecristo",
"paragraphs": {
"name": "paragraph_name_1",
},
{
"name": "paragraph_name_2",
},
{
"name": "The three Musketeers",
"paragraphs": {
"name": "paragraph_name",
},
]
What I tried:
serializers.py
class AuthorSerializer(serializers.ModelSerializer):
books = serializers.CharField(source='get_books', read_only=True)
class Meta:
model = Author
fields = ['name', 'books']
This add the books key but the value is the string representation of the istances of Book (of course), how I make the value being the serialized istances of Book? I have created a BookSerializer.
Notes:
I know that I can created a nested json by creating a serializer for Paragraph with depth = 2 but this will include fields I don't want (like pages in Book) and the json structure will be totally different.
You can create nested serializer as
class ParagraphSerializer(serializers.ModelSerializer):
class Meta:
model = Paragraph
fields = ("name",)
class BookSerializer(serializers.ModelSerializer):
paragraphs = ParagraphSerializer(source="paragraph_set", many=True, read_only=True)
class Meta:
model = Book
fields = ("name", "paragraphs")
class AuthorSerializer(serializers.ModelSerializer):
books = BookSerializer(source="book_set", read_only=True, many=True)
class Meta:
model = Author
fields = ['name', 'books']

Django JSON format error

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()

How to create object with Foreign Key

Fisrt,here is my models:
class Question(models.Model):
description = models.CharField(max_length=200)
analysis = models.CharField(max_length=50)
def __str__(self):
return self.description
class QuestionOption(models.Model):
question = models.ForeignKey(Question,related_name='options')
content = models.CharField(max_length=100)
isAnswer = models.BooleanField()
def __str__(self):
return self.question.description + " " + self.content
My Serializers:
class QuestionSerializer(ModelSerializer):
class Meta:
model = Question
fields = '__all__'
The Serializer of QuestionOption is as same
My ViewSet:
class QuestionViewSet(ModelViewSet):
queryset = Question.objects.all()
serializer_class = QuestionRetriveSerilzer
I want to post a Json data,like this:
{
"options": [
{
"content": "This is the first option",
"isAnswer": false
},
{
"content": "This is the second option",
"isAnswer": true
}
],
"description": "which one is true?",
"analysis": "It's esay"
}
I hope my QuestionViewSet can create a Question and two QuestionOption for me automatically,and when I post that Json data,the options is null list,so I override the create method of QuestionViewSet,like this:
def create(self, request, *args, **kwargs):
serializer = QuestionSerializer(data=request.data)
question = serializer.save()
for data in request.data['options']:
data['question'] = question.id
optionSeializer = OptionSerializer(data=data)
print optionSeializer.is_valid()
optionSeializer.save()
return Response(serializer.data,status=status.HTTP_200_OK)
And this method can work,but I want to find a simpler way to do it,cause I must override update and other methods,it's not a easy task...
So how to design Serializers and ViewSet in order to automatically create objects and update objects with foreign key ?
drf-writable-nested may help .