How to get_absolute_url with domain in Django template? - django

So I am struggling a bit, with something that logically seems so simple but due to my limited understanding of Django I am not sure where to look and how to formulate a solution.
Basically I have a Blog app set up and it shows the complete(all the content including disqus discussion) latest post on the home page. The post has a further link to the posts own page as well. I have set up Disqus and need to get some key information to use for the disqus_url and disqus_identifier. I have set up the model as follows with a method for get_absolute_url as follows:
def get_absolute_url(self):
return reverse('blog.views.renderBlog',args=[str(self.id),str(self.slug)])
My view is set up as follows:
def renderBlog(request,postid=1,slug=None):
template = 'blog_home.html'
if(postid == 1 and slug == None):
post = Post.objects.latest('date_created')
else:
post = Post.objects.get(slug=slug, id=postid)
data = {
'post':post,
}
return render(request, template, data)
As you can see the view is set up to handle both URL's as follows:
url(r'^$', 'renderBlog', name='blogHome'),
url(r'^post/(?P<postid>\d{1,4})/(?P<slug>[\w-]+)/$', 'renderBlog', name='blogPostPage'),
In my template I am setting disqus_identifier = '{{ post.get_absolute_url }}' and I am hardcoding the domain portion in the meantime as disqus_url = 'http://127.0.0.1{{ post.get_absolute_url }}';.. Same goes for the comment count <a href="" data-disqus-identifier.
I dont like doing things in a hackish manner, what would be the best method for me to get the full absolute url. I have looked at request.get_absolute_uri but am not sure on how to actually use it to get what I want.
Thanks

The way I like to do it is configure a context_processor:
from django.contrib.sites.models import Site
def base_context_processor(request):
return {
'BASE_URL': "http://%s" % Site.objects.get_current().domain
}
# or if you don't want to use 'sites' app
return {
'BASE_URL': request.build_absolute_uri("/").rstrip("/")
}
in settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
...
'path.to.base_context_processor',
...
)
(In newer versions of Django, modify context_processors under TEMPLATES, OPTIONS instead.)
then in templates:
Object Name
Another solution would be to use request.build_absolute_uri(location), but then you would have to create a template tag that takes a request object and a location or an object that has get_absolute_uri method. Then you would be able to use it templates like that: {% get_full_uri request=request obj=post %}. Here is documentation on how to write custom tags.

This question is pretty old but I think its still relevant.
To get_absolute_url with domain in Django template you can do the following:
<li>Home</li>
First check if the request is https or not and then get the request of the host and pass the absolute url.
This way you will get full URL with domain in Django template.

I know the question is old, but I'm not sure the best answer provided is the correct one.
You should just use
as the Django docs point out.
https://docs.djangoproject.com/en/4.0/ref/models/instances/#get-absolute-url
The url provided comes with the domain as well.
Regards

Related

how to create a dynamic link in Django

how can i build dynamic link in Django?
I have a blog and each post need to have a unique link.
content of blog's post must show on linked page.
I searched in google but i'm was a little confused.
Thanks
The answer involves setting a slug on your model instance, then referencing it within your URL, and then consuming it in your view in order to determine what blog post to pass into your context. Honestly, this is unfortunately a loaded question, but one that is gone over in pretty much any starter tutorial on Django.
Check out this video as it covers exactly what you're asking (he's building a blog).
https://www.youtube.com/watch?v=Bmvd1O5pNIY
The Answer is:
steps:
in views:
def article_content_view(request,article_id):
content = Article.objects.get(id=article_id).content
context = {
'content':content
}
return render(request,'article.html',context)
in urls:
path('article/<int:article_id>/', views.article_content_view,name= 'article_content'),
in template html file:
<a href="{% url 'article_content' article.article_id %}"</a>
and my problem solved by add an id for each post in view:
'article_id': article.pk
you can see my github repo for this project.
you can get a unique random URL by using
import uuid
x = uuid.uuid4().hex
get this link in localhost:8000/?url=x
in urls.py
add path in urlpatterns
path(<url>/,viewname)

