Django migrate naive DateTimeField - django

I am very sad: Every time I migrate the database, Django calls me naive:
$ python manage.py migrate
RuntimeWarning: DateTimeField Book.released received a naive datetime (2023-02-17 22:59:29.126480) while time zone support is active.
...and the worst part is: It's impossible to fix it!
Steps to reproduce:
$ python -V
Python 3.10.6
$ pipenv --version
pipenv, version 2022.11.11
$ mkdir naive-django
$ cd naive-django
$ pipenv install django
$ pipenv shell
$ python -m django --version
4.1.7
$ django-admin startproject naive_project
$ cd naive_project
$ python manage.py startapp naive_app
$ vim naive_project/settings.py
...
INSTALLED_APPS = [
'naive_app.apps.NaiveAppConfig',
...
$ vim naive_app/models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
$ python manage.py makemigrations
$ python manage.py migrate
No problem so far. Let's add a DateTimeField now:
$ vim naive_app/models.py
from datetime import datetime
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
released = models.DateTimeField(default=datetime.now)
$ python manage.py makemigrations
$ python manage.py migrate
RuntimeWarning: DateTimeField Book.released received a naive datetime (2023-02-17 22:59:29.126480) while time zone support is active.
Oh no! I made a terrible mistake! If only it was not impossible to fix it... Let's try anyway:
$ vim naive_app/models.py
from django.utils import timezone # timezone instead of datetime
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
released = models.DateTimeField(default=timezone.now) # timezone instead of datetime
$ python manage.py makemigrations
$ python manage.py migrate
Hey! It worked! It was not impossible after all!
Let's write a test:
$ vim naive_app/tests.py
from django.test import TestCase
class NaiveTests(TestCase):
def test_naive(self):
pass
$ python manage.py test
RuntimeWarning: DateTimeField Book.released received a naive datetime (2023-02-17 23:10:54.367162) while time zone support is active.
Oh no! It's not fixed! Every time I run the tests, a database is built from scratch and my old migration is executed!
$ echo "Please Mister Django, I apologize. I'm going to delete my model."
$ vim naive_app/models.py
# from django.utils import timezone # timezone instead of datetime
# from django.db import models
#
#
# class Book(models.Model):
# title = models.CharField(max_length=100)
# released = models.DateTimeField(default=timezone.now) # timezone instead of datetime
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py test
RuntimeWarning: DateTimeField Book.released received a naive datetime (2023-02-17 23:18:36.955394) while time zone support is active.
I still get a warning while the model is deleted and the test is almost empty.
Would you have an idea?
$ exit
$ pipenv --rm
$ cd ..
$ rm -rf naive-django

If you squash the two migrations that add the DateTimeField and fix the default they will be optimised into a single migration that uses the latest default, the old operation using the incorrect default will then not run so you shouldn't get the warning
$ python manage.py squashmigrations naive_app 0002 0003
$ python manage.py migrate
$ python manage.py test

Related

Django deploy errors

I just launched the Django app. As an image, everything is in place, but the form and admin panel do not work. Anyone who knows please help
I get this error when I run the form.
Let me know if I need to share any code.
model.py
from django.db import models
# Create your models here.
class Form(models.Model):
fname_lname = models.CharField(max_length=50, verbose_name="Ad Soyad")
number = models.CharField(max_length=20, verbose_name="Nömrə")
send_date = models.DateTimeField(auto_now_add=True, verbose_name="Tarix")
class Meta:
verbose_name = 'Formlar'
verbose_name_plural = 'Formlar'
def __str__(self):
return self.fname_lname
As Marco suggested, once you deploy you should run your migrations since you're probably using a different database. You run migrations same as when in development depending on your platform the following should work:
python manage.py makemigrations
python manage.py migrate
just make sure you are on the same directory as the manage.py file. Also remember that you will have to tweak the settings.py file database settings if you haven't already.
try the commands below:
python manage.py makemigrations --fake
python manage.py migrate --fake
if it donot work, i think you have to delete database and recreate it,
if you need the data you can use python manage.py dumbdata ->data.json
and after you create the new database use python manage.py loaddata data.json

python3 manage.py makemigrations No changes detected

(fcdjango_venv) Subinui-MacBook-Pro:Impassion_community subin$ python3 manage.py makemigrations
No changes detected
I'm learning Basic Django right now, and was following the lecture, but got problem.
I followed the lecture, so first I typed the code on models.py
from django.db import models
# Create your models here.
class Impassionuser(models.Model):
username=models.CharField(max_length=64,
verbose_name='사용자명')
password = models.CharField(max_length=64,
verbose_name='비밀번호')
registered_dttm = models.DataTimeField(auto_now_add=True,
verbose_name='등록시간')
class Meta:
db_table = 'Impassion_Impassionuser'
and then on Terminal, I typed
(fcdjango_venv) Subinui-MacBook-Pro:Impassion_community subin$ python3 manage.py makemigrations
but the result was
No changes detected
In the lecture, after typing python3 manage.py makemigrations
it shows
Migrations for "User" :
user/migrations/0001_initial.py
- Create model User
how can I get the same result?
Include the name of your app after the makemigrations command and make sure you have a migrations folder created within your app.

Django won't import values to database - sqlite3

I am trying to put values to my django database.
My app_name/models.py looks like:
from django.db import models
# Create your models here.
class Language(models.Model):
id = models.AutoField(primary_key=True)
code = models.TextField(max_length=14)
I ran this commands:
python3 manage.py makemigrations app_name
python3 manage.py migrate app_name
After that I starting importing values to my database. So I run this command:
python3 manage.py shell
and put this code to the shell:
from app_name.models import *
with open('lang.txt', 'r') as file:
for i in file:
a = Language.objects.create(code=i.strip())
File lang.txt contains 309 lines with language codes. The file looks like:
en
fr
af
de
...
When I run this code in the manage.py shell Django created 309 Language objects. But when I try type random id in the shell -> Language(id=1).code it return only empty string - ''.
I tried use save() method too but still same problem.
from definitions.models import *
with open('lang.txt', 'r') as file:
for i in file:
a = Language(code=i.strip())
a.save()
Django version 1.10.1
So my question is where can be a problem?
This is happening because you are not fetching Language objects properly.
When you do Language(id=1).code, You are instantiating Language object with no value in given to code field.
In django, to fetch a object, you do Model.objects.get(field=value). So your code becomes:
Language.objects.get(id=1).code

How to install PostGIS for Django?

So I'm following the DOCS and just want to make sure I'm understanding correctly.
https://docs.djangoproject.com/en/1.10/ref/contrib/gis/install/postgis/
Do I just create a file called migrations.py with:
from django.contrib.postgres.operations import CreateExtension
from django.db import migrations
class Migration(migrations.Migration):
operations = [
CreateExtension('postgis'),
...
]
and drop it in my project directory? And then run python manage.py makemigrations ?
Still the better way ist to create extension directly by making a sql query:
CREATE EXTENSION postgis;
After that you just have to navigate to your project-root (there is a manage.py file inside) and run python manage.py migrate (since django 1.9 - before v.1.9 first run python manage.py makemigrations and after that python manage.py migrate)
But if you want to use your code, you have to add it to "models.py".
This is the file called by "python manage.py migrate"
So your models.py looks like:
from django.contrib.gis.db import models
from django.contrib.postgres.operations import CreateExtension
from django.db import migrations
class Migration(migrations.Migration):
operations = [
CreateExtension('postgis'),
]
class model1(models.Model):
geom = models.GeometryField(srid=4326,blank=True,null=True)
name = models.TextField(null=True)

How to delete all data for one app in Django 1.4 now that reset is gone?

How do I delete all the data in the database for on Django app? In previous version manage.py reset APPNAME did the job, but that's been deprecated.
What are we supposed to do now if we want to delete all the data from an app using the command line?
reset and sqlreset were both just wrappers around other management commands. sqlreset in particular can be duplicate by simply running:
python manage.py sqlclear myapp
python manage.py sqlall myapp
reset only served to automatically run the result of sqlreset on the database. Personally, I think removing that is a fantastic idea. Still, if you want similar functionality, you can just pipe the output to your database's shell commands.
For PostgreSQL, for example:
python manage.py sqlclear myapp | psql mydatabase
python manage.py sqlall myapp | psql mydatabase
If you want single command that should work with most database types you can pipe the drop table statements, that sqlclear generates, to dbshell
python manage.py sqlclear myapp | python manage.py dbshell
from django.contrib.contenttypes.models import ContentType
for ct in ContentType.objects.all()
ct.model_class().objects.all().delete()
Now that Django integrates migrations by default, you first need to make migrations for your app are first unapplied then deleted.
Here is the command line that works at least with Django 1.8 (replacing by the application you want to delete all associated data and:
# First, update the DB so it thinks no migrations were applied to the app
python manage.py migrate --fake <app_name> zero
# Erase all migrations in the app folder
rm -r "<app_name>/migrations/*"
# Erase the application tables
python manage.py sqlclear <app_name> | python manage.py dbshell
# Recreate the app tables, that will be empty
python manage.py makemigrations <app_name>
python manage.py migrate <app_name>
DIY
If you want to do that from the command line, create the following custom command:
from django.core.management.base import AppCommand, CommandError
from django.utils.six.moves import input
from django.db import DEFAULT_DB_ALIAS, connections
class Command(AppCommand):
help = (
'Removes ALL DATA related to the given app from the database '
'by calling model.objects.all().delete() for all app models. '
'This also removes related data in other apps via cascade.'
)
def add_arguments(self, parser):
super(Command, self).add_arguments(parser)
parser.add_argument(
'--noinput', '--no-input',
action='store_false', dest='interactive', default=True,
help='Tells Django to NOT prompt the user for input of any kind.',
)
parser.add_argument(
'--database', action='store', dest='database', default=DEFAULT_DB_ALIAS,
help='Nominates a database to reset. Defaults to the "default" database.',
)
def handle_app_config(self, app_config, **options):
app_label = app_config.label
database = options['database']
interactive = options['interactive']
db_name = connections[database].settings_dict['NAME']
confirm = (ask_confirmation(app_label, db_name)
if interactive else 'yes')
if confirm == 'yes':
for model in app_config.get_models():
model.objects.using(database).all().delete()
self.stdout.write('Reset done.\n')
else:
self.stdout.write("Reset cancelled.\n")
def ask_confirmation(app_label, db_name):
return input("""You have requested a reset of the application {app_label}.
This will IRREVERSIBLY DESTROY all data related to the app currently in
the {db_name} database, and return each table to empty state.
Are you sure you want to do this?
Type 'yes' to continue, or 'no' to cancel: """.format(**locals()))
Copy it to app/management/commands folder in any of your apps folders and run it with
./manage.py app_db_tables_reset any_installed_app_name
Ready-made package
The command is available in the django_commands package, you can install it with
pip install git+http://github.com/mrts/django-commands.git
and add it to INSTALLED_APPS to activate the command.
Tested with Django 1.9, it may or may not work with 1.8.