Reputation: 848
I have a couple models, one of which is already populated with data (book name/ chapter number/ paragraph number data), and I am implementing the feature for each user to be able to add a note per each unique book name/ chapter number/ paragraph number, which I could, but I have been stack for a couple of days trying to retrieve books with the related_name
note
of the current user if they have any. Here are my models:
Book
model that is already populated with data.
from django.db import models
class Book(models.Model):
day = models.CharField(max_length=128)
book = models.CharField(max_length=128)
chapter = models.CharField(max_length=256)
paragraph = models.CharField(max_length=256)
text = models.TextField()
link = models.CharField(max_length=256)
def __str__(self):
return f'{self.book}_{self.chapter}.{self.paragraph} '
class Meta:
ordering = ['-id']
verbose_name = "Paragraph"
verbose_name_plural = "Paragraph"
Here is the Note
model that should store the current user's note regarding a specific unique book name / chapter number / paragraph number:
from django.db import models
from django.conf import settings
from rest_framework.reverse import reverse
from paragraphs.models import Book
class Note(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='author', on_delete=models.CASCADE)
paragraph = models.ForeignKey(Book, related_name='note', on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
text = models.TextField(default=None)
def __str__(self):
return f'Note on {self.paragraph}'
class Meta:
ordering = ['created']
def save(self, *args, **kwargs):
"""
"""
options = {'text': self.text} if self.text else {}
super(Note, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('note-detail', args=[self.id])
Here are my serializers:
Book
serializer
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
Note
serializer
from rest_framework import serializers
from .models import Note
from users.serializers import UserSerializer
from paragraphs.serializers import BookSerializer
class NoteSerializer(serializers.ModelSerializer):
owner = UserSerializer(many=False, read_only=True)
class Meta:
model = Note
fields = ['id', 'owner', 'paragraph', 'text', 'created']
def to_representation(self, instance):
self.fields['paragraph'] = BookSerializer(read_only=True)
return super(NoteSerializer, self).to_representation(instance)
def user(self):
request = self.context.get('request', None)
if request:
return request.user
return None
def create(self, validated_data):
note, _ = Note.objects.update_or_create(
owner=self.user(),
paragraph=validated_data.get('paragraph', None),
defaults={'text': validated_data.get('text', None)})
return note
The data I am getting:
{
"id": 25,
"day": "2",
"book": "Some book",
"chapter": "1",
"paragraph": "3",
"text": "This is an example text that the user would like to attach a note to",
"link": "https://somelink.com",
}
The data I am trying to get:
{
"id": 25,
"day": "2",
"book": "Some book",
"chapter": "1",
"paragraph": "3",
"text": "This is an example text that the user would like to attach a note to",
"link": "https://somelink.com",
"note": "note of current user or none"
}
Any help is appreciated
Upvotes: 1
Views: 103
Reputation: 2235
models.py:
class Book(models.Model):
day = models.CharField(max_length=128)
book = models.CharField(max_length=128)
chapter = models.CharField(max_length=256)
paragraph = models.CharField(max_length=256)
text = models.TextField()
link = models.CharField(max_length=256)
def __str__(self):
return f'{self.book}_{self.chapter}.{self.paragraph} '
class Meta:
ordering = ['-id']
class Note(models.Model):
owner = models.ForeignKey(to = User, related_name='author', on_delete=models.CASCADE)
book = models.ForeignKey(Book, related_name='note', on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
text = models.TextField(default=None)
def __str__(self):
return '%s(%s)' %(self.owner,self.book)
serializers.py:
class NoteSerializer(serializers.ModelSerializer):
class Meta:
model = Note
fields = ['id', 'owner', 'book', 'text', 'created']
class BookSerializer(serializers.ModelSerializer):
note = serializers.StringRelatedField(many=True, read_only=True)
# note = NoteSerializer(many=True, read_only=True)
class Meta:
model = Book
fields = ['day','book','chapter','paragraph','text','link','note']
Output:
{
"day": "2",
"book": "some book",
"chapter": "1",
"paragraph": "example",
"text": "some textttttttttttttttttttttttttttttttttttttttttttttttt",
"link": "http://127.0.0.1:8000/admin/api/book/add/",
"note": [
"admin(some book_1.example )"
]
}
It's return all field:
class NoteSerializer(serializers.ModelSerializer):
class Meta:
model = Note
fields = ['id', 'owner', 'book', 'text', 'created']
class BookSerializer(serializers.ModelSerializer):
# note = serializers.StringRelatedField(many=True, read_only=True)
note = NoteSerializer(many=True, read_only=True)
class Meta:
model = Book
fields = ['day','book','chapter','paragraph','text','link','note']
Output:
{
"day": "2",
"book": "some book",
"chapter": "1",
"paragraph": "example",
"text": "some textttttttttttttttttttttttttttttttttttttttttttttttt",
"link": "http://127.0.0.1:8000/admin/api/book/add/",
"note": [
{
"id": 2,
"owner": 1,
"book": 1,
"text": "saaaaaaaaaaaaaaaaaaa",
"created": "2021-02-24T14:34:13.279750Z"
}
]
}
Upvotes: 1
Reputation: 143
What you're actually trying to achieve is for the NoteSerializer to include fields from the Foreign-key related book model. Overriding the to_representation method of the serializer is clunky and not the way to go. See here a better approach.
Upvotes: 0