Model.create(...) possibly corrupting other items
See original GitHub issueI have a database where I store user information. I have an API endpoint using quart (async flask) where I can submit information to be put in a database. I have a weird bug however, where for some reason when I use my discord account’s data, it updates every other user’s data to be the same (except for discord_id which is primary key and also payments linked to that id) and also replaces any further inserts.
This may be a logic error, or could possibly be a peewee error somehow.
Here is an example of how data is changed.
Example 1
Discriminator on insert for person 1: 3606 Discriminator on insert for person x: 0661
Discriminators after person x inserted: 0232, 0232
Example 2
So I thought it was some indexing issue so I tried this:
Discriminator on insert for person 1: 3606 Discriminator on insert for person 2: 0434
Discriminators after person x inserted: 3606, 0434
Discriminator on insert for person x: 0232
Discriminators after person x inserted: 0232, 0232, 0232
This is very confusing to me, as the code to create a new user replaces the data of other users. As you see, person 2 does not change person 1 but person x does. However, this gets even more confusing, as when person 2 is inserted after person x, person 2 has the same data (except for primary key) as person x.
Possible reasons
- Person x has “()” in their username, which is put in the database (EDIT: after changing my username, nothing changed)
- Person x is my current user (logic error in code as access token effects somehow?)
- Past that I do not know
Relevant code
(mind my spaghet code)
@QUART.route(API_PRE + "add_payment", methods=["POST"])
async def add_payment():
"""
Add a new payment to existing or new user.
"""
if request.method == "POST":
request_parameters = await request.get_json(force=True, silent=True)
discord_id = request_parameters["discord_id"]
amount_payed_usd = request_parameters["amount_payed_usd"]
subtype = request_parameters["subtype"]
pre_payment = request_parameters["pre_payment"]
if (
request_parameters["discord_access_token"] is not None
and discord_id is not None
and amount_payed_usd is not None
and subtype is not None
and pre_payment is not None
):
try:
member = Member(request_parameters["discord_access_token"], MAIN_BOT)
if member.is_manager == True:
user_data = MAIN_BOT.get_data_from_id(discord_id)
last_seen_username = user_data["user"]["username"]
print(last_seen_username)
last_seen_discriminator = user_data["user"]["discriminator"]
print(last_seen_discriminator)
# get pfp URL
if user_data["user"]["avatar"] is None:
last_seen_pfp = ""
else:
last_seen_pfp = f"https://cdn.discordapp.com/avatars/{discord_id}/{user_data['user']['avatar']}"
# find or add user
user = User.get_or_none(User.discord_id == discord_id)
if user is None:
# suspect code
user = User.create(
discord_id=discord_id,
last_seen_username=last_seen_username,
last_seen_discriminator=last_seen_discriminator,
last_seen_pfp=last_seen_pfp,
)
debug(f"NEW USER ADDED BY MANAGER ADDITION ({discord_id})")
print(vars(user))
if pre_payment == True:
# pre-payment logic
update_q = User.select(User.discord_id==discord_id).update(pre_payment=True, pre_payment_amount_payed_usd=amount_payed_usd)
update_q.execute()
debug(f"ADDING PRE-PAYMENT ({subtype}) FOR {discord_id}")
else:
# non pre-payment logic
Payment.create(
discord_id=discord_id,
subtype=subtype,
ms_initiated=current_milli_time(),
amount_payed_usd=amount_payed_usd,
)
debug(f"PAYMENT COMPLETED (NOT PRE-PAYMENT) ({subtype}) for user {discord_id}")
return jsonify(is_error=False)
else:
return jsonify(is_error=True, error_msg="You do not have the permission to use this endpoint")
except Exception as error:
MAIN_BOT.error_to_developer(error, "add_payment()")
return jsonify(is_error=True, error_msg="Could not add payment (User Discord ID may be invalid)")
else:
return jsonify(is_error=True, error_msg="Required data not passed (access token)")
The only two operations here are .create and .update, but the the .update is, first of all, not even run when the bad operation happens (as I do not pass pre_payment as true), but also the update is on a .select(). The only suspect code I see to make a difference is the User.create(…) clause.
Also for further reference, “access token” is a token that managers pass to the API via a web interface (which is checked for appropriate roles), checked by the Member class creation, however this is never referenced again past role check
By the way, it is not an issue about data creation, but one about possible data corruption either by my own error or peewee error, however I cannot conclude anything from this, but I would appreciate any support, thank you.
Issue Analytics
- State:
- Created a year ago
- Comments:10 (4 by maintainers)
Top GitHub Comments
@peepopoggers If you prefer the SQL style over the ORM style:
But if you prefer the ORM style use the regular
save
like Coleifer mentioned.You should probably use the more idiomatic
save()
instead ofupdate()
: