Aknell
Aknell

Reputation: 25

DateTimeField object has no attribute strftime

My main code is this:

  class Post(models.Model):
    title = models.CharField(max_length=200, unique=True)
    slug = models.SlugField(max_length=200, unique=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts')
    updated_on = models.DateTimeField(auto_now=True)
    image = models.ImageField(upload_to='images/%Y/%m/%d/', blank=True)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    status = models.IntegerField(choices=STATUS, default=0)

    publishdate = created_on.strftime('%Y/%m')

    class Meta:
        ordering = ['-created_on']

    def __str__(self):
        return self.title

When I run this code, I get:

'DateTimeField' object has no attribute 'strftime'

referring to publishdate

strftime works with datetime.datetime, and DateTimeField converts to datetime.datetime, so what am I doing wrong?

I've tried to convert to datetime.datetime to no avail

EDIT: Having seen answers, I think I should verify what I'm trying to do

I'm trying to add the date to this url in urls.py:

   urlpatterns = [
      path('', views.PostList.as_view(), name='home'),
      path('<publishdate>/<slug:slug>', views.PostDetail.as_view(), name='post_detail'
]

EDIT 2: I've updated my code to this:

class Post(models.Model):
    title = models.CharField(max_length=200, unique=True)
    slug = models.SlugField(max_length=200, unique=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts')
    updated_on = models.DateTimeField(auto_now=True)
    image = models.ImageField(upload_to='images/%Y/%m/%d/', blank=True)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    status = models.IntegerField(choices=STATUS, default=0)

    created_on_string = created_on.value_to_string(created_on)
    publishdate = strptime(created_on_string, '%Y/%m')

    class Meta:
        ordering = ['-created_on']

    def __str__(self):
        return self.title

and the output is:

File "C:\Users\[user]\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\models\fields\__init__.py", line 933, in value_from_object
    return getattr(obj, self.attname)
AttributeError: 'DateTimeField' object has no attribute 'attname'

Upvotes: 2

Views: 1831

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476594

At the class level, created_on is a DateTimeField, not the datetime object a Post object (not the class) holds. If you want to add a property that formats it, you can use:

class Post(models.Model):
    # …
    created_on = models.DateTimeField(auto_now_add=True)

    @property
    def publishdate(self):
        return self.created_on.strftime('%Y/%m')

    # …

That being said, formatting data is usually not the task of a model. A model is used to store and represent data. In a template you can for example use the |date template tag [Django-doc] to format a datetime object in a specified format. For a given Post object post, you for example can format this as:

{{ post.created_on|date:'Y/m' }}

For the URL, you can use two parameters:

urlpatterns = [
    path('', views.PostList.as_view(), name='home'),
    path(
        '<int:year>/<int:month>/<slug:slug>',
        views.PostDetail.as_view(),
        name='post_detail'
    )
]

in your view you then filter with:

class PostDetail(DetailView):
    model = Post

    def get_queryset(self, *args, **kwargs):
        return super().get_queryset(*args, **kwargs).filter(
            created_on__year=self.kwargs['year'],
            created_on__month=self.kwargs['month']
        )

In a template, you can then link to the view with a post object with:

{% url 'post_detail' post.created_on.year post.created_on.month post.slug %}

Upvotes: 3

everspader
everspader

Reputation: 1710

Shouldn't it work by adding a self to the attribute at the class level?

publishdate = self.created_on.strftime('%Y/%m')

Upvotes: 0

Related Questions