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
Related
I have two different models in my project. The StudentDetail model has an one-to-one connection with the student-user and the EnrollmentList has a foreign key connection with the student user. I want to combine information from both the models for that specific student-user and send them as as a single response rather than sending different responses. Below are the models and their serializers
StudentDetail/models.py
class StudentDetail(models.Model):
id = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4)
user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
name = models.CharField(max_length=100, null=True, blank=True)
StudentDetailSerializer
class StudentDetailSerializer(serializers.ModelSerializer):
class Meta:
model = StudentDetail
fields = "__all__"
Enrollment/models.py
class EnrollmentList(models.Model):
id = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4)
student = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='student')
EnrollSerializer
class AllReqs(serializers.ModelSerializer):
class Meta:
model = EnrollmentList
fields = ['id','student_name', 'student_parent_name', 'standard', 'applying_for_standard', "board", 'home_tuition', 'address']
Now suppose a request is made, I want to combine the information from the StudentDetail and EnrollmentList for that specific student user to get a serialized data which may look like below example and send this as a single response
{
"student_name": name, #from StudentDetail
"home_tuition": home_tuition #from EnrollmentList
}
Please suggest to me the correct way to do it
Define your serializer like that:
class AllReqs(serializers.ModelSerializer):
student_name = serializers.CharField(source='student.user.name')
class Meta:
model = EnrollmentList
fields = ['id','student_name', 'home_tuition']
additional StudentDetail serializer:
class StudentDetailSerializer(serializers.ModelSerializer):
student_name = serializers.CharField(source='user.name')
home_tuition = serializers.SerializerMethodField()
class Meta:
model = StudentDetail
fields = ['id','student_name', 'home_tuition']
def get_home_tuition(self, obj):
for enrollment in obj.user.students.all():
return enrollment.home_tuition
I kindly ask the questioner to refer to the Django-Rest-Framework documentation. https://www.django-rest-framework.org/
class BookingSerializer(serializers.ModelSerializer):
class Meta:
model = Booking
fields = "__all__"
class EmployeeSerializer(serializers.ModelSerializer):
bookings_st = BookingSerializer(many=True, read_only=True)
class Meta:
model = Employee
fields = "__all__"
class ProjectSerializer(serializers.ModelSerializer):
employees = EmployeeSerializer(read_only=True, many=True)
class Meta:
model = Project
fields = "__all__"
class Employee(models.Model):
name = models.CharField(max_length=127)
lastname = models.CharField(max_length=127)
class Project(models.Model):
title = models.CharField(max_length=127)
employees = models.ManyToManyField(Employee,
related_name='employees')
class Booking(models.Model):
start = models.DateField()
end = models.DateField()
employee = models.ForeignKey(Employee,
on_delete=models.CASCADE,
related_name='bookings_st')
project = models.ForeignKey(Project,
on_delete=models.CASCADE,
related_name='bookings_st')
I get nested object, but how to get in Emploee only related to both (project and employee) bookings? Now I just get all bookings that this employee has.
I mean that structure:
project_1:
emploee_1:
[bookings_that_belong_to_THIS_PROJECT]
A possibility here is to leverage a SerializerMethodField together with the serializer's context object:
class BookingSerializer(serializers.ModelSerializer):
class Meta:
model = Booking
fields = "__all__"
class EmployeeSerializer(serializers.ModelSerializer):
bookings_st = serializers.SerializerMethodField()
def get_bookings_st(self, employee):
project = self.context.get("project")
return BookingSerializer(
employee.bookings_st.filter(project=project),
many=True,
).data
class Meta:
model = Employee
fields = "__all__"
class ProjectSerializer(serializers.ModelSerializer):
employees = serializers.SerializerMethodField()
def get_employees(self, project):
return EmployeeSerializer(
project.employees.all(),
many=True,
context={**self.context, "project": project}
).data
class Meta:
model = Project
fields = "__all__"
This wouldn't be super performant if you're using that when listing projects or when retrieving a specific project with many employees. Depending on your use case - if you're only using it to retrieve a specific project, for example, you could leverage prefetch_related and the Prefetch class to prefetch custom employees + bookings querysets by filtering out the specific project at hand (and you could then use the regular serializers).
I have a model with a one-to-one relationship with a main model:
class User(models.Model):
id = models.BigIntegerField(primary_key=True)
username = models.CharField(max_length=100, blank=True)
class AggregatedStats(models.Model):
user_id = models.ForeignKey('User', on_delete=models.DO_NOTHING, unique=True)
followers_30d = models.BigIntegerField(blank=True)
I have written the following serializers:
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'followers']
class AggregatedStatsSerializer(serializers.HyperlinkedModelSerializer):
username = UserSerializer(source='user.username')
class Meta:
model = AggregatedStats
fields = ['followers_30d', 'username']
I am trying to return the username from the User model, but whatever I try to get it, the best I can do is get the hyperlinked related field from user, but not the actual "username" attribute. How would you return this?
You can simply create a field and return it:
class AggregatedStatsSerializer(serializers.HyperlinkedModelSerializer):
username = SerializerMethodField()
class Meta:
model = AggregatedStats
fields = ['followers_30d', 'username']
def get_username(self, obj):
return obj.user_id.username
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.
I have three models for Movie, NowShowing and UpComingMovie. NowShowing and UpComingMovie has foreignkey relationship with the Movie.
class Movie(models.Model):
name = models.CharField(max_length=254, unique=True)
synopsis = models.TextField()
release_date = models.DateField()
director = models.ManyToManyField(MovieDirector)
writer = models.ManyToManyField(MovieWriter)
actor = models.ManyToManyField(MovieActor)
censor_rating = models.PositiveIntegerField(choices=CENSOR_TYPE)
#property
def is_screening(self):
if self.nowshowing_set.all().count() > 0:
return True
else:
return False
class NowShowing(models.Model):
movie = models.ForeignKey(Movie)
show_time = models.DateTimeField()
class UpComingMovie(models.Model):
movie = models.ForeignKey(Movie)
Each three of the models can be accesed in the admin:
class MovieAdmin(admin.ModelAdmin):
list_display = ('name', 'release_date', 'censor_rating', 'is_screening')
class Meta:
model = Movie
admin.site.register(Movie, MovieAdmin)
admin.site.register(NowShowing)
admin.site.register(UpComingMovie)
The problem is that I have to go to NowShowing or UpComingMovie admin page to create/change object. Is it possible to display each movies related set fields (NowShowing or UpComingMovie) to display in the Movie object detail admin page itself, so that its related field can be created/changed from the Movie obj directly without going to NowShowing or Upcoming admin page?
Yes, it's quite possible thanks to TabularInline (or StackedInline)
class UpcomingInline(admin.TabularInline):
model = UpComingMovie
class NowShowingInline(admin.TabularInline):
model = NowShowing
class MovieAdmin(admin.ModelAdmin):
list_display = ('name', 'release_date', 'censor_rating', 'is_screening')
inlines = [UpcomingInline,NowShowingInline]
class Meta:
model = Movie