Django Naturaltime is not working in .annotate - python

Here I just wants to annotate a field on a model that gives human readable format saying how much time elapsed since it's created
My Model is created 30 seconds ago
My Model Description:
from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created_at']
#property
def natural_time(self):
return naturaltime(self.created_at)
What I did is here
from django.contrib.humanize.templatetags.humanize import naturaltime
from django.db.models import F
from .models import MyModel
m = MyModel.objects.annotate(timesincecreated=naturaltime(F('created_at'))
print m.values('timesincecreated')
on this print call I am getting the DateTimeField that I used in the model.
But If I want to access the property.
from .models import MyModel
m= MyModel.objects.first()
print m.natural_time
It works.
Any help? TIA.

You cannot use naturaltime function for annotation, annotation is a computation that is done on database level.
Django provides only a set of basic computations which can be processed by the database like Count, Sum, Min, Max, etc. You can refer to official doc to learn more about Query Expressions.

Related

Django DateTimeField and datetime.datetime.now() giving different times

I have a model where I want the name field to be a string representation of the timestamp, and another field to be the actual time stamp. Here is my model code:
from django.db import models
from datetime import datetime
class Image(models.Model):
name = models.CharField(max_length=255, default=datetime.now().strftime("%Y%m%d-%H%M%S"))
create_date = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to="images/")
Then I go in the django shell and enter this:
>>> import models
>>> models.Image(image='images/rock.png').save()
This works but the only problem is the two times do not align. For example, I get name = 20191201-143119 and create_date = 2019-12-01 14:32:11.445474.
How can I get these two datetimes to be the same?
This is a pretty common gotcha in Django's world. The post mentioned by #eliakin-costa discuss this problem, although his solution works I wouldn't recommend overriding save method to get this behavior as it's easier to create a function (keeping decoupled and explicit):
from django.db import models
from django.utils import timezone
def default_image_name():
return timezone.now().strftime("%Y%m%d-%H%M%S")
class Image(models.Model):
name = models.CharField(max_length=255, default=default_image_name)
create_date = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to="images/")
By the way, did you take a look at this docs (upload_to also accepts a callable) ? Do you really need a name column in your table?
I've linked an answer will help you understand what is happening. Achieving what you want is quite simple though.
models.py
from django.db import models
from datetime import datetime
class Image(models.Model):
name = models.CharField(max_length=255)
create_date = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to="images/")
def save(self, *args, **kwargs):
if not self.name:
self.name = datetime.now().strftime("%Y%m%d-%H%M%S")
super(Image, self).save(*args, **kwargs)

How to make a TabularInline orderable by user?

I created an admin view using the TabularInline class. With this view it is not possible to let the user order/sort the table to their liking, like within a standard ModelAdmin view. I would like to achieve this. I am using Django 2.2.1.
What I tried
I searched the Django docs, but besides hard coding 'ordering' within the admin.py file, I couldn't find anything on this topic. This is not what I want, I want the admin user to choose how to order.
I tried to use adminsortable2, however I ran into some issues I couldn't resolve. This got me thinking: is it really not possible with the standard Django package.
My code
My model consists of TimeFrames, which are made up by TimeSlots.
This is what my model.py looks like:
from django.db import models
class TimeFrame(models.Model):
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class TimeSlot(models.Model):
DAY_CHOICES = ('work', 'Work'), ('weekend', 'Weekend')
begin_time = models.TimeField()
end_time = models.TimeField()
reference = models.CharField(max_length=30)
day = models.CharField(max_length=30, choices=DAY_CHOICES)
timeframe = models.ForeignKey('TimeFrame', on_delete=models.CASCADE)
I don't want to register a separate TimeSlot admin view, since the TimeSlots are always part of a TimeFrame. They don't exist on their own.
from django.contrib import admin
from .models import *
class TimeSlotInline(admin.TabularInline):
model = TimeSlot
ordering = ("day", "begin_time") #hard-coded ordering
#admin.register(TimeFrame)
class TimeFrameAdmin(admin.ModelAdmin):
inlines = [TimeSlotInline]
Expected outcome
Enable the admin user to sort like in a standard ModelAdmin view.

AttributeError: (Class) object has no attribute '__name__' Creating ModelForms [Django & Python2.7]

This is my first time using Django and I am completely stuck at how to use ModelForms in my project. I have been able to follow the online tutorials this far but without ModelForms(to add data into a Postgresql database), I can't proceed onward. I am trying to simply make a form page that lets the users add a few inputs (2 datefields and 1 textfield) and by submitting that form, the data will be added to the database.
The error I have been getting is:
AttributeError: 'Hyuga_Requests' object has no attribute 'name' [where Hyuga_Request is a class set in the models.py]
models.py
from __future__ import unicode_literals
from django.db import models
from django.forms import ModelForm
class Hyuga_Requests(models.Model):
name = models.CharField(max_length=50)
s_date = models.DateField(auto_now=True)
e_date = models.DateField(auto_now=True)
reason = models.TextField(max_length=500)
def __unicode__(self):
return self.name
views.py
from django.shortcuts import render
from django import forms
from .forms import Hyuga_RequestForm
def create_req(request):
form = Hyuga_RequestForm()
context = {"form":form,}
return render(request,"request_form/requestform.html", context)
forms.py
from django import forms
from .models import Hyuga_Requests
from django.forms import ModelForm
class Hyuga_RequestForm(forms.ModelForm):
class Meta:
model = Hyuga_Requests()
fields = ['name','s_date','e_date','reason']
Please help this noobie...
Don't instantiate the model in the class Meta inside the Hyuga_RequestForm class.
model = Hyuga_Requests() should be model = Hyuga_Requests
model = Hyuga_Requests() -> model = Hyuga_Requests
The error come because you are calling the model on the form.
from django import forms
from .models import Hyuga_Requests
from django.forms import ModelForm
class Hyuga_RequestForm(forms.ModelForm):
class Meta:
model = Hyuga_Requests
fields = ['name','s_date','e_date','reason']
Note: i suggest to you use on the any class you define on python not use "_", you can check more about PEP8 and code styles here: https://www.python.org/dev/peps/pep-0008/

Django CreateView - ignores defaults on POST-test

I have a simple create view for a simple model with default-value fields. I want to test this setup by supplying only fields which don't have a default value.
The test fails, because no object was created in the database. Having played around with prints, I know the following:
The models clean() passes, and is supplied with the default values.
The response claims "This field is required." for maxVar and minVotes.
(And sending both values lets the tests pass.)
The failing test is:
from django.test import TestCase
from django.utils import timezone
from django.core.urlresolvers import reverse
import datetime
from testcase.models import Poll
class PollCreateTest(TestCase):
def test_create_with_description_only(self):
"""description should be sufficient to create a poll."""
self.assertEqual(Poll.objects.count(), 0)
x = self.client.post(reverse('rating:create'), {'description':'A Poll'})
#print x
self.assertEqual(Poll.objects.count(), 1)
With corresponding models.py:
from django.db import models
from django.core.urlresolvers import reverse
class Poll(models.Model):
description = models.TextField()
pub_date = models.DateTimeField('date published')
minVotes = models.IntegerField(default=5)
maxVar = models.FloatField(default = 0.0)
finished = models.BooleanField(default=False)
And views.py:
from django.shortcuts import render
from django.views import generic
from .models import Poll
class CreateView(generic.edit.CreateView):
model=Poll
fields=['description', 'maxVar', 'minVotes']
I am trying to get myself familiar with Django. The problem can probably be solved by writing a FormView with custom clean() methods. But I would like to understand WHY this doesn't work and, ideally, how to solve the problem.
I use Django 1.8 with Python 2.7.8.
The initial value is only used for two purposes: to render the initial value in the html form input, and to see if the submitted value has changed. It is not used to validate the form: not passing the actual data to the form is the same as explicitly changing the initial data to an empty value.
As your maxVar and minVotes fields are required (they don't have blank=True), deleting the initial values and passing no data to the form is not allowed. You have to pass both of them if you want the form to validate.

Circular import in python+django?! how to make it work?

Hello I'm spliting my files because the model is getting bigger. So here we are again with problems:
My models;
If in my Category model I remove the "ArticleToCategory" and the many-to-many relationship it works well. But I need them!
How to fix it?
I deleted the model.py in order to load files from the model package.
Category (models.category):
class Category(MPTTModel):
# relationships
from RubeteDjango01.generic.models.article import Article
from RubeteDjango01.generic.models.article_to_category import ArticleToCategory
articles = m.ManyToManyField(Article, through=ArticleToCategory)
ArticleToCategory (models.article_to_category):
from django.db import models as m
class ArticleToCategory(m.Model):
from RubeteDjango01.generic.models.article import Article
from RubeteDjango01.generic.models.category import Category
article = m.ForeignKey(Article)
category = m.ForeignKey(Category)
class Meta:
db_table = 'articles_to_categories'
verbose_name_plural = 'ArticlesToCategories'
thanks
You can define foreign keys using strings, to avoid exactly this problem.
class Art2C(..):
art = m.ForeignKey('Article')
from_other_app = m.ForeignKey('other_app.Article')

Categories