Django Allauth very specific redirection after Facebook Social Signup

I know there are a few questions on the topic already but I have tried to implement those solutions and could not really solve my problem.
I am talking about social signup with allauth here, and facebook in particular.
DESIRED BEHAVIOR: after facebook signup I want user to go to my url "accounts:welcome", but when they simply login I want them to go to my LOGIN_REDIRECT_URL (which is the site's home page).
After looking here and there this is the code I came up with (writing my custom adapter)
settings.py:
LOGIN_REDIRECT_URL = ("gamestream:home")
SOCIALACCOUNT_ADAPTER = "myproject.users.adapter.MySocialAccountAdapter"
adapter.py:
from django.conf import settings
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
from django.core.urlresolvers import reverse
from django.shortcuts import redirect
class MySocialAccountAdapter(DefaultSocialAccountAdapter):
def save_user(self, request, sociallogin, form=None):
print('OK11OK')
super().save_user(request, sociallogin, form=form)
return redirect(reverse('accounts:welcome'))
def get_connect_redirect_url(self, request, socialaccount):
print('OK22OK')
assert is_authenticated(request.user)
url = reverse('accounts:welcome')
return url
Please assume that all links/settings are good as for example the console prints out 'OK11OK' when I create myself as a user via the facebook app. The fact is that the method get_connect_redirect_url never gets triggered as I never read 'OK22OK' on the console.
The user is created and I end up on the home page, which is not what I want.
So I thought that after the save_user method something else gets called as I can tell that I pass through accounts:welcome, but then end up on the home page.
I can tell this because if I return an incorrect url in the save_user method I get an error that is specific to that url on that line.
So, what is wrong here?
I think I might be overriding the wrong method but I have read all the code of the base SocialAccountAdapter and I can't see anything else that would be the right choice.
Just wanted to mention that as I have more control on the normal account signup (not social) I have achieved what I wanted.
Any ideas?
Thanks very much!
I had the same problem too, I found two methods:
METHOD 1
Django doesn't use redirection function of the DefaultSocialAccountAdapter, you'll have to override the get_signup_redirect_url function of DefaultAccountAdapter to achieve the result.
First you need to change the default adapter in settings.py:
ACCOUNT_ADAPTER = 'users.adapter.MyAccountAdapter'
Then, just override the get_signup_redirect_url with your url:
# project/users/adapter.py
from allauth.account.adapter import DefaultAccountAdapter
class MyAccountAdapter(DefaultAccountAdapter):
def get_signup_redirect_url(self, request):
return resolve_url('/your/url/')
METHOD 2
This is the easier one
If you take a look at the source code at DefaultAccountAdapter it says:
Returns the default URL to redirect to after logging in. Note
that URLs passed explicitly (e.g. by passing along a next
GET parameter) take precedence over the value returned here.
So, you can pass along a next parameter in your login template to force the redirection. Here is an example using Google social login:
{% load socialaccount %}
{% providers_media_js %}
{# your html tags #}
<body>
SOCIAL LOGIN
</body>
Of course you can personalize the next url (I'm refering to /success/url/) as you wish. You can pass a context variable with your desired url and put it there instead of that hardcoded url.

Pass a query parameter with django reverse?

I have a url that is meant to be accessed like
/people/raj/updates
/people/raj/updates?tag=food
But Django reverse URL resolver seems to have no provision to do tag=food, that is to detect it as an extra parameter and put in the query string.
How do I pass query parameters?
It depends on whether you are building the URL in the python code or in a template.
In python code (e.g. the view):
from django.http import QueryDict
query_dictionary = QueryDict('', mutable=True)
query_dictionary.update(
{
'tag': 'food'
}
)
url = '{base_url}?{querystring}'.format(
base_url=reverse(my.url.name),
querystring=query_dictionary.urlencode()
)
And in a template:
My Link
You caould also pass the QueryDict object from the view to the template and use that when building the URL in the template:
My Link
Django's reverse does not include GET or POST parameters. They are not part of the url.
You can of course always create the url by, for instance in a template, attaching the parameter as in:
{% url 'named_url' %}?tag=food
This way it gets attached anyway. Alternative is building an url regex that includes the possible tag, like:
url(r'^/people/raj/updates/(?P<tag>[a-zA-Z0-9]+/)?', yourview())
This way you can check for the kwarg tag in your view.

django-cms: urls used by apphooks don't work with reverse() or {% url %}

I'm using django-cms with apphooks to display book detail information. I need the page with the app hook to accept a slug that specifies which book to display.
I created a page called 'books' and added the apphook 'BookDetailApp'.
Here's what my books.cms_app file looks like:
class BooksApp (CMSApp):
name = _('Book Detail Page Application')
urls = ['books.urls']
apphook_pool.register(BooksApp)
Here's what my books.urls looks like:
urlpatterns = patterns('',
url(r'^(?P<slug>[\w\-]+)?', BookDetailView.as_view(), name='book_detail'),
)
And here's what my books.views file looks like:
class BookDetailView (DetailView):
model = Book
template_name = 'layouts/book-detail.html'
context_object_name = 'book'
This all works fine when I go directly to book detail page.
So going to http://localhost:8000/books/the-book-slug/ works exactly how I want to.
The problem is that I need be able to link to specific book detail pages from promos on the home page and none of the expected methods are working for me.
Using the page_url template tag from django-cms doesn't work because it only accepts one argument, so i can't provide the slug needed to determine which book to display:
go
As expected this only redirects to http://localhost:8000/books/ which throws an error because the required slug was not included.
So my next options are to use the url template tag or defining an get_absolute_url() function on the model. Neither of these options work:
go
def get_absolute_url(self):
return reverse('book_detail', args=[self.slug])
These both result in a NoReverseMatch: Reverse for 'book_detail' not found error.
If I include the books.urls conf in my main url conf then it works. So it would appear that if the url is only being used by a cms apphook that it can't be reversed by django.
Including books.urls in my main urls seems like a dirty solution and I definitely do not want to hardcode the urls in the template or the get_absolute_url function. Neither of those solutions seems very 'pythonesque'.
Any suggestions?
EDIT:
Reverse works only if I use the language namespace. According to documentation specifying language namespace shouldn't be required.
>>> reverse('en:book_detail', args=[book.slug])
This was apparently due to our application having cms.middleware.multilingual.MultilingualURLMiddleware which then forced all {% url %} template tags and the reverse() function to require the language namespace.
Since our site is not localized, removing the middleware worked fine. The documentation didn't seem that clear to me on this and finally found the answer from another source.

Using urls names in views

Is it possible to use urls names in views, like we can do it in template?
Check out the docs on reverse
They have a specific example reversing a named url here:
https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-resolution-of-urls
reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)
viewname is either the function name
(either a function reference, or the
string version of the name, if you
used that form in urlpatterns) or the
URL pattern name.
def myview(request):
return HttpResponseRedirect(reverse('arch-summary', args=[1945]))
https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-resolution-of-urls
(Updated answer to point to an existing url.)
I know this topic is years old, however during my own search for the same, this one popped up. I believe the requester is looking for the following in views.py:
views.py
class Overview(ListView):
model = models.data
template_name = "overview.html"
def get_queryset(self):
name = self.request.resolver_match.url_name
print(name)
Do note that I'm using class based views. Within regular views, the name can be retrieved as follows (not tested):
def current_url_name(request):
html = "<html><body>Url name is {}.</body></html>".format(request.resolver_match.url_name)
return HttpResponse(html)
The url name is within the (self.)'request' variable. From within your view, 'resolver_match.url_name' is the one you're looking for.
Hope this helps people in search of the same.
<script>
var salesApiUrl = "{% url 'URLNamesHere' %}"
</script>
Now, the salesApiUrl is global. You can use the var name in js as well