Saturday, April 30, 2016

How in Django, made count objects in through model by condition, for using in the admin as sortable field?

I need will create two sortable fields in Django admin by values in Though-Model.
    
-----------------
My models.py
----------------
    
    
    from django.core.urlresolvers import reverse
    from django.utils.translation import ugettext_lazy as _
    from django.db import models
    from django.conf import settings
    
    from autoslug import AutoSlugField
    
    from mylabour.models import TimeStampedModel
    from mylabour.utils import CHOICES_LEXERS
    
    
    class Snippet(TimeStampedModel):
        """
    
        """
    
        title = models.CharField(_('Title'), max_length=200)
        slug_title = AutoSlugField(populate_from='title', unique_with='author', always_update=True, sep='__')
        description = models.TextField(_('Decription'))
        code = models.TextField(_('Code'))
        # tags
        lexer = models.CharField(_('Lexer of code'), max_length=50, choices=CHOICES_LEXERS)
        author = models.ForeignKey(
            settings.AUTH_USER_MODEL,
            verbose_name=_('Author'),
            related_name='snippets',
            on_delete=models.DO_NOTHING,
        )
        voted_users = models.ManyToManyField(
            settings.AUTH_USER_MODEL,
            verbose_name=_('Voted users'),
            related_name='voted_users',
            through='VoteUserInSnippet',
            through_fields=('snippet', 'user'),
        )
    
        class Meta:
            db_table = 'snippet'
            verbose_name = _("Snippet")
            verbose_name_plural = _("Snippets")
            get_latest_by = 'date_created'
            ordering = ['date_created']
    
        def __str__(self):
            return '{0.title}'.format(self)
    
        def get_absolute_url(self):
            return reverse('app_snippets:snippet', kwargs={'slug_title': self.slug_title})
    
    
    class VoteUserInSnippet(models.Model):
    
        user = models.ForeignKey(
            settings.AUTH_USER_MODEL,
            on_delete=models.CASCADE,
            verbose_name='User',
            limit_choices_to={'is_active': True},
        )
        snippet = models.ForeignKey('Snippet', on_delete=models.CASCADE, verbose_name='Snippet')
        is_useful = models.BooleanField(_('Is useful'))
        date_voting = models.DateTimeField(_('Date voting'), auto_now_add=True)
    
        def __str__(self):
            return _('User "{0.user}" found this snippet as {0.is_useful}').format(self)
    
    
    class SnippetComment(TimeStampedModel):
    
        text_comment = models.TextField(_('Text comment'))
        snippet = models.ForeignKey('Snippet', related_name='comments', verbose_name=_('Snippet'), on_delete=models.CASCADE)
        author = models.ForeignKey(
            settings.AUTH_USER_MODEL,
            related_name='comments_snippet',
            verbose_name=_('Author'),
            on_delete=models.DO_NOTHING,
        )
    
        class Meta:
            db_table = 'snippet_comment'
            verbose_name = "Comment of snippet"
            verbose_name_plural = "Comments of snippet"
            get_latest_by = 'date_created'
            ordering = ['snippet', 'date_created']
    
        def __str__(self):
            return _('Comment from "{0.author}" on snippet "{0.snippet}"').format(self)
    
-----------
My admin.py
-----------
    
    
    from django.db.models import Count
    from django.utils.translation import ugettext_lazy as _
    from django.contrib import admin
    
    from .models import *
    
    
    class SnippetCommentInline(admin.StackedInline):
        '''
        Stacked Inline View for SnippetComment
        '''
    
        model = SnippetComment
        min_num = 0
        max_num = None
        extra = 1
        fk_name = 'snippet'
    
    
    class VoteUserInSnippetInline(admin.TabularInline):
        '''
        Stacked Inline View for VoteUserInSnippet
        '''
    
        model = VoteUserInSnippet
        min_num = 0
        max_num = None
        extra = 1
    
    
    class SnippetAdmin(admin.ModelAdmin):
        '''
        Admin View for Snippet
        '''
    
        list_display = (
            'title',
            'author',
            'lexer',
            'get_count_good_reply',
            'get_count_bad_reply',
            'get_count_replies',
            'is_new',
            'date_modified',
            'date_created',
        )
        list_filter = (
            ('author', admin.RelatedOnlyFieldListFilter),
            'lexer',
            'date_modified',
            'date_created',
        )
        inlines = [
            SnippetCommentInline,
            VoteUserInSnippetInline,
        ]
        search_fields = ('title',)
    
        def get_queryset(self, request):
            qs = super(SnippetAdmin, self).get_queryset(request)
            qs = qs.annotate(
                count_comments=Count('comments', distinct=True),
                count_voted_users=Count('voted_users', distinct=True),
            )
            return qs
    
        def get_count_comments(self, obj):
            return obj.count_comments
        get_count_comments.admin_order_field = 'count_comments'
        get_count_comments.short_order = _('Count comments')
    
        def get_count_good_replies(self, obj):
            return VoteUserInSnippet.objects.filter(snippet=obj,     is_useful=True).count()
        # get_count_good_replies.admin_order_field = ''
        get_count_good_replies.short_order = _('Count good replies')
    
        def get_count_bad_replies(self, obj):
            return VoteUserInSnippet.objects.filter(snippet=obj, is_useful=False).count()
        # get_count_bad_replies.admin_order_field = ''
        get_count_bad_replies.short_order = _('Count bad replies')
    
        def get_count_replies(self, obj):
            return obj.count_voted_users
        get_count_replies.admin_order_field = 'count_voted_users'
        get_count_replies.short_order = _('Count replies')
    
    
    class VoteUserInSnippetAdmin(admin.ModelAdmin):
        '''
        Admin View for VoteUserInSnippet
        '''
        list_display = ('snippet', 'user', 'is_useful', 'date_voting')
        list_filter = (
            ('user', admin.RelatedOnlyFieldListFilter),
            ('snippet', admin.RelatedOnlyFieldListFilter),
            'is_useful',
            'date_voting',
        )
    
    
    class SnippetCommentAdmin(admin.ModelAdmin):
        '''
            Admin View for SnippetComment
        '''
        list_display = ('snippet', 'author', 'is_new', 'date_modified', 'date_created')
        list_filter = (
            ('author', admin.RelatedOnlyFieldListFilter),
            ('snippet', admin.RelatedOnlyFieldListFilter),
            'date_modified',
            'date_created',
        )



Methods get_count_bad_replies() and get_count_bad_replies() right worked but is not sortable. 
May be who known have resolve this problem.

Thanks.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/140f0b6b-2985-4a32-abc9-762edc199931%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment