How to append string in the end of Django redirect in view? - django

I have a product on my platform and when a specific user does an action, I want to redirect them to example.com/product/product-slug/#SectionInWebsite.
However, I am not able to find a way to append "#SectionInWebsite" to the end of the redirect function.
return redirect('ProductSingle', product.slug, "#SectionInWebsite")

This worked for me (I had to use different names on my machine, but it should work):
# views.py
return redirect('{}#sectionInWebsite'.format(reverse('ProductSingle', kwargs={'product_slug':product.slug})))
That is, assuming your urls.py has something like this:
# urls.py
...
path('ProductSingle/<str:product_slug>', views.ProductSingle, name='ProductSingle'),
...
This is just a variation of the answer provided here, applied to your situation.

do this :
return redirect(reverse('ProductSingle',product.slug) + '#SectionInWebsite')

Maybe this can help you, using reverse.
return redirect(reverse('ProductSingle', product.slug) + '#SectionInWebsite')

Related

Comparing Two Urls Using Reverse And HTTP_REFERER

I am wanting to prevent a user from accessing a certain page unless they have been redirected. In order to do this I thought id do this:
if(request.META.get('HTTP_REFERER') != reverse('some_page')):
return redirect('some_page')
This works almost perfectly except that request.META.get('HTTP_REFERER') returns the whole url address, while reverse('some_page') returns the abbreviated url.
For example
request.META.get('HTTP_REFERER') returnshttp://127.0.0.1:8000/page_one/some_page/
reverse('some_page') returns/page_one/some_page/
How can I either add the (sorry but I dont know the correct term) first part of the url (http://127.0.0.1:8000) to reverse('some_page'), or remove it from request.META.get('HTTP_REFERER') so they can be both compared in the if statement please?
Thank you.
This works :)
if(request.META.get('HTTP_REFERER') != request.build_absolute_uri(reverse('some_page'))):
return redirect('some_page')

Django syndication framework: prevent appending SITE_ID to the links

According to the documentation here: https://djangobook.com/syndication-feed-framework/
If link doesn’t return the domain, the syndication framework will
insert the domain of the current site, according to your SITE_ID
setting
However, I'm trying to generate a feed of magnet: links. The framework doesn't recognize this and attempts to append the SITE_ID, such that the links end up like this (on localhost):
<link>http://localhost:8000magnet:?xt=...</link>
Is there a way to bypass this?
Here's a way to do it with monkey patching, much cleaner.
I like to create a separate folder "django_patches" for these kinds of things:
myproject/django_patches/__init__.py
from django.contrib.syndication import views
from django.contrib.syndication.views import add_domain
def add_domain_if_we_should(domain, url, secure=False):
if url.startswith('magnet:'):
return url
else:
return add_domain(domain, url, secure=False)
views.add_domain = add_domain_if_we_should
Next, add it to your INSTALLED_APPS so that you can patch the function.
settings.py
INSTALLED_APPS = [
'django_overrides',
...
]
This is a bit gnarly, but here's a potential solution if you don't want to give up on the Django framework:
The problem is that the method add_domain is buried deep in a huge method within syndication framework, and I don't see a clean way to override it. Since this method is used for both the feed URL and the feed items, a monkey patch of add_domain would need to consider this.
Django source:
https://github.com/django/django/blob/master/django/contrib/syndication/views.py#L178
Steps:
1: Subclass the Feed class you're using and do a copy-paste override of the huge method get_feed
2: Modify the line:
link = add_domain(
current_site.domain,
self._get_dynamic_attr('item_link', item),
request.is_secure(),
)
To something like:
link = self._get_dynamic_attr('item_link', item)
I did end up digging through the syndication source code and finding no easy way to override it and did some hacky monkey patching. (Unfortunately I did it before I saw the answers posted here, all of which I assume will work about as well as this one)
Here's how I did it:
def item_link(self, item):
# adding http:// means the internal get_feed won't modify it
return "http://"+item.magnet_link
def get_feed(self, obj, request):
# hacky way to bypass the domain handling
feed = super().get_feed(obj, request)
for item in feed.items:
# strip that http:// we added above
item['link'] = item['link'][7:]
return feed
For future readers, this was as of Django 2.0.1. Hopefully in a future patch they allow support for protocols like magnet.

How to modify the link to access user profile?

I would like to modify the url to access user profile. OSQA use permalink() to generate the profile url
The default link is http://meta.osqa.net/users/2836/nhatthinh
And I want to change it to http://meta.osqa.net/users/nhatthinh
So, I modify the function get_profile_url follow as:
#models.permalink
def get_profile_url(self):
return ('user_profile', [slugify(self.username)])
And I also modify the url in forum\urls.py follow as:
url(r'^%s/(.*)/$' % _('users/'), app.users.user_profile, name='user_profile'),
But the result falls short of my expectation.
OSQA generates a link is http://meta.osqa.net/users//nhatthinh
So, how can I fix this issue?
Thank you so much.
You might want to try it like that:
url(r'^%s/(.*)/$' % _('users'), app.users.user_profile, name='user_profile'),
And if you use tranlsations, do not forget to adapt these as well.

Django URLConf Redirect with odd characters

I'm getting ready to move an old Classic ASP site to a new Django system. As part of the move we have to setup some of the old URLs to point to the new ones.
For example,
http://www.domainname.com/category.asp?categoryid=105 should 301 to http://www.domainname.com/some-category/
Perhaps I'm regex stupid or something, but for this example, I've included in my URLconf this:
(r'^asp/category\.asp\?categoryid=105$', redirect_to, {'url': '/some-category/'}),
My thinking is that I have to escape the . and the ? but for some reason when I go to test this, it does not redirect to /some-category/, it just 404s the URL as entered.
Am I doing it wrong? Is there a better way?
To elaborate on Daniel Roseman's answer, the query string is not part of the URL, so you'll probably want to write a view function that will grab the category from the query string and redirect appropriately. You can have a URL like:
(r'^category\.asp', category_redirect),
And a view function like:
def category_redirect(request):
if 'categoryid' not in request.GET:
raise Http404
cat_id = request.GET['category']
try:
cat = Category.objects.get(old_id=cat_id)
except Category.DoesNotExist:
raise Http404
else:
return HttpResponsePermanentRedirect('/%s/' % cat.slug)
(Altered to your own tastes and needs, of course.)
Everything after the ? is not part of the URL. It's part of the GET parameters.

Django HttpResponsePermanentRedirect don't process my view

If I put this in my view:
if slug == 'old-path':
return HttpResponsePermanentRedirect('new-path')
it skips my slugbased view and returns 404.
How do I easily return 301 and "reprocess" my view so I don't get a 404?
EDIT
#Pydev UAs comment was the correct answer in this case, but I appreciated the detailed answer by John Debs, which gave me the hint to look into named urls, which I didn't know about. Thanks all.
Add from django.core.urlresolvers import reverse to your list of imports and then try this bit of code:
if slug == 'old-path':
return HttpResponsePermanentRedirect(reverse('new-path'))
The problem you had was that HttpResponsePermanentRedirect() needs a path but you were providing it with a slug.
reverse() will search through your named URLs for the string you provide and return a path, which can then be redirected to properly.