I feel like I am missing something simple. Working on a small personal project I have a MongoDB which I am connecting to via Djongo. I have started making a front end and have a problem with a collection using the generic MongoDB Object ID. The view will return a 404, while using the same query within MongoDB returns the desired document. Other pages are fine, this is the only one that uses the ObjectIDField as it was a hasty late additon
Model:
class Railway_Firmware(models.Model):
_id = models.ObjectIdField(name='_id', verbose_name='_id', db_column='_id', editable=False, max_length=200, primary_key=True)
qa = models.CharField(name='QA', verbose_name='QA', db_column='QA', max_length=200)
security = models.CharField(name='Security', verbose_name='Security', db_column='Security', max_length=200)
objects = models.Manager()
class Meta:
db_table = "Firmware"
verbose_name_plural = "firmware"
def get_absolute_url(self):
return reverse('firmware-detail-view', args=[self._id])
def __str__(self):
return str(self._id)
View:
class Railway_Firmware_DetailView(generic.DetailView):
model = Railway_Firmware
context_object_name = 'firmware'
template_name = 'firmware/firmware_detail.html'
pk_url_kwarg = '_id'
def get_queryset(self):
print({'_id': ObjectId(self.kwargs['_id'])})
return Railway_Firmware.objects.filter(**{'_id': ObjectId(self.kwargs['_id'])})
URL:
urlpatterns = [ path('firmware/<slug:_id>/', views.Railway_Firmware_DetailView.as_view(), name='firmware-detail-view'),
]
Admin works as expected with the same 631b1ce580404ce3f61d4565 within the link for example:
/admin/web_dev/railway_firmware/631929cc0b15c01285ae87e1/change/
.
Printing the query to console: {'_id': ObjectId('631b1ce580404ce3f61d4565')} this looks correct so I am unsure where this is going wrong. Any help would be greatly appreciated, thanks!
CodePudding user response:
The name of the URLConf
keyword argument that contains the slug is _id
in your route.
You have specified that pk_url_kwarg = '_id'
in your DetailView
.
Therefore, the wrong filter is applied to your queryset seeing as you don't have a pk
field in your document.
queryset = queryset.filter(pk=pk)
You need to inform DetailView
to use the slug
field when building the filter for the queryset via its get_object
method.
class Railway_Firmware_DetailView(generic.DetailView):
model = Railway_Firmware
context_object_name = 'firmware'
template_name = 'firmware/firmware_detail.html'
slug_url_kwarg = '_id'
slug_field = '_id'
def setup(self, request, *args, **kwargs):
super().setup(request, *args, **kwargs)
# Ensure that _id value is an ObjectId type for query filters to work
self.kwargs["_id"] = ObjectId(self.kwargs["_id"])