ModelForm foreignkey field not loaded yet - django

I'm attempting to develop a work record tracker sort of app, very similar to a ticket tracker. Each 'ticket' can have multiple notes owned by employees (employees are tracked in a different app that has been installed into the ticket-tracker).
i.e.
MySite
|___WorkRecords
|__models.py
|__views.py
|__etc.. //standard app stuff
|___emp #the uncreative name for the employee manager app
|__ //standard stuff again...
Within the models:
WorkRecords.models.py
class WorkRecord(models.Model):
issuedate = models.DateField('date first issued',
editable = False, default = timezone.now)
owner = models.ForeignKey('emp.Employee', related_name='work_owner',
on_delete=models.PROTECT)
other_irrelevant_header_data...
....
class WorkRecordNote(models.Model):
ref_wr = models.ForeignKey(WorkRecord, on_delete=models.CASCADE)
note_text = models.CharField(max_length=1000)
author = models.ForeignKey('emp.Employee', related_name='note_author',
on_delete=models.PROTECT)
#Form class for the Work Record
class EditWR(ModelForm):
class Meta:
model = WorkRecord
fields = '__all__'
emp.models.py
class Employee(models.Model)
data stuff
At the moment, the models have all been migrated, but the data has not been input into the tables yet (MySQL tables are all there, matching models etc...but no data within tables yet)
Now that I've gotten the models and tried working out modelform, I've tried makemigrations, but I'm getting an error traceback...
ValueError: Cannot create form field for 'owner' yet, because its related model u'emp.Employee' has not been loaded yet
I checked my mysite/settings.py to ensure that the apps were installed, and the config files are all there:
...
INSTALLED_APPS = [
'WorkRecords.apps.WorkrecordsConfig',
'emp.apps.EmpConfig',
etc...
]
...
To me, this sounds like it can't create the form because there isn't any data 'loaded' into the database, but what else I've learned about Django suggests that it shouldn't care yet. Is that accurate? Or is there something else I'm missing?
EDIT:
I made a change to the model of WorkRecord that somewhat fixed the problem (at least the error isn't there anymore, but I don't know about side-effects)
class WorkRecord(models.Model):
...
owner=models.ForeignKey('emp.Employee', related_name='work_owner',
on_delete=models.PROTECT, editable=False) #Added the editable=False
...
All else stayed the same, but makemigrations did not throw an error this time. What's the reasoning here?

Try changing the order on your installed apps:
INSTALLED_APPS = [
emp.apps.EmpConfig, # first
WorkRecords.apps.WorkrecordsConfig,
etc...
]

Related

Django admin date time helpers missing

I have a model that includes a datetimefield...
# Create your models here.
class BroadcastNotification(models.Model):
message = models.TextField()
broadcast_on = models.DateTimeField()
sent = models.BooleanField(default=False)
class Meta:
ordering = ['-broadcast_on']
In the admin pages the helpers for that field have gone away.
I don't know what I did to cause it as I didn't test everything after every change. I did do collectstatic fairly recently if that might be the cause.

Django migration not picking up all the model fields

I created a new Django project on Windows 10, with the latest python and Django. After creating the model with a number of tables/models on one model it skipped some fields. After retrying it would not create a new migration script. I looked at the initial 0001_initial.py and the fields were missing in that file. I later added a single new field and that field migrated property but not the missing fields. All other models were successfully updated in the initial migration. This happens to be a SQLite DB.
The model that is missing fields:
class articles(models.Model):
""" articles"""
title = models.CharField (max_length=500)
teaser = models.CharField (max_length=500)
summary = models.CharField (max_length=1500)
byline = models.CharField (max_length=250)
category = models.SmallIntegerField
articlenote = models.CharField (max_length=1000)
author = models.CharField
publishedDate = models.DateTimeField
articleStatus = models.CharField(max_length=4)
articleText = models.TextField
last_update= models.DateTimeField
def __str__(self):
return self.name
The missing fields are : category, author, publishedDate, articleText
Interesting after trying to rerun the migration I was getting Missing Defaults errors on a new table I was creating.
Since this is a brand new project I can just blow away the database and the migration scripts and try again. I would like to knwo what is potentially causing this missing migration.
You are missing the initialization of the fields.
So instead of author = models.CharField, use author = models.CharField(max_length=256) and also for all the others, use the parentheses.

In Django, does the intermediate model need to belong in the same file as the target model?

When running a migration, I am currently getting this lazy reference ValueError whenever the model that I have a defined ManyToManyField is in a separate file from the model that I am targeting. However, when I place the two models in the same file, I am able to successfully run the mirgation.
Why is this error happening?
Is it possible to separate the models (community.py and community_member.py) into separate files?
ValueError: contains a
lazy reference to fitness.communitymember, but app 'fitness' doesn't
provide model 'communitymember'.
My directory structure looks like this:
my_app
|----fitness
|----user.py
|----community.py
|----community_member.py
community.py
class Community(models.Model):
id = models.AutoField(
primary_key=True,
)
owner = models.ForeignKey(
User,
)
members = models.ManyToManyField(
User,
through='CommunityMember',
through_fields=('community', 'member')
)
class Meta:
db_table = 'Communities'
community_member.py
class CommunityMember(models.Model):
community = models.ForeignKey(
Community,
db_column='community_id'
)
member = models.ForeignKey(
User,
db_column='member_id',
)
class Meta:
db_table = 'Community_Members'
settings.py
INSTALLED_APPS = [
'my_app.fitness'
]
If I place the contents of community_members.py inside of community.py the migration is successfully executes, but I am not sure why.
Rashed, I really don't know why you need to split your models, but if you insisted in doing so, there must be a reason. A default Django's app must include a models.py file. The ValueError comes from the fact Django is unable to find all your models definitions, it simple doesn't know where to look for these models. If you insist in doing so (which I personally don't recommend with only two models) you should do what the docummentation recommends: https://docs.djangoproject.com/en/1.11/topics/db/models/#organizing-models-in-a-package

Django migration error :you cannot alter to or from M2M fields, or add or remove through= on M2M fields

I'm trying to modify a M2M field to a ForeignKey field. The command validate shows me no issues and when I run syncdb :
ValueError: Cannot alter field xxx into yyy they are not compatible types (you cannot alter to or from M2M fields, or add or remove through= on M2M fields)
So I can't make the migration.
class InstituteStaff(Person):
user = models.OneToOneField(User, blank=True, null=True)
investigation_area = models.ManyToManyField(InvestigationArea, blank=True,)
investigation_group = models.ManyToManyField(InvestigationGroup, blank=True)
council_group = models.ForeignKey(CouncilGroup, null=True, blank=True)
#profiles = models.ManyToManyField(Profiles, null = True, blank = True)
profiles = models.ForeignKey(Profiles, null = True, blank = True)
Any suggestions?
I stumbled upon this and although I didn't care about my data much, I still didn't want to delete the whole DB. So I opened the migration file and changed the AlterField() command to a RemoveField() and an AddField() command that worked well. I lost my data on the specific field, but nothing else.
I.e.
migrations.AlterField(
model_name='player',
name='teams',
field=models.ManyToManyField(related_name='players', through='players.TeamPlayer', to='players.Team'),
),
to
migrations.RemoveField(
model_name='player',
name='teams',
),
migrations.AddField(
model_name='player',
name='teams',
field=models.ManyToManyField(related_name='players', through='players.TeamPlayer', to='players.Team'),
),
NO DATA LOSS EXAMPLE
I would say: If machine cannot do something for us, then let's help it!
Because the problem that OP put here can have multiple mutations, I will try to explain how to struggle with that kind of problem in a simple way.
Let's assume we have a model (in the app called users) like this:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person)
def __str__(self):
return self.name
but after some while we need to add a date of a member join. So we want this:
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership') # <-- through model
def __str__(self):
return self.name
# and through Model itself
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
Now, normally you will hit the same problem as OP wrote. To solve it, follow these steps:
start from this point:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person)
def __str__(self):
return self.name
create through model and run python manage.py makemigrations (but don't put through property in the Group.members field yet):
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person) # <-- no through property yet!
def __str__(self):
return self.name
class Membership(models.Model): # <--- through model
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
create an empty migration using python manage.py makemigrations users --empty command and create conversion script in python (more about the python migrations here) which creates new relations (Membership) for an old field (Group.members). It could look like this:
# Generated by Django A.B on YYYY-MM-DD HH:MM
import datetime
from django.db import migrations
def create_through_relations(apps, schema_editor):
Group = apps.get_model('users', 'Group')
Membership = apps.get_model('users', 'Membership')
for group in Group.objects.all():
for member in group.members.all():
Membership(
person=member,
group=group,
date_joined=datetime.date.today()
).save()
class Migration(migrations.Migration):
dependencies = [
('myapp', '0005_create_models'),
]
operations = [
migrations.RunPython(create_through_relations, reverse_code=migrations.RunPython.noop),
]
remove members field in the Group model and run python manage.py makemigrations, so our Group will look like this:
class Group(models.Model):
name = models.CharField(max_length=128)
add members field the the Group model, but now with through property and run python manage.py makemigrations:
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
and that's it!
Now you need to change creation of members in a new way in your code - by through model. More about here.
You can also optionally tidy it up, by squashing these migrations.
Potential workarounds:
Create a new field with the ForeignKey relationship called profiles1 and DO NOT modify profiles. Make and run the migration. You might need a related_name parameter to prevent conflicts. Do a subsequent migration that drops the original field. Then do another migration that renames profiles1 back to profiles. Obviously, you won't have data in the new ForeignKey field.
Write a custom migration: https://docs.djangoproject.com/en/1.7/ref/migration-operations/
You might want to use makemigration and migration rather than syncdb.
Does your InstituteStaff have data that you want to retain?
If you're still developing the application, and don't need to preserve your existing data, you can get around this issue by doing the following:
Delete and re-create the db.
go to your project/app/migrations folder
Delete everything in that folder with the exception of the init.py file. Make sure you also delete the pycache dir.
Run syncdb, makemigrations, and migrate.
Another approach that worked for me:
Delete the existing M2M field and run migrations.
Add the FK field and run migrations again.
FK field added in this case has no relation to the previously used M2M field and hence should not create any problems.
This link helps you resolve all problems related to this
The one which worked for me is python3 backend/manage.py migrate --fake "app_name"
I literally had the same error for days and i had tried everything i saw here but still didn'y work.
This is what worked for me:
I deleted all the files in migrations folder exceps init.py
I also deleted my database in my case it was the preinstalled db.sqlite3
After this, i wrote my models from the scratch, although i didn't change anything but i did write it again.
Apply migrations then on the models and this time it worked and no errors.
This worked for Me as well
Delete last migrations
run command python manage.py migrate --fake <application name>
run command 'python manage.py makemigrations '
run command 'python manage.py migrate'
Hope this will solve your problem with deleting database/migrations
First delete the migrations in your app (the folders/ files under 'migrations'
folder)
Showing the 'migrations' folder
Then delete the 'db.sqlite3' file
Showing the 'db.sqlite3' file
And run python manage.py makemigrations name_of_app
Finally run python manage.py migrate
I had the same problem and found this How to Migrate a ‘through’ to a many to many relation in Django article which is really really helped me to solve this problem. Please have a look. I'll summarize his answer here,
There is three model and one(CollectionProduct) is going to connect as many-to-many relationship.
This is the final output,
class Product(models.Model):
pass
class Collection(models.Model):
products = models.ManyToManyField(
Product,
blank=True,
related_name="collections",
through="CollectionProduct",
through_fields=["collection", "product"],
)
class CollectionProduct(models.Model):
collection = models.ForeignKey(Collection, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
class Meta:
db_table = "product_collection_products"
and here is the solution,
The solution
Take your app label (the package name, e.g. ‘product’) and your M2M field name, and combine them together with and underscore:
APPLABEL + _ + M2M TABLE NAME + _ + M2M FIELD NAME
For example in our case, it’s this:
product_collection_products
This is your M2M’s through database table name. Now you need to edit your M2M’s through model to this:
Also found another solution in In Django you cannot add or remove through= on M2M fields article which is going to edit migration files. I didn't try this, but have a look if you don't have any other solution.
this happens when adding 'through' attribute to an existing M2M field:
as M2M fields are by default handled by model they are defined in (if through is set).
although when through is set to new model the M2M field is handled by that new model, hence the error in alter
solutions:-
you can reset db or
remove those m2m fields and run migration as explained above then create them again
*IF YOU ARE IN THE INITIAL STAGES OF DEVELOPMENT AND CAN AFFORD TO LOOSE DATA :)
delete all the migration files except init.py
then apply the migrations.
python manage.py makemigrations
python manage.py migrate
this will create new tables.

