writing a model for existing mssql table Django - django

I've this tables in a mssql server:
Table name: Items
Fields:
ItemID - primarykey - integer
StorageLocation - varchar(100)
Table name: Inventory
Fields:
InvetoryID - primarykey - integer
ItemID - foreignkey - integer
sku - integer
QtyToList - integer
How can I tell to Django that ItemID is the ID field and it's also the PK ? (do I need to tell it also it's an integer field?)
What is the best way to model it in django.
Thanks in advance
Amit

class Item(models.Model):
class Meta:
db_table='Items'
item_id = models.IntegerField(primary_key=True, db_column='ItemID')
storage_location = models.CharField(max_length=100, db_column='StorageLocation')
class Inventory(models.Model):
class Meta:
db_table='Inventory'
inventory_id = models.IntegerField(primary_key=True, db_column='InventoryID')
item = models.ForeginKey('Item', db_column='ItemID')
sku = models.IntegerField()
qty_to_list = models.IntegerField(db_column='QtyToList')
Model Field Reference: https://docs.djangoproject.com/en/1.7/ref/models/fields/#db-column
Model Meta Reference: https://docs.djangoproject.com/en/1.7/ref/models/options/

First, I recommend using the 'inspectdb' command, then you can modified the result as you want. Please visit the inspectdb documentation for more details on it.
The documentation is quite helpful.

Related

How can I model a database view in Django if it doesn't have a primary key?

I have a database view that relates 2 companies by foreign keys like so:
DB company_view:
company1_id FK to Company,
company2_id FK to Company,
description text
where
--- some company criteria ---
I try model in Django as unmanaged like so:
class CompanyView(models.Model):
company1 = models.ForeignKey(Company, related_name='company1_id', parent_link=True)
company2 = models.ForeignKey(Company, related_name='company2_id', parent_link=True)
description = models.TextField()
class Meta:
managed = False
db_table = 'company_view'
For the Admin class I have:
#admin.register(models.CompanyView)
class CompanyViewAdmin(AdvancedModelAdmin):
list_display = ('company1', 'company2', 'description')
But the admin page throws exception like:
psycopg2.errors.UndefinedColumn: column company_view.id does not exist
It doesn't make sense to have a primary id key, so is there any way around this?
Thanks
why you dont make a many-to-many relationship?
company = models.ManyToManyField(Company)
look: https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_many/
this will solve your problem, since it use a object instance.

ForeignKey updates aren't cascading on Django created tables in Postgres

This is the error that I get when I try to update the value in the "parent" table that the foreign key is looking at in a related table:
ERROR: update or delete on table "product" violates foreign key constraint "pd_family_product_guid_ada83db3_fk_product_guid" on table "pd_family"
DETAIL: Key (guid)=(902d30b8-26ba-ea11-a812-000d3a5bbb60) is still referenced from table "pd_family".
SQL state: 23503
This is what I have for my models:
class Product(models.Model):
guid = models.UUIDField(primary_key=True)
product = models.CharField(max_length=10)
year = models.IntegerField()
previous_product_name = models.CharField(max_length=10)
class StandardProductFieldsMixin(models.Model):
product_guid = models.ForeignKey('Product', on_delete=models.CASCADE, db_column='product_guid')
class Meta:
abstract = True
class ActiveFieldMixin(models.Model):
active = models.BooleanField()
class Meta:
abstract = True
class Family(StandardProductFieldsMixin, ActiveFieldMixin):
new_code = models.IntegerField(null=True)
code = models.DecimalField(max_digits=20, decimal_places=2)
title = models.CharField(max_length=255)
desc = models.TextField(null=True)
fam_desc = models.TextField(null=True)
When I try to change a value of guid in Product, my expectation is that it would automatically change it in Family as well. I'm trying to change it with something like:
UPDATE product
SET guid = '902D30B8-26BA-EA11-A812-000D3A5BBB6B'
WHERE guid = '902D30B8-26BA-EA11-A812-000D3A5BBB60'
I guess I was under the wrong impression. Do I need to do something additional in the model? Looked at the documentation for something like on_update, but not seeing that either an **options or as a parameter for models.ForeignKey.
From what I gather after reading about it for more than an hour, if I want this kind of functionality I just need to add it Postgres manual, by dropping the constraint and adding it back with ON UPDATE CASCADE.
Apparently I'm under the wrong impression:
https://stackoverflow.com/a/61648910/3123109
Sounds like Django model migrations implement neither ON DELETE nor ON UPDATE database CASCADES options. I guess I'd need to drop into the database and implement them there.

