Django Tastypie Override URL with slug

空扰寡人 提交于 2019-12-13 02:56:07

问题


I have a similar coce:

def override_urls(self):
    return [
        url(r"^(?P<resource_name>%s)/(?P<slug>[\w\d_.-]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
    ]

Which produces an URL like:

/api/v1/nodes/<slug>/

Everything fine except that self.get_resource_uri(bundle) returns /api/v1/nodes/<id>/ and I cannot compare the current URL with the resource URI effectively.

What am I doing wrong?

Solution: working code

I implemented the proposed solution here: https://github.com/ninuxorg/nodeshot/blob/refactoring/nodeshot/core/base/resources.py

Any additional feedback for improvement is welcome.


回答1:


You could override get_resource_uri on your resource to return the correct uri. After all, the correct one is the one with the slug since that is the (first) one captured by your resource.

Update

The right way to do this is actually to skip override_urls and put this on the Resource's Meta:

detail_uri_name = 'slug'

TLDR Background

I dug a bit deeper and it looks like there's a much better place to implement this. The default implementation of get_resource_uri (indirectly) calls self.detail_uri_kwargs and then reverse.

The default implementation of detail_uri_kwargs in ModelResource just looks up self._meta.detail_uri_name (whose name is not intuitive), and grabs that key off the model. detail_uri_name defaults to pk.

If you just provide a different name here, you can skip the override_urls and the get_resource_uri!

Something like this (building on the code linked in comments by the OP):

from tastypie.resources import ModelResource
from tastypie.bundle import Bundle

class BaseSlugResource(ModelResource):
    """ Base Model Resource using slug urls """

    class Meta:
        abstract = True
        detail_uri_name = 'slug'

I'm not sure off the top of my head whether resource Metas are inherited (I'm going to guess they're not), so this may not work as a base class. Luckily, the one line required is probably fine to paste into each Resource that needs it.




回答2:


I'd like to clean it up with a working example even though the @dokkaebi's answer is marked (and partially) correct. The only missing part is you still have to prepend url that will be resolved for listing and such.

from tastypie.resources import ModelResource
from myapp.models import SomeModel

class BaseSlugResource(ModelResource):
    """ Base Model Resource using slug urls """

    class Meta:
        queryset = SomeModel.objects.all()
        detail_uri_name = 'slug'

    def prepend_urls(self):
        return [
            url(r'^(?P<resource_name>%s)/(?P<slug>[\w\.-]+)/$' % self._meta.resource_name, self.wrap_view('dispatch_detail'), name='api_dispatch_detail'),
        ]

This will display the correct resource_uri's for listing as well as resource get. However, you'll most likely loose {schema} resource (i.e. /api/posts/schema/) as it's treated as a slug too.



来源:https://stackoverflow.com/questions/12515146/django-tastypie-override-url-with-slug

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!