Python, Django, Mongodb: view can't find document

Question:

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!

Asked By: dp_bluesets

||

Answers:

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"]) 
Answered By: Oluwafemi Sule
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.