Подреждане по персонализирано поле за модел в django

Опитвам се да добавя допълнително потребителско поле към django модел. Имах доста трудно време да разбера как да направя следното и ще дам награда от 150 точки за първия напълно правилен отговор, когато стане наличен (след като стане наличен -- вижте като справка Подобряване на кода за изглед на Python/django).

Имам следния модел с персонализирана дефиниция, която връща брой видеоклипове за всеки потребител --

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
    positions = models.ManyToManyField('Position', through ='PositionTimestamp', blank=True)

    def count(self):
        from django.db import connection
        cursor = connection.cursor()
        cursor.execute(
        """SELECT (
            SELECT COUNT(*)
                FROM videos_video v
                WHERE v.uploaded_by_id = p.id
                OR EXISTS (
                    SELECT NULL
                    FROM videos_videocredit c
                    WHERE c.video_id = v.id
                    AND c.profile_id = p.id
                )
            ) AS Total_credits
            FROM userprofile_userprofile p
            WHERE p.id = %d"""%(int(self.pk))
        )
        return int(cursor.fetchone()[0])

Искам да мога да поръчам по брой, т.е. UserProfile.objects.order_by('count'). Разбира се, не мога да направя това, затова задавам този въпрос.

Преди се опитах да добавя персонализиран диспечер на модели, но проблемът с това беше, че също трябва да мога да филтрирам по различни критерии на модела UserProfile: По-конкретно, трябва да мога да направя: UserProfile.objects.filter(positions=x).order_by('count'). Освен това трябва да остана в ORM (не мога да имам необработен sql изход) и не искам да поставя логиката на филтриране в SQL, защото има различни филтри и ще изисква няколко оператора.

Как точно бих направил това? Благодаря ти.


person David542    schedule 24.07.2011    source източник
comment
не бихте ли могли да използвате нещо като допълнителния модификатор на набор от заявки? docs.djangoproject.com/en/dev/ref/models/querysets /#допълнително   -  person niklasdstrom    schedule 24.07.2011
comment
UserProfile.objects.extra(select={'count':SELECT (SELECT COUNT(*) FROM videos_video v WHERE v.uploaded_by_id = p.id OR EXISTS (SELECT NULL FROM videos_videocredit c WHERE c.video_id = v.id AND c. profile_id = p.id)) AS Total_credits FROM userprofile_userprofile p където p.id=%d%(...)}). Как бих могъл да получа profile.id за всеки, така че да мога да коментирам резултата към всеки потребителски профил и след това да преброя order_by?   -  person David542    schedule 24.07.2011
comment
ps: можете да поставите отговора в истински отговор за наградата, дори ако това е синхрон, който трябва да направите.   -  person David542    schedule 24.07.2011


Отговори (3)


"не бихте ли могли да използвате нещо като модификатора на набор от заявки "допълнителен"?"

вижте документи

Първоначално не поставих това в отговор, защото не бях сигурен, че наистина ще работи или дали е това, от което се нуждаете - беше по-скоро като тласък в (надявам се) правилната посока.

в документите на тази страница има пример

запитване

Blog.objects.extra(
    select={
        'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id'
    },
)

резултатен sql

SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) AS entry_count
FROM blog_blog;

Може би правите нещо подобно и осъществявате достъп до потребителския идентификатор, който в момента имате като p.id като appname_userprofile.id

Забележка:

Просто го хвърлям, така че опитайте да си поиграете малко. може би използвайте обвивката, за да изведете заявката като sql и да видите какво получавате.

person niklasdstrom    schedule 24.07.2011

Моята реакция е, че се опитваш да отхапеш по-голяма хапка, отколкото можеш да сдъвчеш. Разбийте го на хапки, като си дадете повече примитиви за работа.

Искате да създадете тези две части поотделно, за да можете да ги използвате:

  • Получава ли този потребител кредит за този видеоклип? връщане на булево
  • За колко видеоклипа този потребител получава кредит? връщане вътр

След това използвайте комбинация от @property, мениджъри на модели, набори от заявки и методи, които правят най-лесно да изразите това, от което се нуждаете.

Например можете да прикачите „кредит“ към видео модела, който взема потребителски параметър, или потребителския модел, който взема видео параметър, или „кредитен“ мениджър на потребителите, който добавя брой видеоклипове, за които те имат кредит.

Не е тривиално, но не би трябвало да е твърде сложно, ако работите за това.

person John Mee    schedule 28.07.2011

модели:

class Positions(models.Model):
    x = models.IntegerField()

    class Meta:
        db_table = 'xtest_positions'

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
    positions = models.ManyToManyField(Positions)

    class Meta:
        db_table = 'xtest_users'

class Video(models.Model):
    usr = models.ForeignKey(UserProfile)
    views = models.IntegerField()

    class Meta:
        db_table = 'xtest_video'

резултат:

test = UserProfile.objects.annotate(video_views=Sum('video__views')).order_by('video_views')
for t in test:
    print t.video_views

документ: https://docs.djangoproject.com/en/dev/topics/db/aggregation/

Това или искате, или съм разбрал напълно погрешно!.. Както и да е... Надявам се да помогне!

person StefanNch    schedule 28.07.2011