M
M
mkone1122020-12-12 15:53:46
Django
mkone112, 2020-12-12 15:53:46

How to change the display order of ManyToManyField elements?

There is an image model that users can like.

class Image(models.Model):
    
    image = models.ImageField(upload_to='images/%Y/%m/%d/')

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        related_name='images_created',
        on_delete=models.CASCADE
    )
    
    # Пользователи лайкнувшие изображение.
    users_liked = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name='images_liked',
        blank=True
    )

    title = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    url = models.URLField()
    slug = models.SlugField(max_length=200, blank=True)
    created = models.DateField(auto_now_add=True, db_index=True)

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super().save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('images:detail', args=(self.id, self.slug))

I can get a list of all users who liked an image like this:
from .models import Image
image = Image.objects.get(pk=1)

image.users_liked.all()

>> <QuerySet [<User: first_fake_user>, <User: second_fake_user>]>


Tell me how to make each like have a timestamp, and image.users_liked.all()display users in chronological order, according to the time of the like?

Unsuccessful attempt:

Added an intermediate Like model with an extra timestamp field, and gave it `ordering`, but to no avail:
class Image(models.Model):

    image = models.ImageField(upload_to='images/%Y/%m/%d/')

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        related_name='images_created',
        on_delete=models.CASCADE
    )

    users_liked = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        through='Like',
        related_name='images_liked',
        blank=True
    )

    title = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    url = models.URLField()
    slug = models.SlugField(max_length=200, blank=True)
    created = models.DateField(auto_now_add=True, db_index=True)

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super().save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('images:detail', args=(self.id, self.slug))


class Like(models.Model):

    image = models.ForeignKey(Image, on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    liked_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ('liked_at',)


It seems that the `ordering` parameter does not affect anything (I think this was expected):
image.users_liked.all()  >> <QuerySet [<User: first_fake_user>, <User: second_fake_user>]>

...
    class Like(models.Model):
        ...
        class Meta:
            ordering = ('-liked_at',)

image.users_liked.all()  >> <QuerySet [<User: first_fake_user>, <User: second_fake_user>]>

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dr. Bacon, 2020-12-12
@bacon

and than order_by did not arrange?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question