get_full_path in django model method - python

I'm just starting with django (and python too, to be honest)
I am trying to get a model method that would cut the self.slug from current URL and return it to template.
This is the method I tried:
class Category(models.Model):
...
def remove_filter(self):
url = HttpRequest.get_full_path()
slug = '/' + self.slug
return url.replace(slug, '')
But as you can imagine, it doesn't work.
Template's snippet:
{% for object in active_filters %}
<li><i class="icon-remove"></i>{{ object }}</li>
{% endfor %}
My core goal here is to have a front-end icon with a url altered by removing current object's slug.
I have no idea how to do it through views, but I'm open to any suggestions.
def category_page(request, url):
slugs = url.split('/')
active = Category.objects.filter(slug__in=slugs)
sorted_slugs = []
for i in active:
sorted_slugs.append(i.slug)
if slugs != sorted_slugs:
url = '/'.join(sorted_slugs)
return redirect('http://127.0.0.1:8000/catalog/' + url)
inactive = Category.objects.exclude(slug__in=slugs)
return render(request, 'category.html', {'active_filters': active,
'inactive_filters': inactive})
Thanks.

You can send a list of all active slugs to the template and then build a custom template filter to construct the modified url.
views.py
# Send your list of active slugs to the template
return render(request, 'category.html', {
'active_filters': active,
'inactive_filters': inactive,
'slugs': slugs,
})
tags_and_filters.py
import copy
from django import template
register = template.Library()
#register.filter(name='remove_filter')
def remove_filter(category, slugs):
copied_slugs = copy.copy(slugs)
slug = category.slug
if slug in copied_slugs:
copied_slugs.remove(slug)
return '/'.join(copied_slugs)
your template
{% for object in active_filters %}
<li>
<i class="icon-remove"></i>{{ object }}
</li>
{% endfor %}

Your remove_filter method has no access to the current request. HttpRequest is the class, not the current request instance.
I suggest that you rewrite remove_filter as a custom tag or filter. That way your function can access the category and request instance. You will have to activate the request template context processor in your settings as well.

Related

How to render differently a django model object field on a html page?

My model object have a IntegerField but I want to be able to render it differently on my html page, like lets say the object IntegerField is 500000 I want to render it as 500 000$ on my html page. So Add a space before the last 3 number and add a $ at the end.
I have a models with a IntegerField that look like this
class Listing(models.Model):
listing_price = models.IntegerField(max_length=100)
In my view I extract the models like this
def home(request):
listing_object = Listing.objects.all()
context = {
"listing_object": listing_object,
}
return render(request, "main/index.html", context)
I render the data like this
{% for listing in listing_new_object %}
{{listing.listing_price}}
{% endfor %}
You have two options:
Manipulate the context to make a list of tuples:
context = {
"listing_object": [(listing, f'{listing.listing_price:,}'.replace(",", " ")) for listing in listing_object]
}
then in your template:
{% for _, price in listing_new_object %}
{{price}}
{% endfor %}
The other option is to make a Django template filter
{{ listing.listing_price|price_format }}
from django import template
register = template.Library()
def price_format(value):
return f'{value:,}'.replace(",", " ")
register.filter(price_format)

How can i call class function thats insert row into db properly from my django template?

