diff --git a/evennia/accounts/accounts.py b/evennia/accounts/accounts.py index 2c33e5c1f8..f90575edd2 100644 --- a/evennia/accounts/accounts.py +++ b/evennia/accounts/accounts.py @@ -14,7 +14,9 @@ instead for most things). import time from django.conf import settings from django.contrib.auth import password_validation +from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError +from django.urls import reverse_lazy from django.utils import timezone from evennia.typeclasses.models import TypeclassBase from evennia.accounts.manager import AccountManager @@ -189,6 +191,25 @@ class DefaultAccount(with_metaclass(TypeclassBase, AccountDB)): @lazy_property def sessions(self): return AccountSessionHandler(self) + + def get_absolute_url(self): + """ + Returns the canonical URL for an Account. + + To callers, this method should appear to return a string that can be + used to refer to the object over HTTP. + + https://docs.djangoproject.com/en/2.1/ref/models/instances/#get-absolute-url + """ + try: return reverse_lazy('account-detail', kwargs={'pk': self.pk, 'slug': slugify(self.name)}) + except: return '#' + + def get_admin_url(self): + """ + Returns a link to this object's entry within the Django Admin panel. + """ + content_type = ContentType.objects.get_for_model(self.__class__) + return reverse_lazy("admin:%s_%s_change" % (content_type.app_label, content_type.model), args=(self.id,)) # session-related methods diff --git a/evennia/accounts/tests.py b/evennia/accounts/tests.py index 2855dd0ca2..4d941782ad 100644 --- a/evennia/accounts/tests.py +++ b/evennia/accounts/tests.py @@ -59,6 +59,19 @@ class TestDefaultAccount(TestCase): self.s1 = Session() self.s1.puppet = None self.s1.sessid = 0 + + def test_absolute_url(self): + "Get URL for account detail page on website" + self.account = create.create_account("TestAccount%s" % randint(100000, 999999), + email="test@test.com", password="testpassword", typeclass=DefaultAccount) + self.assertTrue(self.account.get_absolute_url()) + + def test_admin_url(self): + "Get object's URL for access via Admin pane" + self.account = create.create_account("TestAccount%s" % randint(100000, 999999), + email="test@test.com", password="testpassword", typeclass=DefaultAccount) + self.assertTrue(self.account.get_admin_url()) + self.assertTrue(self.account.get_admin_url() != '#') def test_password_validation(self): "Check password validators deny bad passwords" diff --git a/evennia/objects/objects.py b/evennia/objects/objects.py index 27d8147999..167cd60612 100644 --- a/evennia/objects/objects.py +++ b/evennia/objects/objects.py @@ -12,6 +12,9 @@ from future.utils import with_metaclass from collections import defaultdict from django.conf import settings +from django.contrib.contenttypes.models import ContentType +from django.urls import reverse +from django.utils.text import slugify from evennia.typeclasses.models import TypeclassBase from evennia.typeclasses.attributes import NickHandler @@ -324,6 +327,25 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)): # look at 'an egg'. self.aliases.add(singular, category="plural_key") return singular, plural + + def get_absolute_url(self): + """ + Returns the canonical URL for an object. + + To callers, this method should appear to return a string that can be + used to refer to the object over HTTP. + + https://docs.djangoproject.com/en/2.1/ref/models/instances/#get-absolute-url + """ + try: return reverse('object-detail', kwargs={'pk': self.pk, 'slug': slugify(self.name)}) + except: return '#' + + def get_admin_url(self): + """ + Returns a link to this object's entry within the Django Admin panel. + """ + content_type = ContentType.objects.get_for_model(self.__class__) + return reverse("admin:%s_%s_change" % (content_type.app_label, content_type.model), args=(self.id,)) def search(self, searchdata, global_search=False, @@ -1821,6 +1843,17 @@ class DefaultCharacter(DefaultObject): a character avatar controlled by an account. """ + def get_absolute_url(self): + """ + Returns the canonical URL for a Character. + + To callers, this method should appear to return a string that can be + used to refer to the object over HTTP. + + https://docs.djangoproject.com/en/2.1/ref/models/instances/#get-absolute-url + """ + try: return reverse('character-detail', kwargs={'pk': self.pk, 'slug': slugify(self.name)}) + except: return super(DefaultCharacter, self).get_absolute_url() def basetype_setup(self): """ @@ -1938,6 +1971,17 @@ class DefaultRoom(DefaultObject): This is the base room object. It's just like any Object except its location is always `None`. """ + def get_absolute_url(self): + """ + Returns the canonical URL for a Room. + + To callers, this method should appear to return a string that can be + used to refer to the object over HTTP. + + https://docs.djangoproject.com/en/2.1/ref/models/instances/#get-absolute-url + """ + try: return reverse('location-detail', kwargs={'pk': self.pk, 'slug': slugify(self.name)}) + except: return super(DefaultRoom, self).get_absolute_url() def basetype_setup(self): """ diff --git a/evennia/objects/tests.py b/evennia/objects/tests.py new file mode 100644 index 0000000000..f317f2c39c --- /dev/null +++ b/evennia/objects/tests.py @@ -0,0 +1,11 @@ +from evennia.utils.test_resources import EvenniaTest + +class DefaultObjectTest(EvenniaTest): + + def test_urls(self): + "Make sure objects are returning URLs" + self.assertTrue(self.char1.get_absolute_url()) + self.assertTrue('admin' in self.char1.get_admin_url()) + + self.assertTrue(self.room1.get_absolute_url()) + self.assertTrue('admin' in self.room1.get_admin_url()) \ No newline at end of file