I have 3 models, A, B and C.
Model C have 2 reference fields, one is pointing to A and another to B. There are 3 update APIs, for each of the model tables.
There is a 4th API that will retrieve data from table C and related data in table A and B.
Sometimes during fetching the data in 4th API, we face issue where the variable pointing to model B is said to be pointing to model A and hence fail to get the field which is in B and not in A. This sometimes happen for variable pointing to model A as well.
This happen on and off and it get resolved on its own.
I am not sure where to start looking for the issue.
Can someone please help me?
EDIT 1:
Here is the basic model example
class A(models.Model):
short_name = fields.StringField()
class B(models.Model):
description = fields.StringField()
class C(models.Model):
name = fields.StringField()
short_name_id = fields.ReferenceField(A)
desc_id = fields.ReferenceField(B)
Related
I have the following tables in my database:
class A(models.model):
...
class B(models.model):
a = models.ForeignKey(A)
class C(models.model):
b = models.ForeignKey(B)
data = models.TextField(max_length=50)
What I want to do is get the C object with a pk of 215, and select the related B object, and also select the related A object of the B object. Right now, what I am doing is this:
c = Models.objects.select_related('b').select_related('a').get(pk=215)
However, I get the following error:
django.core.exceptions.FieldError: Invalid field name(s) given in select_related: 'a'. Choices are: b
Is this possible to actually get all 3 objects with just one database hit? Thanks for any answers.
Try
c = Models.objects.select_related('b__a').get(pk=215)
Note the double underscore.
See the section starting with You can follow foreign keys... under https://docs.djangoproject.com/en/2.2/ref/models/querysets/#django.db.models.query.QuerySet.select_related
So I'm using inheritance in django with the following classes:
class main_menu(node):
"""
main_menu(node)
Has no extra fields. All children of the root node must
be main_menu nodes
"""
# Required for tree hierarchy to work (db_column='path' for raw queries)
_path1 = models.CharField(db_column='path', max_length=Global.MAX_FILE_PATH_LENGTH, unique=True);
main_menu_blah = models.CharField(max_length=30, default='');
def __unicode__(self):
return self.main_menu_blah;
main_menu
class language(main_menu):
"""
language(main_menu)
Main menu used specifically for a main menu targetted
at a speaker of some language.
"""
# Required for tree hierarchy to work
_path2 = models.CharField(db_column='path', max_length=Global.MAX_FILE_PATH_LENGTH, unique=True);
language_blah = models.CharField(max_length=30, default='');
def __unicode__(self):
return self.language_blah;
language
class language2(language):
_path3 = models.CharField(db_column='path', max_length=Global.MAX_FILE_PATH_LENGTH, unique=True);
language_blah2 = models.CharField(max_length=30, default='');
Now, I can insert access all of these models just fine as long. I can also get them using .objects.get(...).
But if I delete a row from a parent class table (such as language which is a parent to language2), then I cannot get() the last row from the language2 table.
I execute:
subNode = language2.objects.get(_path3=);
I always get the following error:
DoesNotExist
language2 matching query does not exist.
And I've looked in the database (sqlite) and I can see that the last entry has in the column _path3.
Furthermore, I can use a raw query (using connection.cursor()) and I can get the last row. But it's only the raw data, and I need a model object. Oh and using .extra() hasn't worked either.
Why can't I get the last row? (until I reboot the server)
Thanks.
EDIT:
The different "_path*" variables are needed for something else, so an abstract base class will not help in my case, but that's another topic.
As for the db_column='path', I have it that way so that raw queries are more streamlined and I have tried removing that (so that the column is "_path1", "_path2", etc), but the issue still persists. The part that is most confusing is that a raw query works, and restarting the server fixes it (until a new row is inserted, then that last one isn't seen).
EDIT2:
So I discovered what was happening. The important thing I forgot was how each of the tables were tied together.
If I have a base class:
class A
A subclass:
class B (A)
Another subclass:
class C (B)
I have tables linked like so:
A -> B -> C
Lets say I have 2 rows in each table (each one representing a instance of the class):
row 1 A: Name="Gerald" -> B: Age="25" -> C: Gender="Male"
row 2 A: Name="Janet" -> B: Age="24" -> C: Gender="Female"
If row two in table B is deleted, there is a break in the link that points to table C.
So I basically chopped of the torso of the class. 1/3 of the data is missing. And so, django reports it as non-existent.
So, be sure you are careful when deleting entries manually. You shouldn't have this issue with django as it should keep track of all of it for you.
First thing I notice is that you have two models that are inheriting from other classes and adding their own fields, but they're using the same db_column. A cleaner way to achieve this (if you're not directly using main_menu) is with an Abstract Base Class.
Effectively, your language2 model has these fields:
_path1 = models.CharField(db_column='path', max_length=Global.MAX_FILE_PATH_LENGTH, unique=True)
_path2 = models.CharField(db_column='path', max_length=Global.MAX_FILE_PATH_LENGTH, unique=True)
_path3 = models.CharField(db_column='path', max_length=Global.MAX_FILE_PATH_LENGTH, unique=True)
main_menu_blah = models.CharField(max_length=30, default='')
language_blah = models.CharField(max_length=30, default='')
language_blah2 = models.CharField(max_length=30, default='')
Also, Python does not require a semicolon at the end of each statement.
I want to save the A object and B object. A has a foreignkey to B. B has a OneToOneField to A. Is there a way I can get around having to reassign the variables between each save? or perhaps there's a better way to do it?
# The models a and b were created earlier in code
# a.b = b Was already set earlier in code
# b.a = a Was already set earlier in code
with transaction.commit_on_success():
a.save() # pk created for a
b.a = a # attach a.pk to b
b.save() # pk created for b
a.b = b # attach b.pk to a
a.save() # re-save a to database
"A has a foreignkey to B. B has a OneToOneField to A." I don't think this is the way to set up your relationships. You can just set B as a ForeignKey of A and then you can access A from B using B.a_set.all().
To paraphrase from here, with the following model definitions, Book is one-to-many (ForeignKey) with Publisher and many-to-many with Author. (The ~~~~ just means other stuff not related to the relationships between the models)
class Publisher(~~~~):
~~~~
class Author(~~~~):
~~~~
class Book(~~~~):
publisher = models.ForeignKey(Publisher)
authors = models.ManyToManyField(Author)
Then you can access publisher and author from a given book like so:
b = Book.objects.get(id=50)
publisher1 = b.publisher # publisher object for a given book
author_set = b.authors.all() # query set of authors for a given book
and you can do the reverse relationship (which isn't explicitly defined in the models above).
p = Publisher.objects.get(name='Apress Publishing')
p.book_set.all() # query set of books for a given publisher
publisher1.book_set.all() # set of books for the publisher from above.
a = Author.objects.get(name="JK Rowling")
a.book_set.all() # query set of books for a given author
Any time you update an object field you need to call save() to save it in the database, but you shouldn't need to reassign ForeignKey or any other field before doing so. If that wasn't working for you, maybe it was because of the funky relationship between the models. I'm not 100% sure, but I think the only time an object gets a (new) primary key is the first time it's saved to the database, and then that's its first pk.
Instead of dynamically altering a models file by adding fields, very bad i've been told, i'm suppose to maintain a type of flexibility by having variable field list names(i think).
Thus, when an attribute is added to the database, this attribute can be accessed without the models file being altered.
I cant figure out how to create variable field list names in my models class though.
I'm having trouble sifting through reading materials to find a solution to my problem, and trial and era is 15hrs and counting.
Could some one point me in the right direction.
New Edit
Heres what im trying to achieve.
When an attribute is added, i add it to the table like this.
c = 'newattributename'
conn = mdb.connect('localhost', 'jamie', '########', 'website')
cursor = conn.cursor()
cursor.execute("alter table mysite_weightsprofile add column %s integer not null; SET #rank=0; UPDATE mysite_weightsprofile SET %s = #rank:=#rank+1 order by %s DESC;" % (c, c, a))
cursor.close()
conn.close()
Now, in my models class i have
class WeightsProfile(models.Model):
1attributes = models.IntegerField()
2attributes = models.IntegerField()
3attributes = models.IntegerField()
class UserProfile(WeightsProfile):
user = models.ForeignKey(User, unique=True)
aattributes = models.CharField()
battributes = models.CharField()
cattributes = models.CharField()
Now all i want to do is get access to the new attribute that was added in the table but not added to in the models file.
Does sberry2A have the right answer. I hope it is, it seems the simplest.
I might not be following what you are asking, but assuming you have some model, like Person, which will start out having some defined fields, but may have several more added in the future...
class Person(models.Model):
fname = models.CharField(max_length=255)
lname = models.CharField(max_length=255)
age = models.IntegerField()
# more fields to come
Then you could use a PersonAttribute model...
class PersonAttribute(models.Model):
name = models.CharField(max_length=32)
value = models.CharField(max_length=255)
Then you could just add a ManyToMany relationship field to your Person...
attributes = models.ManyToManyField(PersonAttribute)
Or something similar.
I don't really understand what it is you're trying to do, but South is a good system for handling changes to models. It makes migrations, so that it understands the changes you've made and knows how to change them in the database in a way that you can use for both development sites and production.
I don't understand what you're after either, JT, but I really doubt South (see #Dougal) is going to help you if what you want boils down to "Look at the relevant DB table to know what fields the model should have at read time. But not write time.". South is brilliant for evolving schemas/models, but not at runtime, and not inconsistently across rows/instances of models. And hacking models at runtime is definitely a world of hurt.
Indeed, Django's ORM isn't built for dynamic fields (at least for now) - it was built to abstract writing SQL and speed up dev against an RDBMS, not schemaless/NoSQL stuff.
Speaking of which, if someone landed me with a spec that effectively said "We don't know what fields the model will have to store" I'd suggest we try MongoDB for that data (alongside Postgres for trad relational data), probably via MongoEngine
I need help on how to save the same (reference to an) object into a ManyToManyField.
For example I have models like this:
class Material(models.Model):
name = models.CharField(max_length=50)
class Compound(models.Model):
materials = models.ManyToManyField(Material)
In this example, the Compound can be made of one or many different Materials, and it also could be made from the same Material twice (same id in Material model).
If I try to save through a ModelForm, the second Material is discarded because it has the same id as the first Material.
What is the best approach for this?
Thank you!
I would suggest doing this as per http://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany
class Material(models.Model):
name = models.CharField(max_length=50)
class Compound(models.Model):
materials = models.ManyToManyField(Material, through='CompoundMaterials')
class CompoundMaterials(models.Model)
Material = models.ForeignKey(Material)
Compound = models.ForeignKey(Compound)
Quantity = models.IntegerField()
What am I doing here? Well, Django normally automatically generates an intermediary table for holding pairs of keys associating compounds to elements. In this case we're definiting it ourselves, but not only that, we're adding additional data to the relationship i.e. the quantity you speak of.
As an example usage, what you might do is this:
$ python manage.py shell
from project.app.models import *
oxygen = Material(name="oxygen")
hydrogen = Material(name="hydrogen")
water = Compound(name="water")
oxygen.save()
hydrogen.save()
water.save()
water_chemistry_oxygen = CompoundMaterials(Material=oxygen, Compound=Water, Quantity=1)
water_chemistry_hydrogen = CompoundMaterials(Material=hydrogen, Compound=Water, Quantity=2)
water_chemistry_oxygen.save()
water_chemistry_hydrogen.save()
Don't use a ManyToManyField -
Create a new model (MaterialOfCompound, for example), which holds two ForeignKeys - one to a Material record and one to a Compound object.
Then, to find all materials a compound is made of, you could use:
[x.material for x in MaterialOfCompound.filter( compound = my_compound ) ]
or something similar.