问题
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 Meta
s 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