Django union two tables into single model

I have an external database which I can't modify in any way (read-only). It has three tables - Company (id), CompanyContact (company_id, contact_id), Contact (id, company_id).
Basically, Contact has a nullable foreign-key to Company table and it works as many-to-one, but if company_id is null, I have to look into CompanyContact table, which is many-to-many kind relationship.
How can I combine these two tables (Contact and CompanyContact) into one model - Contact? In other words, how can I get all contacts for a given company?
In SQL that would be something like:
select contact.id from contact where company_id = XXX
union
select contact_id from companycontact where company_id = XXX
Django models:
class Company(models.Model):
uuid = models.CharField(max_length=36, primary_key=True, db_column='id')
class Meta:
managed = False
class Contact(models.Model):
uuid = models.CharField(max_length=36, primary_key=True, db_column='id')
company = models.ForeignKey(Company, db_column='company_id')
class Meta:
managed = False
I don't have a model for CompanyContact. And there is nothing to show in views because that basically is my question, how to get contacts for a given company.
The original tables in your database are not properly structured. It's incorrect that the contact field should have a company_id field. That needlessly complicates all queries (raw SQL or Django) because an additional check is needed on the contact_id field.
On the other hand it's perfectly legit for two entities in a many to many relationship to have exactly one mapping instead of many. So there isn't one clear answer to this question. I suppose your best bet would be to add a ManyToMany field as well. I am making this suggestion purely on the fact that you say the data is read only
class Contact(models.Model):
uuid = models.CharField(max_length=36, primary_key=True, db_column='id')
company = models.ForeignKey(Company, db_column='company_id')
companies = models.ManyToManyField(Company, related_name='companies')
class Meta:
managed = False

Django with legacy database - how to work with DB sequences?

Given a database table that was created using this SQL query:
CREATE TABLE Bill
(
Time DATE NOT NULL ,
Address VARCHAR2 (60) NOT NULL ,
ID NUMBER NOT NULL
) ;
ALTER TABLE Bill ADD CONSTRAINT Bill_PK PRIMARY KEY ( ID ) ;
CREATE SEQUENCE Bill_ID_SEQ START WITH 1 NOCACHE ORDER ;
CREATE OR REPLACE TRIGGER Bill_ID_TRG BEFORE
INSERT ON Paragony FOR EACH ROW BEGIN :NEW.ID := Bill_ID_SEQ.NEXTVAL;
END;
I have to use it with Django ORM so I have run inspectdb command. It is the autogenerated code:
class Bill(models.Model):
time = models.DateField()
address = models.CharField(max_length=60)
id = models.IntegerField(primary_key=True)
class Meta:
managed = False
db_table = 'bill'
After saving it to app' models.py file and running migrations everything was fine. I could read DB like it was created using ORM. However there was a problem with creating rows in Bill table.
It is simple form for Bill model:
class BillForm(ModelForm):
class Meta:
model = Bill
fields = ('time', 'address')
The problem is that I can't retrieve the ID generated with the DB sequence. Adding id field to Form won't work because we have to generate it with code and then pass as a argument. Even than database will create different ID that will not be possible to retrieve without raw queries.
The solution is really simple. We have to remove the id field from Bill model:
class Bill(models.Model):
time = models.DateField()
address = models.CharField(max_length=60)
# Remove 'id' field so the ORM can work properly.
# id = models.IntegerField(primary_key=True)
class Meta:
managed = False
db_table = 'bill'
This way the Django ORM can make all the hard work and correctly use legacy database sequences. Bill objects now can be created using BillForm and they will have proper IDs.

Django Relational database lookups

I cant figure out how to do relationships.
I have a products model and a stores model.
A product has a foreign key to the stores.
So i would like to get the product name, and the store name in the same lookup.
Since the products model is:
class Products(models.Model):
PrName = models.CharField(max_length=255)
PrCompany = models.ForeignKey(Companies)
And the company model is:
class Companies(models.Model):
ComName = models.CharField(max_length=255)
How do i make django return ComName (from the companies model) when i do:
Prs = Products.objects.filter(PrName__icontains=ss)
Assuming you get results:
Prs[0].PrCompany.ComName # Company name of the first result
If you want all the company names in a list:
company_names = [product.PrCompany.ComName for product in Prs]