django full url in get_absolute_url

2020-07-03 08:29发布

问题:

I want to have a absolute/complete url when i call my models get_absolute_url method in template. in my entry model i have below:

def get_absolute_url(self):
    return ('blog_entry_detail', (), { 'year': self.pub_date.strftime("%Y"),
                                           'month': self.pub_date.strftime("%b").lower(),
                                           'day': self.pub_date.strftime("%d"),
                                           'slug': self.slug })

get_absolute_url = models.permalink(get_absolute_url)

in my template file:

{{object.get_absolute_url}}

I want to output the url prepended with 'http://www.example.com'

I want to use below lines to get the current domain name but i dont know where will i put it.

from django.contrib.sites.models import Site
current_site = Site.objects.get_current().domain

回答1:

This might work for you:

class Article(models.Model):
    ...
    ...
    def get_absolute_url(self):
        path = reverse('display_article', args=[self.slug])
        return "http://%s%s" % (self.site, path)


回答2:

My solution, with Sites framework

In API\views.py

class NotificationSerializer(serializers.HyperlinkedModelSerializer):
    absolute_url = serializers.CharField(source='get_full_absolute_url', read_only=True)

    class Meta:
        model = Notification
        fields = ( 'id', 'created_at', 'msg_txt', 'url', 'absolute_url' )

In models.py

from django.contrib.sites.models import Site

class Notification(models.Model):
    sender_user = models.ForeignKey(User, related_name = 'sender_user' )
    created_at = models.DateTimeField(default=timezone.now)
    reciever_user = models.ForeignKey(User, related_name = 'reciever_user')
    readed_at = models.DateTimeField( blank=True, null = True )
    msg_txt = models.CharField(max_length=255, blank=False)

    def get_absolute_url(self):
        return "/notification/%i/" % self.id

    def get_full_absolute_url(self):
        domain=Site.objects.get_current().domain

        return 'http://%s%s' % (domain, self.get_absolute_url()) 

Var 2, without Sites framework

If you have not Sites framework, you can use the ALLOWED_HOSTS settings.

In models.py

from myapp.settings import ALLOWED_HOSTS

class Notification(models.Model):
    ...

    def get_full_absolute_url(self):
        domain=ALLOWED_HOSTS[0]

        return 'http://%s%s' % (domain, self.get_absolute_url()) 

ALLOWED_HOSTS is required for production site.



回答3:

When I need full URLs, I usally go for request.get_absolute_url(), rather than assemble it myself using Site.objects.get_current().domain. However, there seem to be some issues with this method.

In any case, I don't think the model is the right place to put this because it violates the DRY principle by duplicating the URL in the urlconf and in the model. Can you not use some form of reverse URL lookups?



回答4:

As I didn't find any up-to-date answer on this, I achieved the results by this:

In settings.py, I set BASE_URL and then in models get_absolute_url method:

def get_absolute_url(self):
    from django.urls import reverse
    from django.conf import settings
    path = reverse('urlname', args=(arg)) # Assuming that a URL with name `urlname` is set in urls.py
    return '{}{}'.format(settings.BASE_URL, path)

I don't know either this is the best way to get the full URL or not, but I didn't find any better way to achieve the desired results. I hope this helps someone.



标签: django