Display the object related set objects in the admin - django

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

Related

How to get only related objects in django serializer with manyToMany?

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

How to retrieve data from model that current user created and list it for another model's field in django

Let us imagine that I have two models.
First model contains curse details and user that created this course
class Course(models.Model):
course_name = models.CharField(max_length=100, null=False)
description = models.CharField(max_length=255)
user_profile = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
and my second model is:
class Lesson(models.Model):
course = models.OneToOneField(Course, on_delete=models.CASCADE) #
# inside the course I want my APIVIEW to list only the courses that current user created.
# OnetoOne relationship does not solve the problem.
status = models.CharField(choices=STATUS, null=False, default=GOZLEMEDE,max_length=20)
tariffs = models.FloatField(max_length=5,null=False,default=0.00)
continues_off = models.CharField(max_length=2)
user_profile = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
My serializers for both Models:
class LessonSerializer(serializers.ModelSerializer):
class Meta:
model = models.Lesson
fields = ('course', 'status', 'tariffs', 'continues_off', 'user_profile')
def create(self, validated_data):
lesson = models.Lesson.objects.create(
course = validated_data['course'],
status = validated_data['status'],
tariffs=validated_data['tariffs'],
continues_off=validated_data['continues_off'],
user_profile=validated_data['user_profile']
)
return lesson
class CourseSerializer(serializers.ModelSerializer):
"""Serializers Course content"""
class Meta:
model = models.Course
fields = '__all__'
def create(self,validated_data):
course = models.Course.objects.create(
course_name = validated_data['course_name'],
description=validated_data['description'],
user_profile=validated_data['user_profile']
)
return course
My Viewset:
class LessonViewset(viewsets.ModelViewSet):
model = models.Lesson
serializer_class = serializers.LessonSerializer
authentication_classes = (SessionAuthentication,)
permission_classes = (IsAuthenticated,BasePermission,)
def get_queryset(self):
user_current = self.request.user.id
return models.Lesson.objects.filter(user_profile=user_current)
How can I get the desired result. I want to get the courses for the current user and show them as a dropdown list in my API view. Just only the courses that user created should be in the dropdown list not all.
OnetoOne relationship gives all results of course table.
i think change your view code to :
def get_queryset(self,id):
return model.objects.filter(user_profile=id)
#You do not need to call it again when you put the Lesson on the model
\

fields in class Meta got invalid

models.py
class Product(models.Model):
title = models.CharField(max_length=200)
description = models.TextField()
price = models.DecimalField(decimal_places=5,max_digits= 1500)
summary = models.TextField()
featured = models.BooleanField()
def __str__(self):
return self.title
# return f'product title:{self.title}-product price:{self.price}'workok
class Meta:
ordering = ('-price',)
class Opinion(models.Model):
name = models.CharField(max_length=20)
email = models.EmailField(max_length=20)
body = models.TextField()
opinion_date = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=False)
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='opinion_set')
def __str__(self):
return f'({self.name}) add opinion about ({self.product})'
forms.py:
from django.forms import ModelForm
from .models import Product #space after from keyword
class OpinionModelForm(ModelForm):
class Meta:
model = Product
fields = ['name','email','body','product']
invalid in code line :
fields = ['name','email','body','product'] #---- NOT WORK !!!
, but if i change above code to :
fields = "__all__" # ----it is WORKing ok without any problem !!
question : what is the error? I am not need all the fields in the Product model (like active boolean field), I need only 'name','email','body','product' fields .
According to the error and the code you provided the main problem is that you made a mistake in chosing model in serializer:
class OpinionModelForm(ModelForm):
class Meta:
model = Product
fields = ['name','email','body','product']
Serializer name is OpinionModelForm and listed fields belong to Opinion so I guess you actually wanted to serialize Opinion and no Product as you defined at this line:
model = Product
Simply change it to:
model = Opinion

Django - Get parent object with children's object

I'm new to Django so I might miss the answer for this one because of terminology.
I am trying to get parent object with children objects, I've got:
#models.py
class Category(models.Model):
name = models.CharField(max_length=255)
sub_category = models.ForeignKey(SubCategory)
title = models.CharField(max_length=255, null=True)
#serializer.py
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = '__all__'
#views.py
Product.objects.all().filter(sub_category__category_id=category_id).select_related()
products_serializer = ProductSerializer(products, many=True)
return Response({
'data': products_serializer.data
})
I am trying to get parent category object within the children objects I've already got.
Thanks in advance :)
You already have your parent object, you can access it through each of your objects:
products = Product.objects.all().filter(sub_category__category_id=category_id)
for product in products:
parent = product.parent # You already have it
For better performance change your query to
Product.objects.all().filter(sub_category__category_id=category_id).select_related('parent')
As commented you can do it through serializers:
class ProductItemSerializer(serializers.ModelSerializer):
class Meta:
model = ProductItem
class ProductSerializer(serializers.ModelSerializer):
product_items = ProductItemSerializer(many=True, read_only=True)
class Meta:
model = Product
class CategorySerializer(serializers.ModelSerializer):
products = ProductSerializer(many=True, read_only=True)
class Meta:
model = Category
Now just get categories and products and items will be nested

django: how does manytomanyfield with through appear in admin?

As stated in the title how does manytomanyfield with through appear in the admin site?
class SchoolClass(models.Model):
id = models.AutoField(primary_key = True)
class_name = models.TextField()
level = models.IntegerField()
taught_by = models.ManyToManyField(User,related_name="teacher_teaching",through='TeachSubject')
attended_by = models.ManyToManyField(User,related_name='student_attending')
def __unicode__(self):
return self.class_name
class Meta:
db_table = 'classes'
class TeachSubject(models.Model):
teacher = models.ForeignKey(User)
class_id = models.ForeignKey(SchoolClass)
subject = models.ForeignKey(Subject)
In the admin site, for the model SchoolClass, I have a field for attending students, but not the teachers.
You should use InlineModelAdmin. Docs.
class TeachSubjectInline(admin.TabularInline):
model = TeachSubject
extra = 2 # how many rows to show
class SchoolClassAdmin(admin.ModelAdmin):
inlines = (TeachSubjectInline,)
admin.site.register(SchoolClass, SchoolClassAdmin)