I’m creating a simple blog with a Django backend using MongoDB to store blog posts and their metadata.
Everything worked find when I was testing with a local mongodb instance, but when I switched to an atlas hosted database I started getting the following error.
The current Post model is
`
class Post(models.Model):
_id = models.UUIDField(
primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(
max_length=50, help_text='Post title. equivalent to obsidian file name')
publish_date = models.DateField()
last_edited = models.DateField(auto_now=True)
content = models.TextField(blank=False)
summary = models.TextField(blank=True)
tags = models.CharField(max_length=20, blank=False)
choices = [
('published', 'published'),
('draft', 'draft'),
('private', 'private')
]
status = models.CharField(
choices=choices, default='published', max_length=20, blank=False,)
class Meta:
pass
def get_absolute_url(self):
return reverse('post', args=[self._id])
def __str__(self):
return self.title
And the associated view
class PostDetailView(generic.DetailView):
model = Post
def get_context_data(self, **kwargs):
context = super(PostDetailView, self).get_context_data(**kwargs)
# context['post'].tags = context['post'].tags.split(',')
context['post'].content = markdown.markdown(context['post'].content)
return context
To debug I overrode the get_object
method as follows:
def get_object(self, *args, **kwargs):
kwargs = self.kwargs
kw_id = kwargs.get('pk')
all_results = Post.objects.filter()
print(all_results.first()._id == str(kw_id))
result = Post.objects.get(_id=str(kw_id))
print("result:", result)
return result
assuming there is only one test post in the DB, all_results = Post.objects.filter()
returns the post, but some of its element (e.g. all_results.first().content
are None
even though it is populated in the DB.
the main problem is that when trying to filter
or get
based on the value of the _id
field no results are returned even though print(all_results.first()._id == str(kw_id))
outputs true
.
Any ideas as to what might be causing this, please?
Edit:
Since the posts are added from somewhere else (an obsidian plugin) I ran a test to compare the posts created from the admin page (which work properly) to those created by the plugin, and it seems that the id field which is created using typsscripts’ uuid.v4()
produce a mongodb string _id field whereas the posts created in the admin page end up with a BinData
type. How can these be made to match ?
2
Answers
I ended up figuring it out. The issue was the type compatibility of the _id field. On the typescript side I generate the
_id
usingmongoDB
'snew ObjectId()
. On the Django side I convert the_id
received as a string fromget_absolute_url()
to abson.objectid.ObjectId
class before doing the filtering. I also changed the model to the following (switched to djongo fields)Now the types are consistent everywhere and the queries are successful.
all_results.first()._id
will return the _id and if you are comparing it with id that is not same with it will returnNone
.You can do:
With that, you will have access to the first data from the DB.