I have 3 inherited classes (Fitters -> Workers -> Staffs) connected with tables in my Database (class names in the plural, but that's not important now).
User can add/edit/remove only Fitters. The Workers and Staffs tables are updated automatically (cascaded).
It works fine: when I add new Fitter, all changes come to all tables in database. But when I want to edit any Fitter via Django admin tool, I go to edit Fitter page and I see incorrectly filled fields.
For example:
In Staffs table I have "John Smith" with id=41
In Workers table I have the record with id=21 and ForeignKey=41 (to John Smith)
In Fitters table I have the record with id=5 and ForeignKey=21 (to record in Workers table)
When I go to edit Fitter "John Smith" page, I see all fields filled by "Kevin Thomas" (id=21 in Staffs table!).
So, Django misses the Workers table and goes directly to the Staffs table.
How can I fix it?
Here is my draft code:
class Staffs(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=135, blank=True)
surname = models.CharField(max_length=135, blank=True)
def __unicode__(self):
return self.name + " " + self.surname
class Meta:
db_table = u'staffs'
class Workers(Staffs):
idWorker = models.AutoField(primary_key=True, db_column='id')
staffs_idstaff = models.OneToOneField('Staffs', db_column='Staffs_idstaff', parent_link=True)
brigades_idbrigade = models.ForeignKey('Brigades', db_column='Brigades_idBrigade')
def __unicode__(self):
return self.staffs_idstaff.name + " " + self.staffs_idstaff.surname
class Meta:
db_table = u'workers'
class Fitters(Workers):
idFitter = models.AutoField(primary_key=True, db_column='id')
qualification = models.CharField(max_length=135, blank=True)
workers_idworker = models.OneToOneField('Workers', db_column='Workers_idWorker', parent_link=True)
def __unicode__(self):
staff = self.workers_idworker.staffs_idstaff
return staff.name + " " + staff.surname
class Meta:
db_table = u'fitters'
EDIT1:
I tried to change my code like this:
class Staffs(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=135, blank=True)
surname = models.CharField(max_length=135, blank=True)
class Meta:
db_table = u'staffs'
class Workers(Staffs):
idWorker = models.AutoField(primary_key=True)
brigades_idbrigade = models.ForeignKey('Brigades')
class Meta:
db_table = u'workers'
class Fitters(Workers):
idFitter = models.AutoField(primary_key=True)
qualification = models.CharField(max_length=135, blank=True)
class Meta:
db_table = u'fitters'
It's pretty simple now. I synced my database, but I have the absolutely same problem!
EDIT2:
Part of my admin.py file:
from django.contrib import admin
from appclient.models import *
admin.site.register(Fitters)
admin.site.register(Staffs)
admin.site.register(Workers)
...
SOLUTION:
Solution is I don't need use my own id's and ForeignKey's for each model. Djando automatically creates special field for each model and uses it as an id (PrimaryKey) and for link to the parent tables (ForeignKey).
Here is solution:
class Staffs(models.Model):
name = models.CharField(max_length=135, blank=True)
surname = models.CharField(max_length=135, blank=True)
class Meta:
db_table = u'staffs'
class Workers(Staffs):
brigades_idbrigade = models.ForeignKey('Brigades')
class Meta:
db_table = u'workers'
class Fitters(Workers):
qualification = models.CharField(max_length=135, blank=True)
class Meta:
db_table = u'fitters'
Thanks to everyone who helped me.
This does seem somewhat strange. However, as far as I understand, Django will automatically setup the required one-to-one mappings between parents and children, when using multi-table inheritance. As you have also set these up manually, it might very well be that some kind of inconsistency is introduced due this.
If you take a look directly in the database, are the two different one-to-one relations consistent?
What happens if you remove the explicit one-to-one fields from your models?
Related
I have Three model defined. I want to filter Get specific user and get all related fields in the result set. For example, I want to get supplierInfo and company info of that user.
class User(AbstractBaseUser):
user_email= models.EmailField(unique=True, max_length=254)
user_id = models.AutoField(primary_key=True)
staff=models.BooleanField(default=True)
admin=models.BooleanField(default=True)
role_id=models.IntegerField(default=0)
supplier=models.ForeignKey(Supplier, on_delete=models.CASCADE) ....
class Company(models.Model):
company_name= models.CharField(('company name'), max_length=255, blank=True)
company_id = models.AutoField(primary_key=True)
class Meta:
verbose_name = ('company')
verbose_name_plural = ('company')
db_table = "company"
def __str__(self):
return self.company_name
class Supplier(models.Model):
supplier_name= models.CharField(('supplier name'), max_length=255, blank=True)
supplier_id = models.AutoField(primary_key=True)
company=models.ForeignKey(Company, on_delete=models.CASCADE)
class Meta:
verbose_name = ('supplier')
verbose_name_plural = ('supplier')
db_table = "supplier"
def __str__(self):
return self.supplier_name
I Have tried this
userInfo=User.objects.filter(user_id__exact=user.user_id).get()
userRelated= Supplier.objects.filter(supplier_id__exact=userInfo.supplier_id).get()
companyRelated=Company.objects.filter(company_id__exact=userRelated.company_id).get()
I am getting expected result But I dont think it is the best way. I want to merge three queries and get the result in one object . I am new in django so please help me out.
You can create a one to one relationship by defining a foreign key.
https://docs.djangoproject.com/en/3.0/topics/db/examples/one_to_one/
The documentation is really well written and i suggest you take a look for yourself.
If you do this you will have access to the related table when using the typical django orm methods.
I have the below models:
# Child
class Media (models.Model):
id = models.BigAutoField(primary_key=True)
name = models.CharField(max_length=128,unique=True)
file = models.FileField()
enabled = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
# Parent
class Gallery(models.Model):
id = models.BigAutoField(primary_key=True)
name = models.CharField(max_length=128,unique=True)
description = models.TextField(max_length=254,null=True)
medias = models.ManyToManyField(Media,related_name='medias')
enabled = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = "gallery"
verbose_name_plural = "galleries"
def __str__(self):
return self.name
I would like to be able to sort the child table by setting it in junction table; therefore not affecting the child table. I'm thinking of setting position field in junction table, is manually adding it in DB the only way of doing that? I'm fairly new to Django and I'm sorry in advance if this happens to be just a basic question.
Usual ManyToMany doesn't work here, because association table should contain order. So, this case you have to bring through to the mix:
class Gallery(models.Model):
medias = models.ManyToManyField('Media',related_name='medias', through='ChildGallery')
Where ChildGallery is a join model:
class ChildGallery(models.Model):
child = models.ForeignKey(Child)
gallery = models.ForeignKey(Gallery)
order = models.IntegerField()
class Meta:
ordering = ['order']
I don't know how you would like to implement order, but if it's just a number, you could use IntegerField as I showed above.
P.S. Note I wrapped all association models in quotes (like 'Child' not Child). It allows to break circular dependencies, so I recommend to use this way
I have an application that has a Company, and this company can have 0 or multiple addresses. Companies are not the only 'models' that could have addresses. To achieve this, I use ContentTypes.
models.py
class Company(models.Model):
''' models a company in the system. '''
number = models.CharField(_('Number'), unique=True, max_length=20)
name = models.CharField(_('Name'), max_length=100)
active = models.BooleanField(_('Active'), default=True)
def _get_addresses(self):
'''
'''
contentType = ContentType.objects.get(
model=self.__class__.__name__.lower()
)
try:
addresses = Address.objects.get(
actor_type=contentType, actor_id=self.id
)
except Address.DoesNotExist:
addresses = []
return addresses
addresses = property(_get_addresses)
class Address(Auditable):
''' models an address '''
actor_type = models.ForeignKey(ContentType)
actor_id = models.PositiveIntegerField()
actor_object = fields.GenericForeignKey('actor_type', 'actor_id')
_type = models.CharField(
_('Address Type'),
max_length=10,
choices=sorted(TYPES.items())
)
active = models.BooleanField(default=True)
address1 = models.CharField(_('Address 1'), max_length=50)
address2 = models.CharField(
_('Address 2'),
max_length=50,
...
This way, I could also have a Profile model and I could link multiple addresses to a Profile. However, my problem comes when I tried to implement the Serializers.
Serializers.py
class AddressSerializer(serializers.ModelSerializer):
class Meta:
model = Address
fields = (
'_type',
'address1',
'address2',
'address3',
'country',
'state',
'city'
)
class CompanySerializer(serializers.ModelSerializer):
addresses = AddressSerializer(required=False, many=True)
class Meta:
model = Company
fields = (
'number',
'name',
'addresses'
)
This implementation gives me this error. It says that it cannot iterate through Address model (which makes sense), but I'm not sure how to make my addresses iterable.
I would need to perform CRUD operations not only on the Company, but also on the nested Addresses.
Any suggestions/ideas on how to go about this?
The following database schema is just a suggestion for the scenario prevailed.
class Details(models.Model):
official_name = models.CharField(....)
is_company = models.BooleanField(default=False)
#something like that....
class Address(models.Model):
owner = models.ForeignKey(Details, related_name='addresses')
is_company = models.BooleanField(default=False)
building_name = .....
building_no = ......
locality = ......
#some other fields.....
class Company(models.Model):
details = models.OneToOneField(Details, related_name='company')
name = models.CharField(...)
number = .....
is_active = ........
class Profile(models.Model):
details = models.OneToOneField(Details, related_name='profile')
name = models.CharField(....)
.........
Here, each Company table and Profile table has a one to one relationship with a Details table. The Details table is related to the Address table with a Foreign key in it. So, each Company or Profile can have multiple addresses through the Details table.
So, the queries would be like,
For accessing addresses from the Company or Profile instances,
company.details.addresses.all()#or
profile.details.addresses.all()
For reverse queries are simple as the tables contains the respective fields in them, for a given address the owner would be, address.owner.profile or address.owner.company which could be determined by a flag in the respective tables.
I know, designing the database like this is somewhat tiring. But, this does helps in serialization of the data into a better format.
Serializers can be as follows,
class DetailsSerializer(ModelSerializer):
addresses = AddressSerializer(source='addresses', many=True)
class Meta:
model = Details
fields = ('addresses',)
class AddressSerializer(ModelSerializer):
class Meta:
model = Address
fields = '__all__'
class CompanySerializer(ModelSerializer):
details = DetailsSerializer()
class Meta:
model = Company
fields = ('details', .........)
class ProfileSerializer(ModelSerializer):
details = DetailsSerializer()
class Meta:
model = Profile
fields = ('details', .........)
Experts!
Having the following models.py
class Country(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class Meta:
verbose_name = 'Countries Uploaded'
class Users(models.Model):
name = models.CharField(max_length=50)
cUsers = models.ForeignKey(Country)
def __unicode__(self):
return self.name
class Meta:
verbose_name = 'Users on a country'
class GoalsinCountry(models.Model):
Country = models.ForeignKey(VideoTopic)
name = models.CharField(max_length=50)
descr = models.TextField(blank=True, null=True)
def __unicode__(self):
return self.name
class Meta:
verbose_name = 'Goals Topic'
I would like to filter out the users that belongs to a particular country and not all see all users when choosing a country on the combobox, and be able to save this information to a sqlite3 db.
if I add the following code below Country = Models..
gUser = models.ForeignKey(Users)
Using the Django admin interface, will show all users, not filtering users based on the country they are.. Would this be possible to do with Django + Something else? is there any working example/Tutorial - like the northwind MS Tutorial?
Thank you
i am working with django to create three tables that define a store, it's item list and a price list. In the 'price_list' model i created Foreign key links to the other two tables that i later use to create a compisite primary key using the unique together option. It all validates without an error but when i try to change the 'price_list' via the admin interface, i get the error as stated above in the title to this post. Editing for the other two models goes on without a glitch.
As i understand it, the error is saying the foreign key linked to the primary key of the businesses table is null. How can that be when the value is automatically generated?
Please help
models.py
from django.db import models
class Businesses(models.Model):
business_name = models.CharField(max_length=50, unique=True)
telephone_number = models.CharField(max_length=15)
where = models.ManyToManyField('Location', verbose_name='where?')
def __unicode__(self):
return self.business_name
class Meta:
ordering = ['business_name']
class Location(models.Model):
located_at = models.CharField(max_length=30)
city = models.CharField(max_length=30)
country = models.CharField(max_length=30)
def __unicode__(self):
return u'%s' % (self.located_at)
class Meta:
ordering = ['located_at']
class Item_list(models.Model):
item_name = models.CharField(max_length=50, unique=True)
def __unicode__(self):
return self.item_name
class Meta:
ordering = ['item_name']
class Price_list(models.Model):
price_list_id = models.AutoField(primary_key=True)
price = models.IntegerField(max_length=50)
business_id = models.ForeignKey(Businesses, related_name='businessID')
item_id = models.ForeignKey(Item_list, related_name='ItemID')
business_name = models.ForeignKey(Businesses, to_field='business_name', related_name='businessName')
item_name = models.ForeignKey(Item_list, to_field='item_name', related_name='itemName')
def __unicode__(self):
return u'%s' % self.price
class Meta:
ordering = ['price']
unique_together = (("price_list_id", "business_id", "item_id"),)
admin.py
from django.contrib import admin
from biaSearch.app.models import *
class BusinessAdmin(admin.ModelAdmin):
list_display = ('business_name', 'telephone_number')
search_field = ('business_name')
filter_horizontal = ('where',)
class LocationAdmin(admin.ModelAdmin):
list_display = ('located_at', 'city', 'country')
search_field = ('located_at')
list_filter = ('located_at', 'city')
class Item_listAdmin(admin.ModelAdmin):
list_display = ('item_name',)
class Price_listAdmin(admin.ModelAdmin):
list_display = ('price',)
fields = ('price', 'business_name', 'item_name')
admin.site.register(Businesses, BusinessAdmin)
admin.site.register(Location, LocationAdmin)
admin.site.register(Item_list, Item_listAdmin)
admin.site.register(Price_list, Price_listAdmin)
I suspect you're missing a capital B in the foreign key definition for "businessID" on Price_List.
I'm not sure but I think the whole "related_name='businessID'" argument is unnecessary since you're wanting to create a foreign key to the primary key of the Businesses table.
Try it - it might work!