Django Hide Posts(objects) in UI per User without affecting main model

Viewed 300

I have an app that display all newsitems having model like:

class NewsItem(models.Model):
    url = models.CharField(max_length=500, default="",unique=True)
    title = models.CharField(max_length=500, default="")
    hacker_news_url = models.CharField(max_length=500, default="")
    posted_on = models.DateTimeField(default=datetime.now)
    upvote_count = models.IntegerField(default=0)
    comment_count = models.IntegerField(default=0)

UI: enter image description here

I had already setup the default django authentication to view this page. The ui has hide button for each post. So the problem is if the logged in user hides the post, it must be hidden for that user only (even after page refresh) without deleting from NewsItem Model/Table. How to do that? Help Please!

This is my views.py:

@login_required(login_url='/accounts/login')
def index(request):
    context={'news_items':NewsItem.objects.all().order_by('posted_on')}
    return render(request, "hello.html", context)
1 Answers

You need to set up some kind of "Proof Of Reading" some where. One way of doing this, is adding up an M2M between NewsItem and User model.

As soon as a user click on "Mark As Read", you do something like NewsItem.users.add(request.user), and you can filter your NewsItem in your index view.

class NewsItem(models.Model):
    url = models.CharField(max_length=500, default="",unique=True)
    title = models.CharField(max_length=500, default="")
    hacker_news_url = models.CharField(max_length=500, default="")
    posted_on = models.DateTimeField(default=datetime.now)
    upvote_count = models.IntegerField(default=0)
    comment_count = models.IntegerField(default=0)

    users = models.ManyToManyField('your-user-model', verbose_name="Readers", related_name="reads")

After 'makemigrations/migrate', In your views:

@login_required(login_url='/accounts/login')$
def index(request):
    news = NewsItem.objects.exclude(users=request.user).order_by('posted_on')
    context={'news_items':news}
    return render(request, "hello.html", context)

@login_required(login_url='/accounts/login')
@require_http_methods(['POST'])
def read(request, news_item_pk):
    """
    This is the most basic example.
    If you use AJAX Calls, Do not forget to add your CSFR;
    """
    news = get_object_or_404(NewsItem, pk=news_item_pk)
    news.users.add(request.user)
    return HttpResponse()

Finally in your views, you should add your read view

Related