How should queryset be set for related fields - django

I have two models named book and chapter. each book can have many chapters, so models are like:
class Book(models.Model):
title = models.CharField(max_length=100)
class Chapter(models.Model):
title = models.CharField(max_length=100)
book = models.ForeignKey("books.Book", on_delete=models.CASCADE)
and serializers are like:
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ["title"]
class ChapterSerializer(serializers.ModelSerializer):
book = serializers.PrimaryKeyRelatedField(queryset=Book.objects.all())
class Meta:
model = Chapter
fields = ["title", "chapter_number", "text", "book"]
So my question is here: Is it OK to set queryset=Book.objects.all()) for related field?
I mean, if the number of books gets bigger, wouldn't be any problem to query all the books to set the right book?

Serializers can be nested.
class ChapterSerializer(serializers.ModelSerializer):
book = BookSerializer(read_only=True)
class Meta:
model = Chapter
fields = ["title", "chapter_number", "text", "book"]

Related

How would I specify a data table that I have set up postgresql?

I am looking to set up the backend logic for a form where it shoots information to a data table that I set up in postgresql and was wondering, how I would specify the data table that I want to send the information to?
You can do this with a ModelForm. Assuming the 'data table' you mention is the database model class, you declare the Model you are sending information to in the Meta class, as shown here:
class Author(models.Model):
name = models.CharField(max_length=100)
title = models.CharField(max_length=3, choices=TITLE_CHOICES)
birth_date = models.DateField(blank=True, null=True)
def __str__(self):
return self.name
class Book(models.Model):
name = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ['name', 'title', 'birth_date']
class BookForm(ModelForm):
class Meta:
model = Book
fields = ['name', 'authors']
Notice where it says "model = Book" or "model = Author". This example is from the Django Documentation on ModelForms. You will need to instantiate your ModelForm class in your view.

Django, getting access to parent's fields and method in Many to One relation

I have the below example for demonstration only, the relationship between the authors and books is one to many, each book can be written by one author only.
Let's say I have created a record for the author, and then created a book written by that author. When I want to update the Book's details, I would like to get the author age as well, and getting access to any filed of Author model in book template.
{{form.author}} will return the author name, I tried {{form.author.age}}
and {{form.author.find_age}} without success.
My real example involves a formset of books, but I thought to make it simple as a single book as in the below will be easier for getting an answer.
Model:
class Author(models.Model):
name = models.CharField(max_length=300)
age = models.DecimalField(max_digits=3, decimal_places=1, default=3.0, blank = True )
def __str__(self):
return self.name
def find_age(self):
return self.age
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.PROTECT)
title = models.CharField(max_length=300)
publish = models.CharField(max_length=300)
def __str__(self):
return self.title
View:
class BookCreate(CreateView):
model = Book
fields = '__all__'
success_url = reverse_lazy('books-list')
class BookUpdate(UpdateView):
model = Book
success_url = reverse_lazy('books-list')
fields = '__all__'
class AuthorCreate(CreateView):
model = Author
fields = '__all__'
success_url = reverse_lazy('authors-list')
class AuthorUpdate(UpdateView):
model = Author
success_url = reverse_lazy('authors-list')
fields = '__all__'
template:
<div class="col-sm-3">
{{form}}
</div>
You can access the model instance associated with the form using form.instance
{{form.instance.author.age}}

django rest framework serialize the related fields

models.py
class Category(models.Model):
name = models.CharField(max_length=128)
class Product(models.Model):
category = models.ManyToManyField(Category, related_name="category")
name = models.CharField(max_length=128)
class ProductVariation(models.Model):
product = models.ForeignKey(Product, related_name="product")
name = models.CharField(max_length=128)
serializers.py
class ProductVariantSerializer(serializers.HyperlinkedModelSerializer)
class Meta:
model = ProductVariation
fields = (
"name",
)
class CategoryDetailSerializer(serializers.Modelserializer):
product_variant = PromotionVariantSerializer(many=True)
class Meta:
model = Category
fields =(
"name",
"product_variant" #how can i do this
)
here i want to list all the product variant that belongs to the category.
can i do this way or i want to write methods to get the product variant details
You may need to write serializers for Product and ProductVariation models. You can't display the ProductVariation objects right in the Category model serializer, as there is no direct relation between Category and ProductVariation models. But you could try may be using separate nested serializers for Product and ProductVariation models.
class ProductVariantSerializer(serializers.ModelSerializer):
class Meta:
model = ProductVariation
fields = ("name", )
class ProductSerializer(serializers.ModelSerializer):
variants = ProductVariantSerializer(source='product', many=True, read_only=True)
class Meta:
model = Product
fields = ('name', 'variants')
class CategorySerializer(serializers.ModelSerializer):
products = ProductSerializer(source='category', many=True, read_only=True)
class Meta:
model = Category
fields = ('name', 'products')
You could use the CategorySerializer for nested relationships.

Django Rest Framework Serializer

I'm using Django Rest Framework, i'm trying to get some field from my models
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
ordering = ['score' , 'username']
fields = ('id', 'username', 'user' ,'first_name', 'last_name', 'reg_number' ,'score', 'classroom')
my problem is that i get just :
-id
-username
-first_name
-last_name
-score
but i can't get the reg_number and classroom
even if i delete all fields :
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
ordering = ['score' , 'username']
i get the some result.
I have this problem just with 3 models : User & Student & Professor ( Student and Professor are inhereted from User )
my student model :
class Student(User):
reg_number = models.IntegerField()
classroom = models.ForeignKey(Classroom)
score = models.IntegerField(default=0)
skills = models.TextField(blank=True)
interest = models.TextField(blank=True)
about = models.TextField(blank=True)
projects = models.TextField(blank=True)
Can you include your student model definition.?? The reason may be ur student model contains reverse relationship in any other models. You have explicitly include that field in serializer. Checkout reverse relations topic in following link
http://www.django-rest-framework.org/api-guide/relations/#reverse-relations

django rest framework return selected field in view

Let's say I have a model name Book. I have two views(list and detail)
models.py
class Book(models.Model):
name = models.CharField(max_length=100)
author = models.CharField(max_length=100)
publishdate = models.DateTimeField()
serializers.py
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
If I'm going to use this serializer in my list view and detail view. Can I set the return field? Example : list view only return name list only and detail view will return name, author, publishdate field.
Or do I have to create new serializer and insert fields in Class Meta on both class?
If you need different representations for list and detail views you should define seperate serializers for each. For example...
class DetailBookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ('name', 'author', 'publishdate')
class ListBookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ('name',)
Then make sure to set the serializer_class attribute as appropriate on each view.