Mysql User table: user_id int (pk), name varchar, last_name varchar
SQLAlchemy model:
class User(db.Model):
__tablename__ = 'user'
user_id = Column('user_id',INTEGER, nullable=False, primary_key=True)
name = Column('name',String(256), nullable=False)
lastname = Column('last_name',String(256), nullable=False)
If I want to add columns in my User table like phone_number and address which are not going to be used by my application. Do I need to change necessary my model of sqlalchemy or is it not harmful?
You do not have add the columns into your User class. But if you add data into the database using sqlachemy, it will construct the rows using only the fields from the class User, so if you do not have the defaults set in the database table definition, it may cause an error.
EDIT: You should be safe if you only use the model to query the database.
Related
Currently i have the following model that i would like to set CharField as primary key( my database is Mysql)
class Customer(models.Model):
class Meta:
db_table = "customers"
verbose_name = _('Customer')
verbose_name_plural = _('Customers')
customer_id = models.CharField(_('Customer ID'),max_length=255, primary_key=True)
name = models.CharField(_('Name'), max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
In the document it stated that :
primary_key=True implies null=False and unique=True. Only one primary
key is allowed on an object.
In Mysql the primary key has the following structure:
customer_id, type=varchar(255), collation=latin1_swedish_ci,
Attributes=blank Null=No, Default=None,Comments=blank, Extra=blank
but when i try to use the save() method with null value for primary key:
Customer.objects.create(customer_id=None, name="abc")
It still save Null value in the primary key without returning any error or validation, why is that?
EDIT:
After saving in Mysql it show the value of the customer_id=blank(when try to save it as None). Why it set to blank when saving customer_id=None?
When you create object for the first time
Customer.objects.create(customer_id=None, name="abc")
It will store customer_id value as '' (empty value, not null) and there are no other object we have created till now, so it's unique too.
Now when you again create an Customer object
Customer.objects.create(customer_id=None, name="xyz")
This will throw an error django.db.utils.IntegrityError: UNIQUE constraint failed: customers.customer_id because we already have empty value in our customer_id value. So, this is throwing an error of UNIQUE constraint
Do you use Django Rest Framework?
Then you may have add your customer_id to the read_only_fields in serializer.py
The result is:
You can't add an id in your request
Django doesn't recognised it as a required field anymore (except of Django Admin)
Django accepts a NULL value, which shouldn't be allowed
I have three models:
class Agent(models.Model):
name = models.CharField(max_length=200)
class Phone(models.Model):
calls = models.CharField(max_length=200)
agent_phone_name = models.CharField(max_length=200)
agent = models.ForeignKey(Agent, on_delete=models.CASCADE)
class Chat(models.Model):
chats = models.CharField(max_length=200)
agent_chat_name = models.CharField(max_length=200)
agent = models.ForeignKey(Agent, on_delete=models.CASCADE)
Chat and Phone links to agent with foreign key.
I want to make a table like this:
agent1 | sum(calls) | sum(chats)
agent2 | sum(calls) | sum(chats)
agent3 | sum(calls) | sum(chats)
First question is:
I've read about SQL foreign key as a way to maintain data and referential integrity. However in my case, there are miss call and chat (agent didn't pick it up) that generate rows of data has empty value on agent_name. So when I'm inserting the phone/chat data and update the FK, I have leave the FK empty and kinda that conflicts with the idea of FK. What's the best way to handle this?
Second question is: is using Foreign key the only way to perform SQL join table query in Django ORM? Is there any other way around it?
Thank you !
I'm not sure I've titled this question correctly. I can add a unique constraint well enough to any of my tables, but in the case below I'm not sure how to do what I'm after:
class Branch(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(160))
#foreign key for 'branches' in Account class. access with Branch.account
account_id = db.Column(db.Integer, db.ForeignKey('account.id'))
class Account(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(160), unique=True)
branches = db.relationship('Branch', backref = 'account', lazy = 'dynamic')
So when I added a unique constraint to the Branch table's name column, I could not add same-name branches to different accounts. For example, Seattle, could be a branch for both AccountA and AccountB.
What I want to do is apply a constraint that checks for uniqueness only when account.id is the same. Is this possible?
Thanks to dirn, pointing out the duplicate, I've added:
__table_args__ = (db.UniqueConstraint('account_id', 'name', name='_account_branch_uc'),
)
to my Branch class, and then pushed it to the database with alembic via:
def upgrade():
op.create_unique_constraint('_account_branch_uc', 'branch', ['name','account_id'])
I will note, though, that since I added this constraint manually via alebmic, I'm not certain if I added it correctly to my model. I suppose I'll find out when I eventually wipe my DB and start a new one.
EDIT
I have rolled a new database and the __table_args__ from above works correctly!
I want to clarify the format of providing initial data in raw SQL for a Django model that uses a many to many relationship. I've based my query on this example. I know I'm not required to specify the through parameter in ManyToManyField for this case, but I would like to have the table listed explicitly.
Backend db is MySQL & table names are lowercase Class names.
Model :
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
I suppose the correct way to provide data would be :
INSERT INTO person VALUES ('Ringo Starr')
INSERT INTO person VALUES ('Paul McCartney')
INSERT INTO group VALUES ('The Beatles')
INSERT INTO membership VALUES (1, 1)
INSERT INTO membership VALUES (2, 1)
How will I specify this data if I did not declare the Membership table explicitly and didn't use the through parameter? Is the following correct?
INSERT INTO person VALUES ('Ringo Starr')
INSERT INTO person VALUES ('Paul McCartney')
INSERT INTO group VALUES ('The Beatles', 1)
INSERT INTO group VALUES ('The Beatles', 1)
UPDATE : The second method isn't correct. The members field under Group class isn't a real dB column.
Short answer:
The correct way to do it in SQL is the same as when you use through, but the table that was membership before will either have a name generated by Django like person_group_a425b, or a name you specify with the db_table parameter on Group.members.
More details:
Even if you don't make a model explicitly for the table that joins them together, Django will create a join table for them.
From the Django docs about how the table is named:
Behind the scenes, Django creates an intermediary join table to represent the
many-to-many relationship. By default, this table name is generated using the name of
the many-to-many field and the name of the table for the model that contains it. Since
some databases don’t support table names above a certain length, these table names will
be automatically truncated to 64 characters and a uniqueness hash will be used. This
means you might see table names like author_books_9cdf4; this is perfectly normal.
You can provide a shorter/different name for the join table in the definition of the ManyToManyfield, using the db_table option.
I am trying to generate a report across 2 models/ tables. Here they are:
class Members(models.Model):
username = models.CharField(max_length=30,null=True, unique=True)
email = models.CharField(max_length=100,null=True, unique=True)
name = models.CharField(max_length=30,null=True)
phone = models.CharField(max_length=30,null=True)
and
class Report(models.Model):
report_text = models.CharField(max_length=500)
reporter_id = models.IntegerField(db_index=True)
reported_id = models.IntegerField(db_index=True)
date_created = models.DateTimeField(null=True)
date_read = models.DateTimeField(null=True)
The 2 tables obviously have auto increment IDs as the primary key.
The report will look like this:
Reported Phone | Reported Name | Report | Date Reported | Date Report Read
Everyone reported on will be in the member table. The reporter ID is the ID of the member who logged the report. The reported_id is the ID of the person the report is on. I need to do a join across the 2 models to get the members name and their phone number. I can't quite work it out form the doc. I believe I should make the reported_id and reporter_id both foreign keys to the Members table primary key ID field. How do I do that and what code will extract the report for all entries submitted by a specific reporter?
Do I user reported_id = models.ForeignKey(Members) and do the same for reporter_id. It seems odd as I don't specify the field that the field is foreign to. The ORM is supposed to make it easier (and it usually does!). I could do it with a join in SQL but this has got me stumped.
I hope the question makes sense.
Thanks in advance
Rich
How do I do that and what code will
extract the report for all entries
submitted by a specific reporter?
Yes, do reported_id = models.ForeignKey(Members)
The field will be the target models primary key, which is in your case id since you haven't specified one.
You will need to specify a related_name for one of these fields to prevent a name clash for the reverse foreign key accessor.
After setting up the foreign key field, to get all objects related via that foreign key, use the related_name to query the related model.
http://docs.djangoproject.com/en/dev/topics/db/queries/#following-relationships-backward
For example, if you set up your model as:
reporter = models.ForeignKey(Members, related_name="reports_by_me")
reported = models.ForeignKey(Members, related_name="reports_by_others")
You could access all related Report models via that foreign key by
member_instance.reports_by_me.all()
member_instance.reports_by_others.all()