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)
Related
I'm using timezone.now() (django.utils impor timezone) to set the initial date of my model. But, the timezone.now() is fixed to the time when i set the server up, and doesnt change. How can i fix this?
I wanna that the timezone.now() return the datetime when the user is creating an object and not the time when i run the server.
You should pass a reference to the function to it, so:
from django.db import models
from django.utils import timezone
class MyModel(models.Model):
created_at = models.DateTimeField(default=timezone.now)
But likely you want to use auto_now_add=True [Django-doc], which will also make the field non-editable:
from django.db import models
class MyModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
I have created a model called 'Video' and in the Video class there is a field called videoID. I want videoID to be a randomly generated string but in my solution, there has been some errors.
Here is my solution:
models.py
from django.db import models
from django.contrib.auth.models import User
from other.video import generateVideoID
class Video(models.Model):
videoID = models.TextField(default=generateVideoID(),editable=False)
author = models.ForeignKey(User,on_delete=models.CASCADE, null=True)
As you can see in the videoID field I have set the default value to a function that returns a random string. This doesn't work because every time I create an object the videoID has the same string. This is the 'generateVideoID' function:
def generateVideoID():
import random,string
chars = string.ascii_letters+string.digits+"_-~"
videoID = ""
for i in range(12):
videoID += random.choice(chars)
return videoID
I have tried to use the 'init' method to set the videoID but that doesn't work. Can anyone help me?
Yes, but you should not call it, and furthermore it should be defined before you refer to it, so:
from django.db import models
from django.contrib.auth.models import User
from other.video import generateVideoID
class Video(models.Model):
videoID = models.TextField(default=generateVideoID, editable=False)
author = models.ForeignKey(User,on_delete=models.CASCADE, null=True)
so without parenthesis. If you add parenthesis, the function will be called, and the result will be used as default for all objects.
Alternatively you could use the UUIDField:
from uuid import uuid4
class Video(models.Model):
uuid = models.UUIDField(default=uuid4, editable=False, unique=True)
author = models.ForeignKey(User,on_delete=models.CASCADE, null=True)
Good evening,
I know, I asked a similar Question just a while ago, but I still got problems in understanding the more detailled functions of a signal. So I'm hoping someone can help me out with this one!? As an example I have a class in my "models.py" like this one:
class ExampleModel(models.Model):
name = models.CharField(max_length=255, null=False, blank=False)
value1 = models.IntegerField()
value2 = models.IntegerField()
value_of_1_and_2 = models.IntegerField()
def __str__(self):
return self.name
I would like to have my field "value_of_1_and_2" filled automatically with the sum of the other two fields before saving...
Is this possible? I tried some things and got stuck with a "pre_save" like this:
#receiver(pre_save, sender=ExameplModel)
def save(self, *args, **kwargs):
...
Thanks for all of your help and a nice evening to all of you!
Although the signals do logically similar things, they are slightly different from the save method in the model class. To be more specific, they answer the following questions in your head:
What do I want to do before the model is saved/deleted?
What do I want to do after the model is saved/deleted?
Others ..
If we come to what you want; If I understood correctly, you want to leave value_of_1_and_2 field blank while saving your model, and you want django to save it in the background with a method you set.
First of all, I prefer to keep the signals and models apart for a clean look. So next to the models.py file, create the signals.py file.
signals.py :
from .models import ExampleModel
from django.db.models.signals import pre_save
from django.dispatch import receiver
#receiver(pre_save, sender=ExampleModel)
def pre_save_example_model(sender, instance, *args, **kwargs):
if not instance.value_of_1_and_2:
instance.value_of_1_and_2 = instance.value1 + instance.value2
Then make the following definition in apps.py for the signals to work (Let's consider the name of the application as Summing. You can replace it with your own.):
apps.py :
from django.apps import AppConfig
class SummingConfig(AppConfig):
name = 'summing'
def ready(self):
from . import signals
And the most important thing here is: since you will leave the value_of_1_and_2 field empty, you should update your field as follows. Otherwise Django will raise the error.
value_of_1_and_2 = models.IntegerField(blank=True, default=0)
That's all. Save the model by entering value1 and value2, then you will see the result.
I want to create a log system to register some faults I need to handle at my work. I use Django and my models look like these:
class Chan(models.Model):
channelname = models.CharField(max_length=30)
freq = models.FloatField(default = 0.0)
def __unicode__(self):
return u'%s' % (self.channelname)
# timestamp object
class EventTime(models.Model):
since = models.DateTimeField()
till = models.DateTimeField()
def __unicode__(self):
return u'%s' % self.since.strftime('%Y-%m-%d %H:%M')
class Fault(models.Model):
channel = models.ManyToManyField(Chan)
description = models.CharField(max_length=200, default="-")
message = models.TextField()
timeevent = models.ManyToManyField(EventTime,null=True)
visible = models.BooleanField()
Firstly I used just one EventTime object but I soon realized I need to be able to choose several time periods because the same event could happen several times a day. So it would be too tedious to create a new record of Fault each time. So I basically needed something like this:
The problem is that 'ManyToManyField' is too unhandy to use because I don't need to keep these values for other faults. So I don't know what solution I can use for it. I don't know how many time periods I need. Maybe I could add an extra Text field to my table where I would keep comma-separated datetime objects converted into a string like '2017-11-06 18:36,2017-11-06 18:37'. But I don't know where to set this extra-conversion because I want to use a standart DateTimeField in Django admin site to set it before I make this conversion. Or maybe I could change the interface itself and add some Javascript. Maybe someone could give me advice or share some useful links. Thank you.
I would recommend using a Many-to-one relation together with InlineModelAdmin for the django admin.
models.py
class Fault(models.Model):
channel = models.ManyToManyField(Chan)
description = models.CharField(max_length=200, default="-")
message = models.TextField()
visible = models.BooleanField()
class EventTime(models.Model):
since = models.DateTimeField()
till = models.DateTimeField()
fault = models.ForeignKey(Fault, on_delete=models.CASCADE, related_name='timeevents')
def __unicode__(self):
return u'%s' % self.since.strftime('%Y-%m-%d %H:%M')
admin.py
from .models import Fault, EventTime
from django.contrib import admin
class EventTimeInline(admin.TabularInline):
model = EventTime
#admin.register(Fault)
class FaultAdmin(admin.ModelAdmin):
# ...
inlines = [EventTimeInline,]
So I am trying to create a custom Manager that extends the default one and I am getting an error that for the life of me I cannot fix. I've read all the django docs and can't see what I've done wrong!
ERROR:
NameError at /
name 'article_finish_date' is not defined
Here is my models.py
import datetime
from django.conf import settings
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
class ArticleManager(models.Manager):
def get_queryset(self):
return super(ArticleManager, self).get_queryset().filter(article_finish_date==None)
class Article(models.Model):
article_name_text = models.CharField(max_length=200)
article_creation_date = models.DateTimeField('date created')
article_publish_date = models.DateTimeField('date published', null=True, blank=True)
article_finish_date = models.DateTimeField('date finished', null=True, blank=True)
def __str__(self):
return self.article_name_text
actives = ArticleManager()
I have tried filtering by all the different values of the Article model, however the same issue occurs. I have tried both migrated and makemigrations, however no progress has been made.
Many thanks in advance, ask if you need more details!
The error is in this part:
.filter(article_finish_date==None)
Python is trying to evaluate the expression article_finish_date==None, except article_finish_date hasn't been defined yet. Instead, you want to use a single =
.filter(article_finish_date=None)