Am trying to use DRF to make an election tracker; getting on what was supposed to be fairly simple ViewSet list and retrieve endpoints;
django.core.exceptions.ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "election-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.
Model Snippet...
class Election(models.Model):
_id = models.CharField(
name="id", primary_key=True, validators=[election_ids.validate], max_length=32
)
date = ComputedDateField(compute_from="_date") # not relevant
parent = models.ForeignKey(
to="self", on_delete=models.CASCADE, default=None, null=True
)
Serializers
class ElectionSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Election
# Removing the 'url' from below stops the ImproperlyConfigured error on retrieve calls
fields = ["url", "org", "date", "constituency", "parent"]
read_only_fields = ["url"]
depth=1
ViewSet
class ElectionViewSet(viewsets.ReadOnlyModelViewSet):
"""
API endpoint that allows elections to be viewed or edited.
"""
lookup_field = 'id'
lookup_value_regex = '[a-z0-9.\-_]+' # this might be the culprit, see below
queryset = Election.objects.all().order_by("-date")
serializer_class = ElectionSerializer
permission_classes = [permissions.AllowAny]
and relevant urls.py
app_name = "counts"
api_router = routers.DefaultRouter()
api_router.register(r"users", UserViewSet, "users")
api_router.register(r"groups", GroupViewSet, "groups")
api_router.register(r"elections", ElectionViewSet, "elections")
api_router.register(r"candidates", CandidateViewSet, "candidates")
api_router.register(r"stages", StageViewSet, "stages")
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
path("", TemplateView.as_view(template_name="home.html"), name='home'),
path("about/", TemplateView.as_view(template_name="about.html"), name='about'),
path("api/v1/", include(api_router.urls)),
path("api-auth/", include("rest_framework.urls", namespace="rest_framework")),
]
I think the issue is that the ID's are in a standard format that contains periods, which aren't a standard part of the SlugField type, and my working hunch is that something in the bowels of HyperlinkedModelSerializer is having trouble building the reverse / parent entity urls.
If I remove the "url" from ElectionSerializer.Meta.fields, then the individual 'election-detail' view appears to work fine (i.e. I can get a successful, correct, response on /api/v1/elections/nia.2016-05-05/) but I still can't get a listing going on .../elections/.
My understanding was that ReadOnlyModelViewSet would look after the default routing and view generation for list and retrieve operations which at this point are the only ones I'm interested in.
Things I have tried:
- Adding Namespaces and Names to the urls in both / and the base urls or the app-level urls
- Changing the model to use a custom 'slug' field as the lookup with
s/\./_/g - Hopefully not whatever you're about to suggest.
Any ideas? (Full codebase here for anyone feeling masochistic.)