I have two schemas: schema_1 and schema_2. In schema_1 I created a class A such as:
class_A():
__table__='my_table'
A.1 = Columns(Integer, primary_key=True)
A.2 = Column(Integer)
then I created a class B that inherits and expands class A:
class_B():
enter code here`changed = Column(Boolean)
For class A changed column does not exist but I need this column set as Null to preprocessing. I tried to add sth like changed = Column(Boolean, nullable=True, default=None) to class A but it does not work. I was looking for some interesting information in the sqlalchemy but without success. Could you advice what I can do / where can I look for how I can add this kind of column?
Related
I want to specify a column in my sqlalchemy model to only accept values that are in a predefined list (in the example below ['bar','baz'].
Below is a minimal example of what such a model would look like
class Foo(db.Model):
"""Example Model"""
# simple autoincrement primary key
id: int = db.Column(db.Integer, primary_key=True, autoincrement=True)
# this column should be constrained to ['bar', 'baz']
exclusive_str: str = db.Column(db.String, nullable=False)
I found the check constraint in the official documentation, but the examples listed are super simple and don't seem to cover a use case like the above. How do I go about solving this?
I am having a model structure like:
class user(models.Model):
name = models.CharField(max_length=100)
tasks = models.IntegerField(default=0)
class project(models.Model):
worker = models.ForeignKey(user, on_delete=models.CASCADE)
project_name = models.CharField(max_length=100)
class task(models.Model):
project = models.ForeignKey(project, on_delete=models.CASCADE)
task_name = models.CharField(max_length=150)
expected_date = models.DateField(auto_now=False,auto_now_add=False,)
actual_date = models.DateField(auto_now=False,auto_now_add=False,blank=True,null=True,)
I want to traverse through the task list and if actual date field is not null i.e. task completed then to update the tasks field in user class by 1. I have written the following code:
a = task.objects.filter(actual_date__isnull=False)
for x in a:
x.project.worker.tasks+=1
However this is not giving the desired result. What should I do?
You are not saving your object after modifying it - simply modifying the value doesn't write it to the database. Try this instead:
a = task.objects.filter(actual_date__isnull=False)
for x in a:
worker = x.project.worker
worker.tasks += 1
worker.save()
On a separate note you should consider following PEP8 conventions and using CamelCase for your class names. As it is currently you can very easily mix up classes with objects.
I am writing a script which can pull data from different API's and store into a MySQL database. This application will run from command line. So I am only using Django's ORM.
But when I am creating a model which doesn't have primary key but have a column named id. When I am trying to save data in this model I am getting a error django.db.utils.IntegrityError: (1048, "Column 'id' cannot be null")
I am really confused why this happens. Because from API I get values from id column and there is no chance to get null or empty value for this column.
Please suggest me what I am doing wrong here.
Here is my model:
class Graphite(models.Model):
class Meta:
db_table = 'graphite'
id = models.BigIntegerField()
full_name = models.CharField(max_length=250, null=True)
email = models.CharField(max_length=250, null=True)
status = models.CharField(max_length=150, null=True)
And this is the code when I am trying to save data in this model:
Graphite.objects.using('database_name').create(
id=row['id'],
full_name=row['full_name'],
email=row['email'],
status=row['status'])
When saving data into model I am using Graphite.objects.using('database_name'). because I have multiple database connected in this application.
Well I'm not sure did you use django migrations, but it won't let you create this kind of model in django, where your id property (in model) hasn't primary key as its parameter (mySQL). So why don't you just define:
class Graphite(models.Model):
class Meta:
db_table = 'graphite'
id = models.BigIntegerField(primary_key=True)
full_name = models.CharField(max_length=250, null=True)
email = models.CharField(max_length=250, null=True)
status = models.CharField(max_length=150, null=True)
so set primary_key on id? Then you wouldn't have to pass id when creating Graphite.
BUT
If you have to provide id which is something you need to have in every Graphite model and it's something different than primary key, then just define it different, let's say row_id. But you should still have at last one id property in your model with primary_key set to True when you want to have id as BigIntegerField.
EDIT (on the example)
In mySQL execute this command:
ALTER TABLE graphite ADD COLUMN row_id BIGINT;
Then your model should looks like this:
class Graphite(models.Model):
class Meta:
db_table = 'graphite'
row_id = models.BigIntegerField()
full_name = models.CharField(max_length=250, null=True)
email = models.CharField(max_length=250, null=True)
status = models.CharField(max_length=150, null=True)
And usage:
Graphite.objects.using('database_name').create(
row_id=row['id'],
full_name=row['full_name'],
email=row['email'],
status=row['status'])
and that's it.
The problem is that you do not have a primary key.
From the docs:
Each model requires exactly one field to have primary_key=True (either explicitly declared or automatically added).
So, you have to make your id field a primary key by adding primary_key=True. Then, it won't complain.
You are overriding id from default django table id.
so there is no id for primary key. Just make it primary=True. or use another id like graphaite_id
You are missing your primary key, make sure you have your primary=True and to store your id make another column for it
Apologies for the awful title.
I'm setting up a website, using Flask and SQLAlchemy. I'd like a list of tags available for all content types. I'm using sqlite3 for my development database.
After inputting data using the html form, only the tag is not being saved to the db. I'm not sure where the weak point(s?) lies. I can't tell if I've got something wrong conceptually about how SQLAlchemy handles inheritance, passing arguments to a subclass and/or the many to many relationship. I'd really appreciate any clarity on the subject or recommendations about how to improve the model.
Here's the code:
I have an association table for the Many-to-Many relationship between the tags and Content:
tagging_association = Table('tagging', Model.metadata,
Column('content_id', Integer, ForeignKey('content.id')),
Column('tag_id', Integer, ForeignKey('tags.id'))
)
I've set up a Content class:
class Content(Model):
'''
The base class for all content types.
'''
__tablename__ = 'content'
id = Column(Integer, primary_key=True)
tag = relationship('Tag', secondary='tagging', backref='content')
type = Column(String(50))
__mapper_args__ = {
'polymorphic_identity':'content',
'polymorphic_on':type
}
All content types are subclasses of Content, using SQLAlchemy's Joined Table Inheritance:
class Entry(Content):
'''The database model for blog-like entries on the homepage.'''
__tablename__ = 'entries'
id = Column(Integer, ForeignKey('content.id'), primary_key=True)
title = Column(String(200))
body = Column(String)
__mapper_args__ = {
'polymorphic_identity':'entries',
}
# Want to pass a single tag first, just to get it to work. Is this how would I do that?
def __init__(self, title, body, *args, **kwargs):
super(Entry, self).__init__(*args, **kwargs)
self.title = title
self.body = body
And the Tag class:
class Tag(Model):
'''Tag database model.'''
__tablename__ = 'tags'
id = Column(Integer, primary_key=True)
tag = Column(String(30), nullable=False, unique=True)
def __init__(self, tag):
self.tag = tag
Here's my WTForms class:
class EntryForm(Form):
title = TextField('Title', validators=[Required()])
body = TextAreaField('Body', validators=[Required()])
tags = TextField('Tags')
submit = SubmitField('Submit')
Here's where I take the form data and add it to the db:
#mod.route('/add_entry/', methods=['GET', 'POST'])
#requires_admin
def add_entry():
form = EntryForm()
if form.validate():
entry = Entry(form.title(), form.body(), form.tags())
form.populate_obj(entry)
db_session.add(entry)
db_session.commit()
return redirect(url_for('general.index'))
return render_template('general/add_entry.html', form=form)
If what you showed above is the actual code, you can see that your relationship is named tag (tag = relationship(...), but in the EntryForm your TextField property is called tags. So your tag relationship is never set and therefore never saved. What is set to the field tags is just ignored. I assume you just need to rename the Content.tag to Content.tags.
Above should answer the question why it is not saved, but if you just rename the field, this will not solve your problem. You need to write code that handles your Tags properly:
when Tag text is assigned to a Content, then you need:
look if the Tag with this tag already exists.
if it does, load it.
if it does not, create it
append the found/created tag to the Content.tags
See the answer to Inserting data in Many to Many relationship in SQLAlchemy for similar problem to give you an idea what to do and how it could be done.
I have some code here. I recently added this root_id parameter. The goal of that is to let me determine whether a File belongs to a particular Project without having to add a project_id FK into File (which would result in a model cycle.) Thus, I want to be able to compare Project.directory to File.root. If that is true, File belongs to Project.
However, the File.root attribute is not being autogenerated for File. My understanding is that defining a FK foo_id into table Foo implicit creates a foo attribute to which you can assign a Foo object. Then, upon session flush, foo_id is properly set to the id of the assigned object. In the snippet below that is clearly being done for Project.directory, but why not for File.root?
It definitely seems like it has to do with either 1) the fact that root_id is a self-referential FK or 2) the fact that there are several self-referential FKs in File and SQLAlchemy gets confused.
Things I've tried.
Trying to define a 'root' relationship() - I think this is wrong, this should not be represented by a join.
Trying to define a 'root' column_property() - allows read access to an already set root_id property, but when assigning to it, does not get reflected back to root_id
How can I do what I'm trying to do? Thanks!
from sqlalchemy import create_engine, Column, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import backref, relationship, scoped_session, sessionmaker, column_property
Base = declarative_base()
engine = create_engine('sqlite:///:memory:', echo=True)
Session = scoped_session(sessionmaker(bind=engine))
class Project(Base):
__tablename__ = 'projects'
id = Column(Integer, primary_key=True)
directory_id = Column(Integer, ForeignKey('files.id'))
class File(Base):
__tablename__ = 'files'
id = Column(Integer, primary_key=True)
path = Column(String)
parent_id = Column(Integer, ForeignKey('files.id'))
root_id = Column(Integer, ForeignKey('files.id'))
children = relationship('File', primaryjoin=id==parent_id, backref=backref('parent', remote_side=id), cascade='all')
Base.metadata.create_all(engine)
p = Project()
root = File()
root.path = ''
p.directory = root
f1 = File()
f1.path = 'test.txt'
f1.parent = root
f1.root = root
Session.add(f1)
Session.add(root)
Session.flush()
# do this otherwise f1 will be returned when calculating rf1
Session.expunge(f1)
rf1 = Session.query(File).filter(File.path == 'test.txt').one()
# this property does not exist
print rf1.root
My understanding is that defining a FK foo_id into table Foo implicit creates a foo attribute to which you can assign a Foo object.
No, it doesn't. In the snippet, it just looks like it is being done for Project.directory, but if you look at the SQL statements being echo'ed, there is no INSERT at all for the projects table.
So, for it to work, you need to add these two relationships:
class Project(Base):
...
directory = relationship('File', backref='projects')
class File(Base):
...
root = relationship('File', primaryjoin='File.id == File.root_id', remote_side=id)