Describe the bug
While writing a discord bot for a project of a friend of mine i noticed that the get_or_create function does not seem to work as expected.
I can also fully confirm that every value has something in it.
I did a print before the model creation call which confirms that every parameter should receive a proper value.
The following error occurs: (The last one is obviously a discord error)
Traceback (most recent call last):
File "/home/dominik/.cache/pypoetry/virtualenvs/pirate-era-bot-doMltmxG-py3.12/lib/python3.12/site-packages/tortoise/models.py", line 1075, in get_or_create
return await cls.filter(**kwargs).using_db(db).get(), False
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dominik/.cache/pypoetry/virtualenvs/pirate-era-bot-doMltmxG-py3.12/lib/python3.12/site-packages/tortoise/queryset.py", line 1073, in _execute
raise DoesNotExist("Object does not exist")
tortoise.exceptions.DoesNotExist: Object does not exist
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/dominik/.cache/pypoetry/virtualenvs/pirate-era-bot-doMltmxG-py3.12/lib/python3.12/site-packages/tortoise/fields/base.py", line 284, in validate
v(value)
File "/home/dominik/.cache/pypoetry/virtualenvs/pirate-era-bot-doMltmxG-py3.12/lib/python3.12/site-packages/tortoise/validators.py", line 44, in __call__
raise ValidationError("Value must not be None")
tortoise.exceptions.ValidationError: Value must not be None
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/dominik/.cache/pypoetry/virtualenvs/pirate-era-bot-doMltmxG-py3.12/lib/python3.12/site-packages/discord/app_commands/commands.py", line 827, in _do_call
return await self._callback(self.binding, interaction, **params) # type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dominik/Projects/pirate-era-bot/pirate_era_bot/plugins/rule_book/rule_book.py", line 39, in designate_rule_channel
rule_message_tuple = await RuleMessage(
^^^^^^^^^^^^^^^^^^
File "/home/dominik/.cache/pypoetry/virtualenvs/pirate-era-bot-doMltmxG-py3.12/lib/python3.12/site-packages/tortoise/models.py", line 1079, in get_or_create
return await cls.create(using_db=connection, **defaults, **kwargs), True
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dominik/.cache/pypoetry/virtualenvs/pirate-era-bot-doMltmxG-py3.12/lib/python3.12/site-packages/tortoise/models.py", line 1154, in create
await instance.save(using_db=db, force_create=True)
File "/home/dominik/.cache/pypoetry/virtualenvs/pirate-era-bot-doMltmxG-py3.12/lib/python3.12/site-packages/tortoise/models.py", line 962, in save
await executor.execute_insert(self)
File "/home/dominik/.cache/pypoetry/virtualenvs/pirate-era-bot-doMltmxG-py3.12/lib/python3.12/site-packages/tortoise/backends/base/executor.py", line 224, in execute_insert
self.column_map[field_name](getattr(instance, field_name), instance)
File "/home/dominik/.cache/pypoetry/virtualenvs/pirate-era-bot-doMltmxG-py3.12/lib/python3.12/site-packages/tortoise/fields/base.py", line 256, in to_db_value
self.validate(value)
File "/home/dominik/.cache/pypoetry/virtualenvs/pirate-era-bot-doMltmxG-py3.12/lib/python3.12/site-packages/tortoise/fields/base.py", line 286, in validate
raise ValidationError(f"{self.model_field_name}: {exc}")
tortoise.exceptions.ValidationError: title: Value must not be None
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/dominik/.cache/pypoetry/virtualenvs/pirate-era-bot-doMltmxG-py3.12/lib/python3.12/site-packages/discord/app_commands/tree.py", line 1248, in _call
await command._invoke_with_namespace(interaction, namespace)
File "/home/dominik/.cache/pypoetry/virtualenvs/pirate-era-bot-doMltmxG-py3.12/lib/python3.12/site-packages/discord/app_commands/commands.py", line 853, in _invoke_with_namespace
return await self._do_call(interaction, transformed_values)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dominik/.cache/pypoetry/virtualenvs/pirate-era-bot-doMltmxG-py3.12/lib/python3.12/site-packages/discord/app_commands/commands.py", line 846, in _do_call
raise CommandInvokeError(self, e) from e
discord.app_commands.errors.CommandInvokeError: Command 'create-or-edit-rule-message' raised an exception: ValidationError: title: Value must not be None
To Reproduce
Using this code it will crash with the mentioned error.
@app_commands.command(
name="create-or-edit-rule-message",
description="Create or edit rule explanation message",
)
@app_commands.describe(
channel="Channel to designate as rule channel",
title="Title of the rule message",
description="Description of the rule message",
colour="Colour of the embed. Must be in hexadecimal format. Example: #FF0000",
footer="Footer of the rule message",
)
async def designate_rule_channel(
self,
interaction: discord.Interaction,
channel: discord.TextChannel,
title: str,
description: str,
colour: Optional[str],
footer: Optional[str],
):
print(f"Title: {title}")
rule_message_tuple = await RuleMessage(
id=channel.id,
title=title,
description=description,
colour=colour,
footer=footer,
).get_or_create()
rule_message: RuleMessage = rule_message_tuple[0]
embed = discord.Embed(
title=rule_message.title,
description=rule_message.description,
colour=discord.Color.from_str(rule_message.colour),
).set_footer(text=rule_message.footer)
assert not isinstance(interaction.channel, discord.ForumChannel)
assert not isinstance(interaction.channel, discord.CategoryChannel)
assert not isinstance(interaction.channel, discord.GroupChannel)
if rule_message.message_id and isinstance(rule_message.message_id, int):
created_message = channel.get_partial_message(rule_message.message_id)
await created_message.edit(embed=embed)
await interaction.response.send_message(
f"Rule message {rule_message.title} edited with ID {rule_message.id}",
ephemeral=True,
)
else:
rule_message = await channel.send(embed=embed)
rule_message = await RuleMessage.filter(id=interaction.channel_id).update(
message_id=rule_message.id
)
await interaction.response.send_message(
f"Rule message {rule_message.title} created with ID {rule_message.id}",
ephemeral=True,
)
RuleMessage looks like this:
from tortoise import fields
from tortoise.models import Model
class RuleMessage(Model):
id = fields.BigIntField(primary_key=True)
title = fields.CharField(256) # Discord limitations
description = fields.CharField(4096) # Discord limitations
colour = fields.CharField(7, null=True) # Hexadecimal colour
footer = fields.CharField(2048, null=True) # Discord limitations
message_id = fields.BigIntField(null=True)
def __str__(self) -> str:
return f"title={self.title} description={self.description} colour={self.colour} footer={self.footer}"
Expected behavior
The model is either written to the database or retrieved from the database.
Additional context
Using .save() on it saves it to the database and works as expected.
But this is rather cumbersome.
Describe the bug While writing a discord bot for a project of a friend of mine i noticed that the
get_or_create
function does not seem to work as expected.I can also fully confirm that every value has something in it. I did a print before the model creation call which confirms that every parameter should receive a proper value.
The following error occurs: (The last one is obviously a discord error)
To Reproduce Using this code it will crash with the mentioned error.
RuleMessage looks like this:
Expected behavior The model is either written to the database or retrieved from the database.
Additional context Using
.save()
on it saves it to the database and works as expected. But this is rather cumbersome.