TastyPie Foreignkey trouble - tastypie

I'm using django.contrib.auth.models.User model class with no custom code and i've the following model as well:
class XYZ(models.Model):
xyzstring = models.TextField()
created_by = models.ForeignKey(User)
The resource classes are as follows:
class UserResource(ModelResource):
class Meta:
queryset = User.objects.all()
resource_name = 'user'
excludes = ['email', 'password', 'is_active', 'is_staff', 'is_superuser']
filtering = {
'username': ALL,
}
class XYZResource(ModelResource):
created_by = fields.ForeignKey(UserResource, 'user', full=True)
class Meta:
queryset = XYZ.objects.all()
resource_name = 'xyz'
allowed_methods = ['get','post','put']
details_uri_name= 'id'
paginator_class = Paginator
When i go to /api/v1/xyz/ I get the error:
model 'XYZ' has an empty attribute 'user' and doesn't allow a null value.
The database has valid userids in the created_by column in the xyz table. IF i remove created_by line in the XYZResource, i dont get created_by attribute at all. created_by will not take null values as XYZ objects are created by valid users.
Please suggest what should i do to fix this problem

Guys thank you very much for trying to help me out. Out of frustration i replaced "user" in the following line with "created_by" and it WORKED!!
created_by = fields.ForeignKey(UserResource, 'user', full=True)
TO
created_by = fields.ForeignKey(UserResource, 'created_by', full=True)

Change the created_by field to allow a null value
created_by = fields.ForeignKey(UserResource, 'user', full=True, null=True)

Related

FastAPI - SQLModel, Relationship and Insertion of New Row leading to Insertion of New Row in Another Table