Hellow, I am noob and I make instagram followers scraper on Django.
I make a function that should add 1 (only 1 cos it works really slow) new follower in to db which takes from already working sсraping functions and place it into class.
class ListOfFollowers(ListView):
model = Followers
context_object_name = 'followers_of'
template_name = 'insta/followers.html'
def get_follower(self, username):
loader = instaloader.Instaloader()
loader.login('***', '***')
profile = instaloader.Profile.from_username(loader.context, username)
followers = profile.get_followers()
followers_tuple = tuple(followers)
i = random.randint(0, len(followers_tuple) - 1)
login = followers_tuple[i].username
photo = followers_tuple[i].get_profile_pic_url()
url = f'https://www.instagram.com/{login}/'
mutual_subscription = followers_tuple[i] in profile.get_followees()
res = {'login': login, 'photo': photo, 'url': url, 'mutual_subscription': mutual_subscription}
return res
def add_followers(self):
username = WhoFollow.objects.get(follow_on__contains=self.kwargs['follow_id']).title
context = None
while not context:
try:
context = get_follower(username)
except:
next
context.update({'follow_on': self.kwargs['follow_id']})
res = Followers(context)
res.save()
def get_queryset(self):
return Followers.objects.filter(follow_on=self.kwargs['follow_id'])
function calls add_followers (try block is just because its not always working from 1st try)
My models
class WhoFollow(models.Model):
title = models.CharField(max_length=255)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('follow', kwargs={'follow_id': self.pk})
class Followers(models.Model):
login = models.CharField(max_length=255)
photo = models.ImageField(upload_to="photos/", blank=True)
url = models.URLField()
mutual_subscription = models.BooleanField(default=False)
time_add = models.DateTimeField(auto_now_add=True)
time_unfollow = models.DateTimeField(blank=True)
follow_on = models.ForeignKey(WhoFollow, on_delete=models.PROTECT)
def __str__(self):
return self.login
And my template
{% extends 'insta/Base.html' %}
{% block content %}
<h1>Who we find</h1>
<ul>
{% for l in object_list %}
<li>
<h5>{{l.login}}</h5>
</li>
{% endfor %}
</ul>
<!-- from there i dont understand what i should do too -->
<form action="{% url views.ListOfFollowers.}">
<button type="submit" onclick="">add another 1</button>
</form>
{% endblock %}
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', Home.as_view(), name='home'),
path('add/', AddWhoFollow.as_view(), name='add'),
path('follow/<int:follow_id>', ListOfFollowers.as_view(), name='follow'),]
Sorry for too many code but my head already broken on this task.
There are some issues with your code:
First, you have added the two methods get_follower() and add_followers() to the your ListView, but it is unclear how (if at all) they are called. It looks to me like you might be misunderstanding the concept of the ListView. The purpose of the ListView is to render a list of objects, not add something. So instead you want to create a new view for adding followers. You can just define a simple function view for that, does not have to be a CBV.
Second, each view needs to have it's own URL defined. You did not post your urls.py, but I suppose {% url views.ListOfFollowers.} in the template will not work. Instead, you need to define a URL name in your urls.py (one for each view) and out that in your template.
I was totaly misunderstand the concept of the CBV.
The answer is that i should do it inside CreateVeiw after form validation where i choose which login to scrap.
There is result:
class AddFollowers(CreateView):
form_class = AddFollower
model = Followers
template_name = 'insta/add_follower.html'
def get_success_url(self):
return reverse_lazy('home')
def form_valid(self, form):
# Here is a body of scraping script where i creating a list of objects to add in db
Followers.objects.bulk_create(objs=res)
return HttpResponseRedirect(f'http://127.0.0.1:8000/)

Populate list in Django using view

I have the following function to read news headlines into a Python list:
import requests
def us_news_articles():
url = 'https://newsapi.org/v2/top-headlines?country=us&apiKey=###
source = requests.get(url)
data = source.json()
us_news_articles_list = []
for article in data['articles']:
us_news_articles_list.append(article)
return us_news_articles_list
This function works, and I've verified it.
Now I want to be able to use this to populate HTML li items
I have the following views built:
def viz(request):
return render(request, 'resume/viz.html')
class USNewsArticles(TemplateView):
template_name = 'viz'
def get_context_data(self, *args, **kwargs):
context = {
'articles': us_news_articles(),
}
return context
My URL looks like this
path('viz/', views.viz, name='viz')
And in my HTML file, I have the following:
<ul>
{% for article in articles %}
<li>{{ article.title }}</li>
<ul>
<li>{{ article.description }}</li>
</ul>
{% endfor %}
</ul>
However, when I deploy the website, I get no list. I believe it's an issue with the view, but I am not well-versed enough in understand views and functions to understand why it will not populate the li items
Your URLs are routed to your viz view, which just renders an empty template (viz.html). I think what you meant to do is this:
class USNewsArticles(TemplateView):
template_name = 'resume/viz.html'
def get_context_data(self, *args, **kwargs):
context = {
'articles': us_news_articles(),
}
return context
And your URL:
path('viz/', USNewsArticles.as_view())
TemplateView is a helper where you specify the template file directly, and it supplies the appropriate GET handler. - no need for an intermediate def myview function. In fact, the beauty of Class-Based Views is it writes a lot of the boilerplate for you. Unless you are customizing the behavior, you generally don't have to write methods that return Responses by hand.

How to pass a non DB object from a template to a view outside the URL with Django ?

I'm fairly new to Django. I'm writing an app that displays articles using RSS. I want users to be able to react to any given article.
On the index, I display the latest articles dynamically (they are not stored in the DB).
View :
class IndexView(generic.ListView):
template_name = 'publisher/index.html'
def get_context_data(self, **kwargs):
context = super(IndexView,self).get_context_data(**kwargs)
feeds = feedparser.parse('http://www.foo.com/rss/news.xml')
context['feeds'] = feeds
return context
Template :
{% for entry in feeds.entries %}
<li>
<a target="_blank" href="{{entry.link}}">{{entry.title}}</a>
I want to react
</li>
{% endfor %}
This works so far. I have a link next to each of these articles that should call the RSSReactView and display the article title, abstract, and a form to react. I don't want the article to be saved anywhere if the reaction is not posted, and thus I don't want any parameter to be included in the URL of the reaction form.
URL :
app_name = 'publisher'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^new_rss/react/$', views.RSSReactView.as_view(), name='rss_react'),
]
View :
class RSSReactView(generic.CreateView):
model = ReactionArticle
form_class = ReactionForm
template_name = 'publisher/react.html'
def get_context_data(self, **kwargs):
context = super(ReactView,self).get_context_data(**kwargs)
entry = self.kwargs['entry']
context['entry'] = entry
return context
def form_valid(self, form):
pass
Template :
<h1>You are reacting to article {{ entry.title }}</h1>
<p>
{{ entry.description }}
</p>
Of course, I get a NoReverseMatch error since the URL pattern isn't built to catch anything.
Passing parameters from DB stored objects through the URL is straightforward, but how do I pass a context variable ('entry', in this case) as an object to another view without using the URL ?
NB : I'm aware of the solutions using sessions or posts, but I can't believe that's the only way of doing it.

'FriendshipRequest' object has no attribute 'META'

I am trying to build a page that displays all the friend requests for a user. Everything seems to work until I get to the line where I render the page.
I am using Django.
View
def friend_requests(request):
current_user = request.user.username
user_id = (User.objects.get(username=current_user)).id
all_requests = FriendshipRequest.objects.filter(to_user_id=user_id)
friend_requests = []
for request in all_requests:
from_user_id = request.from_user_id
from_user_id_username =(User.objects.get(pk=from_user_id)).username
friend_requests.append(from_user_id_username)
# for some reason i'm getting an attribute error here
return render(request, 'Users/friend_requests.html', {'friend_requests': friend_requests})
Template (friend_requests.html)
{% for request in friend_requests %}
{{request}}
{% endfor %}
I think the variable request you create when looping through friend_requests is shadowing the context processor {{request}} which represents the current request client has made.
Change your variable name sth different than request and you'll probably be good to go:
{% for friend_request in friend_requests %}
{{friend_request}} object of the current user {{request.user}}
{% endfor %}

Categories

Resources