Django admin how to order by model property? - django

I have a model with property and I want to be able to sort instances in the admin panel by that property.
My model with _points property:
class CustomUser(models.Model):
inviter = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True)
#property
def _points(self):
res = CustomUser.objects.filter(inviter_id=self.id).count()
return res
My admin:
class CustomUserAdmin(admin.ModelAdmin):
list_display = ['inviter', '_points']
class Meta:
model = CustomUser
the _points field is displayed in the admin panel, but I cannot sort entries by it

It is not possible to order a queryset by a property. You can only order it by database fields

Related

How to see objects of manytomany field by related_name in admin page?

I have these two models:
class User(AbstractUser):
is_teacher = models.BooleanField(default=False, null=False)
class Course(models.Model):
teacher = models.ForeignKey(User, on_delete=models.CASCADE, related_name='teacher_courses')
students = models.ManyToManyField(User, blank=True, related_name='student_courses')
Course model has a ManyToMany field and a ForeignKey to User model. In django's admin page, you are able to see a course's student/teacher. Is there a way to make it as you can have a list of a user's courses in admin page to see/add/remove courses for a user?
You can define a callable on your ModelAdmin class and add it to list_display. To make the courses editable on an user's page use sub classes of InlineModelAdmin.
class TeacherCourseInlineAdmin(admin.TabularInline):
model = Course
fk_name = "teacher"
class StudentCourseInlineAdmin(admin.TabularInline):
model = Course
fk_name = "student"
class UserAdmin(admin.ModelAdmin):
list_display = ("username", "teacher_courses")
inlines = [TeacherCourseInlineAdmin, StudentCourseInlineAdmin]
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).prefetch_related("teacher_courses")
#admin.display(description='Courses')
def teacher_courses(self, user):
return [c.name for c in user.teacher_courses.all()]
Note that it makes sense to override ModelAdmin.get_queryset() to add a call to prefetch_related() so that Django fetches all related courses in one extra query instead of performing one additional query for every user object.

How to display table with group same values in the column on Django Admin

I have a Comment table on Django Admin:
models.py
class Comment(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
item = models.ForeignKey(Listing, on_delete=models.CASCADE)
comment = models.TextField(max_length=250)
datetime = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.item}"
admin.py
class CommentInline(admin.TabularInline):
model = Comment
class ItemAdmin(admin.ModelAdmin):
inlines = [
CommentInline,
]
#admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
list_display = ('item','user','comment','datetime',)
list_filter = ('item',)
And I want to edit this table with the same values item that will display with a single row, and then after clicked on it will display another table contain user comment and datetime .
Thanks so much for any advice to me !!!
If item is a foreign key to one of your other models, you should be able to use an InlineModelAdmin object to create a tabular inline view of the user/comment/datetime using the item's admin view.
See
https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#inlinemodeladmin-objects for reference.
In your case you may end up with something like:
class CommentInline(admin.TabularInline):
model = Comment
fields = ('user', 'comment', 'datetime')
class ItemAdmin(admin.ModelAdmin):
inlines = [
CommentInline,
]
If item is a models.CharField though I don't think you can do it with the Django Admin as provided by Django.

DRF ManytoMany filtering on related model, in subquery?

There are two models, a Page model and a Banner model, which are manyToMany related.
The parameters API is twitched, which returns a list of pages and banners for each page. The Banner model has a field is_show by which you need to additionally filter the list of banners, i.e. in the admin panel, the banner can be selected for the model, but if is_show = False, then you do not need to return it to the API.
views
class PagesListView(generics.ListAPIView,
viewsets.GenericViewSet):
queryset = Page.objects.all()
serializer_class = PageSerializer
models
class Banner(models.Model):
title = models.CharField(verbose_name='Заголовок', max_length=255, null=True, blank=True)
is_show = models.BooleanField(verbose_name='Управление отображением', null=False)
pages = models.ManyToManyField(
Page, blank=True, related_name='banners')
class Page(models.Model):
name = models.CharField(max_length=255, null=True, blank=True)
serializers
class BannerSerializer(serializers.ModelSerializer):
class Meta:
model = Banner
fields = '__all__'
class PageSerializer(serializers.ModelSerializer):
banners = BannerSerializer(read_only=True, many=True)
class Meta:
model = Page
fields = '__all__'
The question is how to filter Banner by is_show field?
If you just override the queryset for the view like this:
queryset = Page.objects.filters(banners__is_show=True)
then this is not the desired behavior. In this way, I am filtering the Page list, and I need to "wedge" into filtering the Banner list.
You can do it using related_name with prefetch_related
For ex:
queryset = Page.objects.all().prefetch_related(
Prefetch('banners', queryset=Banner.objects.filter(is_show=True)))

How do you display fields from a related model in admin.py?

I have the following models:
class Property(models.Model):
user = models.ForeignKey(User)
id = models.CharField(max_length=20, null=True)
class Property_Value(models.Model):
id = models.ForeignKey(Property)
amount = models.DecimalField(max_digits = 10, decimal_places
How do I access the Property_Value.amount via Property on the admin page?
I have this so far...
class PropertyAdmin(admin.ModelAdmin):
list_display = ('id', 'user', 'property_value')
def property_value(self, obj):
return obj.id.amount
class Meta:
model = Property
admin.site.register(Property, PropertyAdmin)
You're interacting, in that instance, with a Property object (since you defined that in the Meta) - syntax is the same as elsewhere in Django. So it would be obj.property_value.amount. If you're using PyCharm, you can get autocomplete for the field by telling PyCharm what 'obj' is, like so:
def property_value(self, obj: Property):

admin inlines over one2one field

I have three django models and I want to edit item's instances on order's page. Is it possible?
#models.py
class Item(models.Model):
name = models.CharField(max_length = 128)
cart = models.ForeignKey('Cart')
class Cart(models.Model):
number = models.IntegerField()
class Order(models.Model):
cart = models.OneToOneField('Cart')
#admin.py
ItemInline(admin.TabularInline):
model = Item
CartInline(admin.TabularInline):
model = Cart
Order(ModelAdmin):
inlines = (CartInline,) # I need ItemInline here...
Make it so Order is an inline of Cart, rather than the other way around?