Suppose I have two tables, Email and VStatus ('V' stands for 'Verification').
class Email(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
email: str
vstatus_id: Optional[int] = Field(default=None, foreign_key='VStatus.id')
vstatus: Optional["VStatus"] = Relationship()
class VStatus(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
vstatus: StatusEnum = Field(default=StatusEnum.Unverified) # InProgress, Verified, Unverified
vdesc: str = Field(default="") # Verification Description
How should I structure my SQLModel tables such that whenever I create a new email via the API say '/create_email', with just a single field email, it will automatically created a new row in the VStatus table via the Relationship defined in the Email table?
Example:
POST /create_email
{
'email': 'example#example.com'
}
I will get a response that looks like:
response = {
'email': 'example#example.com',
'vstatus_id': '1001', # example
}
And in the VStatus table, there will be a new row that looks like:
id
vstatus
vdesc
1001
Unverified
Null

Conflicts with relationship between tables

I've been constantly getting a warning on the console and I'm going crazy from how much I've been reading but I haven't been able to resolve this:
SAWarning: relationship 'Book.users' will copy column user.uid to column user_book.uid, which conflicts with relationship(s): 'User.books' (copies user.uid to user_book.uid). If this is not intention, consider if these relationships should be linked with back_populates, or if viewonly=True should be applied to one or more if they are read-only. For the less common case that foreign key constraints are partially overlapping, the orm.foreign() annotation can be used to isolate the columns that should be written towards. The 'overlaps' parameter may be used to remove this warning.
The tables the console cites in this notice are as follows:
user_book = db.Table('user_book',
db.Column('uid', db.Integer, db.ForeignKey('user.uid'), primary_key=True),
db.Column('bid', db.Text, db.ForeignKey('book.bid'), primary_key=True),
db.Column('date_added', db.DateTime(timezone=True), server_default=db.func.now())
)
class User(db.Model):
__tablename__ = 'user'
uid = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(25), nullable=False)
hash = db.Column(db.String(), nullable=False)
first_name = db.Column(db.String(30), nullable=True)
last_name = db.Column(db.String(80), nullable=True)
books = db.relationship('Book', secondary=user_book)
class Book(db.Model):
__tablename__ = 'book'
bid = db.Column(db.Text, primary_key=True)
title = db.Column(db.Text, nullable=False)
authors = db.Column(db.Text, nullable=False)
thumbnail = db.Column(db.Text, nullable=True)
users = db.relationship('User', secondary=user_book)
I use the user_book table to show the user the books he has added.
What am I missing? I take this opportunity to ask, semantically the relationship between tables and foreign keys is being done correctly?
As the warning message suggests, you are missing the back_populates= attributes in your relationships:
class User(db.Model):
# …
books = db.relationship('Book', secondary=user_book, back_populates="users")
# …
class Book(db.Model):
# …
users = db.relationship('User', secondary=user_book, back_populates="books")
# …
I kind of figure this out.
As the code in official tutorial.
from sqlalchemy import Column, ForeignKey, Integer, String, Table
from sqlalchemy.orm import declarative_base, relationship
Base = declarative_base()
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True)
name = Column(String(64))
kw = relationship("Keyword", secondary=lambda: user_keyword_table)
def __init__(self, name):
self.name = name
class Keyword(Base):
__tablename__ = "keyword"
id = Column(Integer, primary_key=True)
keyword = Column("keyword", String(64))
def __init__(self, keyword):
self.keyword = keyword
user_keyword_table = Table(
"user_keyword",
Base.metadata,
Column("user_id", Integer, ForeignKey("user.id"), primary_key=True),
Column("keyword_id", Integer, ForeignKey("keyword.id"), primary_key=True),
)
Doesn't it make you wander why the relationship only exists in User class rather than both class ?
The thing is, it automatically creates the reverse relationship in Keyword class (a "backref='users' liked parameter is required I supposed ?)

Is there a way of viewing the columns for relationships within pgAdmin?

I've begun populating the following tables inside my database:
class ModelItem(Base):
__tablename__ = 'item'
name = Column('name', String, primary_key=True)
set_id = Column(String, ForeignKey('set.name'))
class ModelSet(Base):
__tablename__ = 'set'
name = Column('name', String, primary_key=True)
items = relationship('ModelItem', backref='set')
Everything seems to be working fine since I can query the children of the parent record and come up with the expected data within my code. I'm just wondering if there's a way to see that same items column in pgAdmin like I can with all the other columns for the parent table

Set server_default value for relationship table

I have two tables for administrators and roles, connected vía the third table assignments (many-to-many relationship) with the fields role_id, administrator_id and some extra fields created_at and updated_at, which I would like to populate automatically:
assignments = db.Table('assignments',
db.Column('role_id', db.Integer, db.ForeignKey('roles.id')),
db.Column('administrator_id', db.Integer,
db.ForeignKey('administrators.id')),
db.Column('created_at', db.DateTime, server_default=db.func.now()),
db.Column('updated_at', db.DateTime, server_default=db.func.now(),
onupdate=db.func.now()),
db.ForeignKeyConstraint(['administrator_id'], ['administrators.id']),
db.ForeignKeyConstraint(['role_id'], ['roles.id'])
)
class Administrator(db.Model, UserMixin):
__tablename__ = 'administrators'
id = Column(Integer, primary_key=True, server_default=text("nextval('administrators_id_seq'::regclass)"))
email = Column(String(255), nullable=False, unique=True, server_default=text("''::character varying"))
name = Column(String(255))
surname = Column(String(255))
roles = db.relationship('Role', secondary=assignments,
backref=db.backref('users', lazy='dynamic'))
class Role(db.Model):
__tablename__ = 'roles'
id = Column(Integer, primary_key=True, server_default=text("nextval('roles_id_seq'::regclass)"))
name = Column(String(255))
But when I assign a role to an administrator
admin.roles = [role1]
db.session.add(admin)
db.session.commit()
it breaks with the following error:
IntegrityError: (psycopg2.IntegrityError) null value in column "created_at" violates not-null constraint
DETAIL: Failing row contains (1265, 19, 3, null, null).
[SQL: 'INSERT INTO assignments (role_id, administrator_id) VALUES (%(role_id)s, %(administrator_id)s)'] [parameters: {'administrator_id': 19, 'role_id': 3}]
Is there any way to set a default value for created_at and updated_at fields in assignments table?
It worked using default and onupdate parameters instead of server_default and server_onupdate:
db.Column('created_at', db.DateTime, default=db.func.now()),
db.Column('updated_at', db.DateTime, default=db.func.now(),
onupdate=db.func.now()),
Try this
db.Column('created_at', db.DateTime, server_default=text("now()"))

sqlalchemy, violation foreign key constraint

I am new to sqlalchemy. I want to create a class which has two foreign key for different tables. Why I get next error?
sqlalchemy.exc.IntegrityError: (IntegrityError) insert or update on table "event" violates foreign key constraint "event_user_fkey"
DETAIL: Key (user)=(U) is not present in table "user".
'INSERT INTO event (id, "user", item) VALUES (%(id)s, %(user)s, %(item)s)' {'item': 'I', 'user': 'U', 'id': 'E'}
My code is next:
class User(Base):
__tablename__ = 'user'
id = Column(String, primary_key=True)
def __init__(self, id):
self.id = id
class Item(Base):
__tablename__ = 'item'
id = Column(String, primary_key=True)
def __init__(self, id):
self.id = id
class Event(Base):
__tablename__ = 'event'
id = Column(String, primary_key=True)
user = Column(String, ForeignKey('user.id'))
item = Column(String, ForeignKey('item.id'))
def __init__(self, id, user_id, item_id):
self.id = id
self.user = user_id
self.item = item_id
I use postgresql as a back end.
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
usr = User('U')
it = Item('I')
event = Event('E', usr.id, it.id)
session.add(usr)
session.add(it)
session.add(event)
The error seems pretty clear:
Key (user)=(U) is not present in table "user".
So it's trying to insert the Event row before the User has been committed to the database, which breaks the ForeignKey constraint, causing this error. Try committing the User and Item to the database before committing the Event, which depends on them and the problem should evaporate.