Как отобразить последние элементы для персонализации в веб-приложении? - PullRequest
0 голосов
/ 07 декабря 2018

В GitHub вы заметите, что когда вы хотите сослаться на существующие проблемы или пометить проблему в проектах, GitHub интеллектуально покажет вам самые последние элементы, которые вы посетили недавно.

Пример отображения последних проектов впорядок последнего посещения

enter image description here

Пример отображения последних проблем в порядке последнего посещения enter image description here

Я использую django для создания веб-приложения, и мне нравится включать ту же функцию.

У меня есть две идеи, но ни одна из них еще не реализована:

1.Одна гигантская таблица, хранящая все посещения отдельных пользователей

Должна ли я иметь одну гигантскую таблицу, в которой хранятся все элементы, которые посещают все пользователи?Если так, то как мне тогда соединить это с основной таблицей, по которой я должен искать, чтобы произвести сортировку правильно?

2.Добавьте столбец visited к отдельным основным таблицам

Я не могу явно добавить новый столбец даты и времени, который называется «посещен», в основную таблицу, поскольку это будет означать, что персонализация отсутствует.

Чего мне не хватает в плане понимания?

Также справедливо ли предположить, что мне нужно ограничить количество самых последних элементов, хранящихся на пользователя?

То есть, используя пример GitHub, можно хранить не более 5 самых последних проектов или проблем на пользователя.

Ответы [ 3 ]

0 голосов
/ 15 декабря 2018

1.Одна гигантская таблица, в которой хранятся все посещения отдельных пользователей

Вот как я мог бы реализовать это:

class Visit(models.Model):
    user = ForeignKey(User, related_name="recent_visits")
    item = ForeignKey(Item, related_name="visitors")
    last_visited = DateTimeField()

Затем в сериализаторе User вы можетеиметь SerializerMethodField, чтобы соответствовать определенному количеству недавно посещенных предметов, например:

class VisitSerializer(models.Model):
    item = YourItemSerializer()

    class Meta:
        model = Visit
        fields = ['item', 'last_visited']


class UserSerializer(serializers.ModelSerializer):
    recent_visits = serializers.SerializerMethodField()

    def get_items(self, obj):
        # you could also get the value of 5 from a constant or your settings or 
        # even the API itself
        items = Item.recent_visits.filter(user=obj)[:5]
        serializer = VisitSerializer(instance=items, many=True)
        return serializer.data

Однако это может быть излишним, если вы хотите сохранить только небольшой список недавно посещенных предметов и нене хочу иметь никакой логики, основанной на расширенной истории посещений пользователя.

Хранение информации об элементе в пользовательской модели

Если вы хотите показать только определенную информацию об элементе (например, идентификатор, имя и т. Д.), Вы можете сохранить эту информациюв JSONField в пользовательской модели и посещайте элемент только тогда, когда пользователю нужны его детали.Вы можете сохранить запросы к базе данных таким способом, но вам придется немного поспорить с JSON, когда пользователь посещает или повторно посещает элемент.

Этот подход также будет зависеть от того, как часто изменяются поля Item, которые вы хотите сохранить в модели User, или от того, удаляется ли элемент вообще.

0 голосов
/ 18 декабря 2018

Я думаю, что использование Visit в качестве отдельной модели является хорошим выбором для сохранения разделения.

Можно просто ограничить возвращаемый результат, например User.recent_visits.all () [: 5] в интерфейсе DRF.

Приведенное ниже решение гарантирует, что User.recent_visits.all () вернет 5 последних посещений без нарезки и избежит огромного списка.

«Шаблон» I 'Мы успешно использовали в прошлом, что примерно соответствует этому контексту:

class VisitQuerySet(models.QuerySet):
    MAX_LRV = 5 # Max Last Recent Visits

    def add_item(self, user, item):
        with transaction.atomic():
            # to avoid duplicate items
            lrv, created = self.get_or_create(user=user, item=item)

            if not created:
                lrv.save()  # update timestamp
                return lrv

            self.prune_lrv(user)
        return lrv

    def prune_lrv(self, user):
        # One example of how to clean up the recent visits
        qs = self.filter(user=user)
        if qs.count() > self.MAX_LRV:
            pending_delete = qs[self.MAX_LRV:]
            self.filter(user=user, pk__in=pending_delete).delete()


class Visit(models.Model):
    class Meta:
        ordering = ('-last_visited',) # ordering important

    user = ForeignKey(User, related_name="recent_visits")
    item = ForeignKey(Item, related_name="visitors")
    last_visited = DateTimeField(auto_now=True)

    objects = VisitQuerySet.as_manager()


 # Adding a item
 Visit.objects.add_item(user, item)

 #Get last 5 recent visits
 request.user.recent_visits.all()

Список поддерживается при добавлении новых элементов, легко изменить MAX_LRV и должен быть простым, чтобы избежать дублирования (в зависимости от того, какэлемент создается в этом сценарии).

0 голосов
/ 12 декабря 2018

Не будет ли работать таблица, содержащая FK для пользователя, URL-адрес и дату последнего посещения?Затем создайте API (drf), чтобы вернуть самые последние 5 для пользователя:

visits.objects.filter(user=request.user).order_by('-datetime_visited')[:5]

Он станет большим, возможно, вы можете ограничиться сохранением только 5 на пользователя и удалять при вставке.В каждом запросе get для каждой страницы вы могли бы:

last = visits.objects.filter(user=request.user).order_by('datetime_visited').first()
last.delete()
visits.objects.create(user=request.user, url=page_url, datetime_visited=datetime.datetime.now())

Вероятно, хорошей идеей было бы также добавить туда обычную чистку: Ограничить число записей в модели, которые могут иметь значение для пользователя

...