{ "info": { "author": "Johnny Lee", "author_email": "jleeothon@outlook.com", "bugtrack_url": null, "classifiers": [ "Environment :: Web Environment", "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3.4", "Topic :: Internet :: WWW/HTTP :: Dynamic Content" ], "description": "========\nurlmodel\n========\n\nCreating rich and dry URLs for a Django model.\n\n------------\nIntroduction\n------------\n\n **Disclaimer.** Until release of version 1.0, API could significantly change.\n\nAs I started using class-based views for Django, I understood what the `get_absolute_url` method was about. Then I encountered the problem of using URLs that required more than once piece of information from a model instance, let's say, not a single primary key or slug. That's a bit abstract, take:\n\n- ``/regions/cat-cat-province/towns/mieaou/``\n\nThis identifies Mieaou town within Cat-Cat Province (there's another Mieaou town within Copy-Cat Province). Now let's say the usual list of things you'll do with a model is listing, reading detail, creating, updating, deleting (roughly, CRUD_). Roughly, you'll have this URLs:\n\n.. _CRUD: http://en.wikipedia.org/wiki/Create,_read,_update_and_delete\n\n- ``/regions/cat-cat-province/towns/list``\n- ``/regions/cat-cat-province/towns/create``\n- ``/regions/cat-cat-province/towns/mieaou/edit``\n- ``/regions/cat-cat-province/towns/mieaou/delete``\n\nAn important part to notice is that we're using *more than one piece of information per instance*, which makes things a bit more messy than just a pk. Why not just use a pk? First, I *think* there are security implications. Second, nobody wants to remember a pk. Third, programmers respect well-formed URLs and look down to senseless sequences of numbers with unfathomable disdain.\n\nWhat if you provide a link to the edit and delete sections? You'll probably go for::\n\n # urls.py\n\n urlpatterns = patterns('',\n # ...\n url(\n '^regions/(?P[\\w-]+)/towns/(?P[\\w-]+)/edit/?$',\n name='town-update'\n ),\n # ...\n )\n\nWith something in your template like::\n\n # html\n \n \n Update this town\n \n\n..\n\n Note: I mostly use \"update\" for internal stuff for convention and readability (\"update\" has the length as \"create\" and \"delete\" and \"detail\" and \"search\"), but I use \"edit\" for usability when it'll be read by the end-user.\n\nThe latter one is not very DRY_. So I thought I could start writing a ``get_update_url`` method, and so on. Then every model class definition would have a set of ``get_detail_url``, ``get_update_url``, ``get_delete_url`` methods, plus ``get_create_url`` and ``get_list_url`` methods (in the original project, it was \"search\" instead of \"list\"). Now, given that my URLs have roughly the same naming format for every model (``town-list``, ``town-create``, ``town-detail``, ``town-update``, ``town-delete``), that is not very DRY either!\n\n.. _DRY: https://docs.djangoproject.com/en/dev/misc/design-philosophies/#don-t-repeat-yourself-dry\n\nI decided to write a smart and flexible URL system so that the next time I would need a list-create-detail-update-delete set of URLs, things would be as easy as adding a mixin to the inheritance tree of the model.\n\n------------\nInstallation\n------------\n\nI know, my requirements suck:\n\n- Python 3\n- Django 1.6\n\nI'm not sure if this app will not work on previous versions of Django, but I think I will not with Python 2.\n\nTo install version 0.1::\n\n pip install django-urlmodel\n\nTo install the latest version, run the command::\n\n pip install git+git://github.com/jleeothon/urlmodel.git\n\n----------\nHow to use\n----------\n\nUsing the default CRUD urls is as easy as extending funcionality as a mixin::\n\n # models.py\n\n from django.db import models\n\n class Town(CrudUrlModelMixin, models.Model):\n pass\n \n # or, if you're only going to extend the urlmodel functionality...\n\n class Town(CrudUrlModel):\n pass\n\nThe former example will create a set of five methods (class-level: list, create; instance-level: detail, update, delete) that expect an URL based on the model name and the name of the \"action\". Also, these expect an URL keyword argument called \"pk\".\n\nIn order to use a slug field, you should override ``slug_kwarg_name`` to match the URL kwarg::\n\n # urls.py\n\n urlpatterns = patterns('',\n # ...\n url(\n '^digimons/(?P[\\w-]+)/?$',\n name='digimon-detail'\n ),\n # ...\n )\n\nand ``slug_field_name``, to match the model slug::\n\n # models.py\n\n class Digimon(UrlModelMixin, models.Model):\n name = CharField(max_length=100)\n sluggified_name = SlugField(max_length=100)\n \n slug_kwarg_name = 'name'\n slug_field_name = 'sluggified_name'\n\n..\n\n Try out their lazy equivalents, ``LazyCrudUrlModelMixin`` and ``LazyCrudUrlModel``!\n\n..\n\n **Note.** CrudUrlModel provides implementation for ``get_absolute_url`` too, and defaults to ``get_detail_url``.\n\n--------------\nAdvanced stuff\n--------------\n\nIf the default \"CRUD\" system (here: list, create, detail, update, delete) do not work for you, you can try out ``UrlModel`` and ``UrlModelMixin`` (plus their lazy counterparts).\n\n~~~~~~~~~~~\nAction URLs\n~~~~~~~~~~~\n\nThese are URLs based on \"action names\", such as \"detail\", \"create\", etc. For convention, ease and readability, you should try to stick to these methods, e.g.::\n\n class TownPerson(UrlModelMixin, Model):\n\n def get_defenestrate_url(self):\n # expects townperson-defenestrate to exist.\n return self.get_instance_action_url(\"defenestrate\")\n\n @classmethod\n def get_last_defenestrated(cls):\n # expects townperson-last-defenestrated to exist.\n return cls.get_class_action_url(\"last-defenestrated\")\n\n~~~~~~~~~~~~~~~~~~~~~~~~~\nExtra information for URL\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nIf you need to rely on more information than a single pk or slug, use ``*args`` and ``**kwargs`` to pass on this information to the ``urlresolvers.reverse`` method::\n\n class Town(CrudUrlModelMixin, Model):\n \n def get_detail_url(self):\n return super().get_detail_url(region_slug=self.region.sluggified_name)\n\nThe above example does also work similarly for the simpler ``UrlModelMixin`` class.\n\nBe careful!,\n\n instance url methods (``get_instance_url`` and ``get_instance_action_url``) always pass the pk or slug argument to ``urlresolvers.reverse``.\n\n~~~~~~~~~~~~~~~~\nCustom URL names\n~~~~~~~~~~~~~~~~\n\nIf you want to provide a custom URL instead of an automatic ``modelname-action``, use ``@classmethod get_class_url(cls, url_name, *args, **kwargs)`` and ``get_instance_url(self, url_name, *args, **kwargs)``.\n\n~~~~~~~~~~~~~~~~~~~~~~\nFormat for action URLs\n~~~~~~~~~~~~~~~~~~~~~~\n\n**Note:** this section is subject to change in upcoming versions.\n\nAction URLs are formatted ``modelname-action`` by default. To change this format, override the ``action_url_formatter`` object or provide a ``format_action`` class method. If you provide the latter (method), the former (object) will be ignored::\n\n action_url_formatter = lambda model, action: '%s-%s' % (model, action)\n # this signature will override action_url_formatter\n # @classmethod\n # def format_action(cls, modelname, action):\n # pass\n\n---------\nProposals\n---------\n\n- Provide support for Python 2, probably through six_.\n- Submit this project to PyPI.\n\n.. _six: https://pypi.python.org/pypi/six/1.7.3\n\n---------\nResources\n---------\n\n- `url template tag`_\n- `Reversing URLs`_\n- `Slug fields`_\n- `Class-based views`_\n\n.. _`url template tag`: https://docs.djangoproject.com/en/dev/ref/templates/builtins/#url\n.. _`Reversing URLs`: https://docs.djangoproject.com/en/dev/ref/urlresolvers/#reverse\n.. _`Slug fields`: https://docs.djangoproject.com/en/dev/ref/models/fields/#slugfield\n.. _`Class-based views`: https://docs.djangoproject.com/en/dev/topics/class-based-views/", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/jleeothon/urlmodel", "keywords": null, "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "django-urlmodel", "package_url": "https://pypi.org/project/django-urlmodel/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/django-urlmodel/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/jleeothon/urlmodel" }, "release_url": "https://pypi.org/project/django-urlmodel/0.12/", "requires_dist": null, "requires_python": null, "summary": "Rich URLs for Django models.", "version": "0.12" }, "last_serial": 1197256, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "cb0fb1af7beee5f69baa4a083e653444", "sha256": "c82838cd131a60a7cd8c068ae221ce1aa41acbf5a956593a7c7f47bd8681068c" }, "downloads": -1, "filename": "django-urlmodel-0.1.tar.gz", "has_sig": false, "md5_digest": "cb0fb1af7beee5f69baa4a083e653444", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7290, "upload_time": "2014-08-20T22:43:53", "url": "https://files.pythonhosted.org/packages/0b/b6/411d43b2646e6a73bd46350746fb7a02ca1dc42ecc1d7ed64571ae710d30/django-urlmodel-0.1.tar.gz" } ], "0.12": [ { "comment_text": "", "digests": { "md5": "9556d9b1d1b24059a38d240a28a20cc0", "sha256": "08991e796d0763ab9c552b597d3f82474e7a9bee4a0ba90063e579e5e0e8b6a1" }, "downloads": -1, "filename": "django-urlmodel-0.12.tar.gz", "has_sig": false, "md5_digest": "9556d9b1d1b24059a38d240a28a20cc0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6692, "upload_time": "2014-08-21T03:11:38", "url": "https://files.pythonhosted.org/packages/40/c1/f2f808440658312af5e3317659065c7fe8ceceb7a5e05b9c25bbfcf2d33c/django-urlmodel-0.12.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "9556d9b1d1b24059a38d240a28a20cc0", "sha256": "08991e796d0763ab9c552b597d3f82474e7a9bee4a0ba90063e579e5e0e8b6a1" }, "downloads": -1, "filename": "django-urlmodel-0.12.tar.gz", "has_sig": false, "md5_digest": "9556d9b1d1b24059a38d240a28a20cc0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6692, "upload_time": "2014-08-21T03:11:38", "url": "https://files.pythonhosted.org/packages/40/c1/f2f808440658312af5e3317659065c7fe8ceceb7a5e05b9c25bbfcf2d33c/django-urlmodel-0.12.tar.gz" } ] }