I defined a board object as follow:
class Board(models.Model):
#let's do the relational part after I've done the other fields
Title = models.CharField(max_length=255)
Description = models.TextField(blank=True)
#where I got the image https://mixkit.co/blog/trello-backgrounds-awesome-free-illustrations-for-
trello-boards/
ImageUrl = models.URLField(
default="https://mixkit.imgix.net/art/preview/mixkit-starry-night-sky-over-hills-and-water-85-
original-large.png?q=80&auto=format%2Ccompress&h=700&q=80&dpr=1",
blank=True, null=False)
CreatedAt = models.DateTimeField(default=timezone.now)
EndsAt = Board.return_date_time_in_one_year()
def __str__(self):
return self.title
def return_date_time_in_one_year(self):
now = timezone.now()
return now + timedelta(years=1)
When I try to migrate I get the following error, I'm not sure where I went wrong in how I defined the classes, I'm new to both python and django.
File "C:\Users\Ameer\Documents\GitHub\Squasha_trello_clone\squasha\board\models.py", line 16,
in Board
EndsAt = Board.return_date_time_in_one_year()
NameError: name 'Board' is not defined
You are inside the class Board. Therefore, you refer inside the Board class to itself using this.
The line Board.return_date_time_in_one_year() would then become self.return_date_time_in_one_year()
I have two base models SiteData and Showoroom Service that have model structure as per the below.
I need the SiteData info but I also would like to get link_type from the showroomservice model if there is a matching ID.
ive tried a few things thus far, none are getting what I need, what is the best way to achieve this?
Thanks
select related
>>> nd = ShowroomService.objects.select_related('site').all()
>>> nd
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 229, in __repr__
return '<%s %r>' % (self.__class__.__name__, data)
File "/usr/local/lib/python3.6/site-packages/django/db/models/base.py", line 590, in __repr__
u = six.text_type(self)
TypeError: __str__ returned non-string (type SiteData)
Combining :
>>> complete_data = site_data | monitoring_data
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 310, in __or__
combined.query.combine(other.query, sql.OR)
File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/query.py", line 529, in combine
"Cannot combine queries on two different base models."
AssertionError: Cannot combine queries on two different base models.
chaining
>>> final_data = chain(monitoring_data, site_data)
>>> for i in final_data:
... '{} {}'.format(i.location,i.link_Type)
...
Traceback (most recent call last):
File "<console>", line 2, in <module>
AttributeError: 'ShowroomService' object has no attribute 'location'
sites.models.py
class SiteData(models.Model):
location = models.CharField(max_length=50)
site_type = models.ForeignKey(SiteTypes, verbose_name="Site Type", \
on_delete=models.PROTECT)
subnet = models.GenericIPAddressField(protocol='IPv4')
routed_subnet = models.GenericIPAddressField(protocol='IPv4', \
verbose_name="Routed Link Subnet", blank=True, null=True)
bgp_as = models.CharField(max_length=6, verbose_name="BGP AS Number")
opening_date = models.DateField(verbose_name="Showroom opening date")
last_hw_refresh_date = models.DateField(verbose_name="Date of latest hardware refresh", \
blank=True, null=True)
is_live = models.BooleanField(default=False, verbose_name="Is this a live site?")
tel = models.CharField(max_length=20, blank=True, null=True)
address = models.CharField(max_length=255, blank=True, null=True)
town = models.CharField(max_length=255, blank=True, null=True)
...
class Meta:
verbose_name = "Site Data"
verbose_name_plural = "Site Data"
ordering = ('location',)
permissions = (
("can_view", "Can View"),
("can_view_mgmt", "Can View Management"),
)
def __str__(self):
return self.location
monitoring.models.py
from sites.models import SiteData
class ShowroomService(models.Model):
site = models.ForeignKey(SiteData, verbose_name="Site", \
on_delete=models.PROTECT)
link_type = models.CharField(max_length=200, blank=True, null=True)
preference = models.CharField(max_length=200, blank=True, null=True)
timestamp = models.DateTimeField(auto_now_add=True, blank=True, null=True)
dashboard = models.BooleanField(default=True, verbose_name="display on monitoring dashboard?")
class Meta:
verbose_name = "Showroom Service Data"
verbose_name_plural = "Showroom Service Data"
def __str__(self):
return self.site
You can pull all related objects using django's "related manager". Documentation is available here: https://docs.djangoproject.com/en/2.0/ref/models/relations/#related-objects-reference
By calling showroom_service_set on a SiteData model, you can get the set of child records for each SiteData.
Just to explain why the listed attempts failed as well:
your __str__ methods on your models need to return strings. If they don't, you'll get that exception.
The pipe operator | is used for ORing together queries in django. That chunk of code is attempting to combine a query for 2 different types of models.
With the chain attempt, you've created a list containing two different types of models. One of which doesn't have a location attribute.
Here's a chunk of code to get the link type for all ShowroomService models attached to a SiteData model:
for site_data in SiteData.objects.all():
for showroom in site_data.showroom_service_set.all():
print showroom.link_type
I'm not sure how django handles camel-casing with related objects, so showroom_service_set is my best guess. You might have to do a little leg work on this to figure out what the actual set is called.
EDIT: There's something called prefetch_related. Here's a SO answer about it; I think it'll get you what you're looking for: https://stackoverflow.com/a/13096423/769971
I'm getting a confusing error for the second time since yesterday. Last time I just flattened my whole migrations, but I've never actually found what caused the problem.
So this comes up when I try to makemigrations for my python project. Where should I look for errors? I have feeling it's not actually about the migrations, but rather about errors in views.py or models.py even though I absolutely don't understand why this influences db migration.
Anyway, none of theses errors points to code that I have written. It's all in Django. So how to find the error that causes that?
(testenv1) C:\Users\user\eclipse_workspace\test1\test1>python manage.py makemigrations --trace
Traceback (most recent call last):
File "manage.py", line 22, in <module>
execute_from_command_line(sys.argv)
File "C:\Python27\testenv1\lib\site-packages\django\core\management\__init__.py", line 363, in execute_from_command_line
utility.execute()
File "C:\Python27\testenv1\lib\site-packages\django\core\management\__init__.py", line 355, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Python27\testenv1\lib\site-packages\django\core\management\base.py", line 283, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\Python27\testenv1\lib\site-packages\django\core\management\base.py", line 330, in execute
output = self.handle(*args, **options)
File "C:\Python27\testenv1\lib\site-packages\django\core\management\commands\makemigrations.py", line 150, in handle
loader.project_state(),
File "C:\Python27\testenv1\lib\site-packages\django\db\migrations\loader.py", line 323, in project_state
return self.graph.make_state(nodes=nodes, at_end=at_end, real_apps=list(self.unmigrated_apps))
File "C:\Python27\testenv1\lib\site-packages\django\db\migrations\graph.py", line 409, in make_state
project_state = self.nodes[node].mutate_state(project_state, preserve=False)
File "C:\Python27\testenv1\lib\site-packages\django\db\migrations\migration.py", line 92, in mutate_state
operation.state_forwards(self.app_label, new_state)
File "C:\Python27\testenv1\lib\site-packages\django\db\migrations\operations\fields.py", line 148, in state_forwards
delay = not old_field.is_relation
AttributeError: 'NoneType' object has no attribute 'is_relation'
(testenv1) C:\Users\user\eclipse_workspace\test1\test1>
Here is my models.py. It's currently WIP:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
#from wheel.metadata import unique
from datetime import datetime
from django.urls import reverse
# Create your models here.
from django.shortcuts import redirect
class Task(models.Model):
name = models.CharField(max_length=255,blank=True)
code = models.SlugField(max_length=255, unique=True)
sender = models.ForeignKey("Sender", default=0)
client = models.ForeignKey("Client", null=True,blank=True)
datetime = models.DateTimeField(default=datetime.now)
duration = models.IntegerField(default=0,blank=True)
photo = models.ImageField(null=True, blank=True)
route = models.TextField(blank=True)
km = models.FloatField(default=0, blank=True)
notes = models.TextField(blank=True)
milage_receipt = models.ForeignKey("MilageReceipt", null=True, blank=True, on_delete=models.SET_NULL)
def date(self):
return self.datetime.date()
def status(self):
try:
if self.receipt and self.milage_receipt:
return "done"
elif not self.receipt:
return "new"
elif not self.milage_receipt:
return "ok"
except Receipt.DoesNotExist:
return "new"
except MilageReceipt.DoesNotExist:
return "processing"
return str(self.receipt)
def save(self, *args, **kwargs):
if self.duration == None:
self.duration = 0
if self.km == None:
self.km = 0
super(Task, self).save(*args, **kwargs) # Call the "real" save() method.
def get_absolute_url(self):
return reverse('task_update', args=[str(self.id)])
def __unicode__(self):
return self.code
class Client(models.Model):
name = models.CharField(max_length=255)
name2 = models.CharField(max_length=255, blank=True)
slug = models.SlugField(unique=True, max_length=255)
email = models.EmailField()
handle = models.CharField(max_length=255, blank=True)
contact_name = models.CharField(max_length=255, blank=True)
street = models.CharField(max_length=255)
zip = models.IntegerField()
city = models.CharField(max_length=255)
street2 = models.CharField(max_length=255,blank=True)
zip2 = models.CharField(max_length=255,blank=True)
city2 = models.CharField(max_length=255,blank=True)
default_vat = models.IntegerField(default=7)
km_price = models.FloatField(default=0)
active = models.BooleanField(default=False)
def __unicode__(self):
return self.slug
class Sender(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(max_length=255)
email = models.EmailField()
street = models.CharField(max_length=255)
zip = models.IntegerField()
city = models.CharField(max_length=255)
phone = models.CharField(max_length=255)
website = models.URLField()
tax_id = models.CharField(max_length=255)
vat_id = models.CharField(max_length=255)
bank = models.ForeignKey("BankAccount")
def __unicode__(self):
return self.slug
class BankAccount(models.Model):
name = models.CharField(max_length=255)
iban = models.CharField(max_length=255)
bic = models.CharField(max_length=255)
holder = models.CharField(max_length=255)
class ReceiptNumber(models.Model):
id = models.AutoField(primary_key=True, unique=True)
number = models.IntegerField(blank=True)
def __unicode__(self):
return str(self.id)
class MyQuerySet(models.query.QuerySet):
def delete(self):
print self
raise
class SingleDeleteManager(models.Manager):
def get_query_set(self):
return MyQuerySet(self.model, using=self._db)
class Receipt(models.Model):
number = models.OneToOneField("ReceiptNumber", blank=True, related_name="receipt", null=True)
vat = models.IntegerField(blank=True)
amount = models.DecimalField(max_digits=10, decimal_places=2, blank=True)
body = models.TextField(blank=True)
date = models.DateField(default=datetime.now, blank=True)
task = models.OneToOneField("Task", related_name="receipt")
objects = SingleDeleteManager()
def total(self):
a = float(self.amount) * (self.vat / 100.0) + float(self.amount)
return "%.2f" % round(a,2)
def vat_amount(self):
a = float(self.amount) * (self.vat / 100.0)
return "%.2f" % round(a,2)
def save(self,*args, **kwargs):
if self.date == None:
self.date = datetime.now()
if self.amount == None:
self.amount = 0
if self.vat == None:
self.vat = self.task.client.default_vat
super(Receipt, self).save(*args, **kwargs)
#if not hasattr(self, "number") or self.number == None:
# new_number = ReceiptNumber.objects.create()
# new_number.number = ReceiptNumber.objects.filter(Q(receipt__task__sender_id=self.sender.id) | Q(milage_receipt__task__sender_id=self.sender.id)).latest('id').number+1
# new_number.save()
# self.number = new_number
# super(Receipt, self).save(*args, **kwargs)
def delete(self, *args, **kwargs):
if hasattr(self,"number") and self.number.id:
self.number.delete()
return super(self.__class__, self).delete(*args, **kwargs)
def get_absolute_url(self):
return reverse('receipt_create_for_task', args=[str(self.task.id)])
def __unicode__(self):
try:
return str(self.number) + ": " + self.task.code
except Task.DoesNotExist:
return "should be gone"
class ReceiptTemplate(models.Model):
name = models.CharField(max_length=255)
vat = models.IntegerField()
amount = models.FloatField()
body = models.TextField()
class MilageReceipt(models.Model):
number = models.OneToOneField("ReceiptNumber", null=True)
sender = models.ForeignKey("Sender")
client = models.ForeignKey("Client")
It's Version 1.11!
I found an extremely useful way of debugging this on this ticket on Django by Radek.
If you feel brave, you can edit the state_forwards() method on django/db/migrations/operations/fields.py adding a debug print on the first line.
def state_forwards(self, app_label, state):
# THIS IS THE LINE TO ADD
print app_label + " " + self.model_name_lower + " " + self.name
# END OF THE LINE TO ADD
new_fields = []
old_field = None
for name, instance in state.models[app_label, self.model_name_lower].fields:
if name != self.name:
new_fields.append((name, instance))
else:
old_field = instance
state.models[app_label, self.model_name_lower].fields = new_fields
# Delay rendering of relationships if it's not a relational field
delay = not old_field.is_relation
state.reload_model(app_label, self.model_name_lower, delay=delay)
Then run again ./manage.py makemigrations. Before crashing, you should see the name of the model that is making your migration fail.
Notice on the example below that the last model to be processed before crashing is adsummary on the core app, more specifically the account field. By the way, after finding this I just searched for adsummary on the migrations folder on the core app, then found out that there was a command for removing this column in one of the migration files, though the column wasn't on the database anymore, deleted this command and makemigrations started working again.
Felipes-MacBook-Air:backend felipe$ ./manage.py makemigrations -v 3
contenttypes contenttype name
core adsummary account
Traceback (most recent call last):
File "./manage.py", line 22, in <module>
execute_from_command_line(sys.argv)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/__init__.py", line 363, in execute_from_command_line
utility.execute()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/__init__.py", line 355, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/base.py", line 283, in run_from_argv
self.execute(*args, **cmd_options)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/base.py", line 330, in execute
output = self.handle(*args, **options)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/management/commands/makemigrations.py", line 150, in handle
loader.project_state(),
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/migrations/loader.py", line 323, in project_state
return self.graph.make_state(nodes=nodes, at_end=at_end, real_apps=list(self.unmigrated_apps))
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/migrations/graph.py", line 409, in make_state
project_state = self.nodes[node].mutate_state(project_state, preserve=False)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/migrations/migration.py", line 92, in mutate_state
operation.state_forwards(self.app_label, new_state)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/migrations/operations/fields.py", line 149, in state_forwards
delay = not old_field.is_relation
AttributeError: 'NoneType' object has no attribute 'is_relation'
The same thing happened to me. I think there's a bug in Django 1.11. I downgraded to Django 1.10.7 and ran my migrations without problems and re-upgraded to 1.11 again after that.
There is an open ticket:
EDIT: IT's indeed a bug and it's still there in Django 2.1.4
Found a way to fix it:
Open /django/db/migrations/operations/fields.py and go to the line
indicated in the exception in the state_forwards method and change the
line delay = not old_field.is_relation for delay = old_field is
None or not old_field.is_relation
Found the fix on Markus Holtermann answer on
https://code.djangoproject.com/ticket/28073:
I'm not entirely sure how you got to that line delay = not
old_field.is_relation with old_field being None as this means
there's no field with that name in state.models[app_label,
self.model_name_lower].fields, but I think it's safe to go with
delay = old_field is None or not old_field.is_relation.
As FamousJameous says, the problem is on the RemoveField method, probably used on a migration. In my case, the problem came when I was trying to remove a field what was not the defined (ex: I tried to remove field_id, created by a relationship, but the definition, and the correct one is field).
The same migration error happened to me. In my case it was caused by the underlying MySQL table schema becoming out of sync to the model specification in models.py. Specifically, my table had a column left over from an earlier failed migration.
I fixed the problem by manually deleting the column in MySQL and making sure the table schema matched models.py. I deleted the failed migration that caused the error and then re-did the deleted migration anew. Because the underlying table and the models.py schema were now in sync before I ran the migration it went through smoothly.
I hope this helps!
I am not 100% sure how to solve this problem, but I will write what worked for me:
Find function state_forwards ( I am using ubuntu) at following path:
"/home/aseem/venv/bt_pip/lib/python3.6/site-packages/django/db/migrations/operations/fields.py"
bt_pip is my pip virtual env name stored in folder venv.In above state_forwards func add following line:
print (app_label + " " + self.model_name_lower + " " + self.name + str(self.field))
This will show which app is causing the problem.
Now install django-reset-migrations. Then in terminal run :
python manage.py reset_migrations app_name
It showed me some error, but after that when I tried python manage.py makemigrations it just worked.
I was running multiple databases off the same migrations when I got this error. The migrations had gotten messed up from one database. To patch it, I manually edited an old migration to not be applied on a RemovalField on one of the databases.
if (settings.STATUS == '...'):
operations = [
migrations.RemoveField(
model_name='...',
name='...',
),
This is by far from an ideal solution, but worked for me.
The other answers try to find the field responsible of the error but do not give a solution.
I give the solution that worked in my case where there was no code error
Origin migrations state
python manage.py showmigrations app
[X] 0098_auto_20211112_1311
[X] 0099_auto_20211112_1011
[ ] 0100_auto_20220107_1709
[X] 0100_auto_20220105_1114
[X] 0101_auto_20220112_1203
Fix : revert migrations + remove migrations file + new migrations generation
I have to remove the migration that prevent me to revert migration.
rm app/migrations/0100_auto_20220107_1709.py
Now, I can revert migrations to common ancestor :
python manage.py migrate app 0099
I can now remove bad files :
rm app/migrations/0101_auto_20220112_1203.py
rm app/migrations/0100_auto_20220105_1114.py
I run migrations generation :
python manage.py makemigrations app
The migration could be executed without any issues
python manage.py migrate
Please, pay attention this solutions works only if the two migrations 0100 and 0101 have not been executed on production.
If others developper could have executed these migrations, they should follow this procedure.
I'm having huge issues with Django REST Framework and its serializers in relation to a model with an ImageField
Here's the code for my model:
class Photo(models.Model):
id = models.AutoField(primary_key=True)
image_file = models.ImageField(upload_to=generate_image_filename_and_path,
width_field="image_width",
height_field="image_height",
null=False,
blank=False)
image_width = models.IntegerField(null=False, blank=False)
image_height = models.IntegerField(null=False, blank=False)
and here's the serializer:
class PhotoSerializer(serializers.ModelSerializer):
class Meta:
model = Photo
fields = ('image_file',)
read_only = ('id', 'image_width', 'image_height')
id, image_width and image_height are set as read_only fields, as I want them to be generated by the model class. ID is something I couldn't even provide when first creating a model instance.
I've had much trouble. In the current state, I have a test that looks like this:
class PhotoSerializerTestCase(TestCase):
def test_native_data_type_serialization(self):
img_file = create_generic_image_file('test_img.jpg',
'image/jpeg')
p = Photo(image_file=img_file)
p.save()
serialization = PhotoSerializer(p)
expected_id = p.id
expected_image_width = p.image_width
expected_image_height = p.image_height
print(serialization)
actual_id = serialization.data['id']
actual_image_width = serialization.data['image_width']
actual_image_height = serialization.data['image_height']
self.assertEqual(expected_id, actual_id)
self.assertEqual(expected_image_width, actual_image_width)
self.assertEqual(expected_image_height, actual_image_height)
Here's the function that I call to create the generic image file for the test:
def create_generic_image_file(name, content_type):
path = '\\test_files\\test_image_generic.jpg'
file_path = BASE_DIR + path
file_name = name
content = open(file_path, 'rb').read()
image_file = SimpleUploadedFile(name=file_name,
content=content,
content_type=content_type)
return image_file
In present state, I'm left with an error as follows:
Creating test database for alias 'default'...
..PhotoSerializer(<Photo: Photo object>):
image_file = ImageField()
E.
======================================================================
ERROR: test_native_data_type_serialization (photo_broker.test_serializers.PhotoSerializerTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "<local_path>\test_serializers.py", line 25, in test_native_data_type_serialization
actual_id = serialization.data['id']
KeyError: 'id'
I can't even recall all the different errors that I've gotten previously, but I'm sure they'll pop up when this one's cleared.
edit:
Ok, I cleared the key error by moving all the fields back to PhotoSerializer.Meta.fields instead of PhotoSerializer.Meta.read_only. Now I'm back to one of my original questions. Let me explain with a test:
def test_create_model_from_serializer(self):
img_file = create_generic_image_file('test_img.jpg',
'image/jpeg')
data = {'image_file': img_file,
'id': 7357,
'image_width': 1337,
'image_height': 715517}
s = PhotoSerializer(data=data)
print(type(s))
print(s.is_valid())
print(s)
This yields clearly likable output and the serializer validates without a cough, but this is not what I want to be able to do. The ID and the dimensions should be calculated by the model. Not to whatever values by the serializer.
If I remove them from the fields attribute, then I can never get them into my serialization either. That's where I need them.
Or am I getting confused here and there actually is a valid use case, where I originally create the model normally, without going through the serializer?
I used below code to import csv file to django model containing manytomanyfield Release.metamodules
>>> from app.models import Metamodule,Release
>>> reldata = csv.reader(open('/root/Django-1.6.5/django/bin/dashboard/release.csv'),delimiter=',')
for row in reldata:
q = Release(number = row[0],
notes= row[1],
changes = row[2],
metamodules = Metamodule.objects.filter(name = row[3]))
try:
q.save()
except:
# if the're a problem anywhere, you wanna know about it
print "there was a problem with line"
Error:
Traceback (most recent call last):
File "<console>", line 5, in <module>
File "/usr/local/lib/python2.7/site-packages/django/db/models/base.py", line 416, in __init__
raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0])
TypeError: 'metamodules' is an invalid keyword argument for this function
As the field is ManyToManyField i used objects.fileter to get multiple records. But it is returning error.Please help me to fix this issue
models.py:
class Metamodule(models.Model):
name = models.CharField(max_length=50)
version = models.IntegerField(default=0)
modulename = models.ForeignKey(Module)
createdate = models.DateField(auto_now=True, null=True)
createdby = models.CharField(max_length=50)
def __unicode__(self):
return unicode(self.name)
class Release(models.Model):
number = models.IntegerField(default=0)
notes = models.CharField(max_length=50)
changes = models.CharField(max_length=50)
metamodules = models.ManyToManyField(Metamodule)
def __unicode__(self):
return unicode(self.number)
You can't create your Release object like that. You cannot create m2m relations from unsaved objects. See here
Try something like this :
for row in reldata:
q = Release(number=row[0], notes=row[1], changes=row[2])
# You have to save the object before adding the m2m relations
q.save()
metamodules = Metamodule.objects.filter(name=row[3])
for metamodule in metamodules:
q.metamodules.add(metamodule)
There is probably a better way to do the for loop but this is what you want to achieve.