Django: InlineModelAdmin to reference its own Model

So I am trying to setup an entry posting system, where the user can select a bunch of related entries when creating an entry. And it would be wonderful if I could use the InlineModelAdmin for it. But it keeps wanting a foreignkey, which for some reason I'm unable to set up properly.
Here's a simplified setup of my situation:
models.py
class Entry(models.Model):
entry = models.ForeignKey('self', related_name='related_entry', null=True, blank=True)
title = models.CharField(max_length=100, verbose_name='title')
description = models.TextField(verbose_name='description')
def __unicode__(self):
return self.title
admin.py
class EntryInline(admin.TabularInline):
model = Entry
verbose_name = "related entry"
class EntryAdmin(admin.ModelAdmin):
inlines = [
EntryInline,
]
admin.site.register(Entry, EntryAdmin)
The problems im getting are of the likes:
DatabaseError at /admin/app/entry/add/
column app_entry.entry_id does not
exist LINE 1: SELECT "app_entry"."id",
"app_entry"."entry_id", "...
I'm still just kneedeep into the magic world of django, so if someone could point me out where I am going wrong that would be greatly appreciated!
First, I tried the code you provided in my machine (Django 1.2.3, Python 2.6.2, Ubuntu Jaunty) and it worked well as far as I could tell.
where the user can select a bunch of related entries when creating an entry.
Shouldn't you be using a ManyToMany relationship if you want an entry to be related to a bunch of entries? Your code currently defines a ForeignKey instead.
admin.py
...
admin.site.register(Entry, EntryAdmin)
Your admin is presently set up to let the user add an entry and also (optionally) one or more related entries in the same page (this worked perfectly). Was this your expectation?