I have a django model that has a unique together constraint, but I need a specific instance to be able to be repeated over and over. Is this possible?
name = models.ForeignKey(name)
time = models.BigIntegerField()
class Meta:
unique_together = ("name", "time",)
I'm trying to get time=0 and for the same user multiple times. However, in every other instance it time needs to be unique.
A unique_together field is validated on database level (see documentation). It is therefore not possible to make exceptions.
A solution could be to set time = null instead of time = 0.
Your database backend needs to support unique constraint that allows empty values (see this post). This is supported by most major DBMS, but not all.
If you database does not support it you'll have to write a custom form validation.
Related
I know the foreign key concept,Djongo Array field , however is there an alternative?
The issue with the foreign key concept is that I would need to make multiple hits to the database and the issue with Array field is the lack of information and the errors emerging without a known solution.
What I would like to do basically is in fact add multiple instances of a model say comments to a single field in another model but I would like to embed it rather than creating a new table for comments which I tried using an abstract model however it did not work out.
I would like to know any alternative solution.
You can use foreign keys, and to avoid making separate query for every related record you can extract them all at once using prefetch_related - https://docs.djangoproject.com/en/3.1/ref/models/querysets/#prefetch-related :
Returns a QuerySet that will automatically retrieve, in a single batch, related objects for each of the specified lookups.
Code example:
# models.py
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
class Comment(models.Model):
post = models.ForeignKey(Post, models.CASCADE)
text = models.TextField()
# Somewhere else, fetch posts together with related comments:
# It will take 2 requests in total
# - one to fetch posts, another to fetch all related comments
for post in Post.objects.all().prefetch_related('comment_set'):
print([c.text for c in post.comment_set.all()])
tl;dr: Why does Django's uniqueness check on INSERT require a SELECT query, and can I permanently disable it?
I'm working to highly optimize a Django app that is writing to a PSQL database. I have a uuid column which is a primary_key as part of my model. It is the only unique field in the model.
id = models.UUIDField(
primary_key = True,
default = uuid.uuid4,
editable = False,
null = False,
blank = False,
help_text = 'The unique identifier of the Node.'
)
The issue I'm encountering is that when attempting to save a new item, Django automatically performs a uniqueness check query prior to the insert:
SELECT (1) AS "a" FROM "customer" WHERE "customer"."id" = \'1271a1c8-5f6d-4961-b2e9-5e93e450fd4e\'::uuid LIMIT 1
This results in an extra round trip to the database. I know that the field must be unique, but of course Django has already configured this at the database level - so if it tries to insert a row with a non-unique field it will get an error.
I've implemented a workaround which suppresses the query by adding the following to my model:
def validate_unique(self, *args, **kwargs):
# Make sure that we never validate if ID is unique. Duplicates OK.
current_exclude = set(kwargs.get('exclude', []))
current_exclude.add('id')
kwargs['exclude'] = list(current_exclude)
super().validate_unique(*args, **kwargs)
This will ensure that uniqueness on the id field is never checked.
This works, I don't get the extra query. I also verified that if I do try to re-insert a duplicate UUID, I indeed get an error with the database as the source.
My question is this: Why does Django do this? I'm tempted to prevent Django from checking uniqueness ever, unless the extra round trip to the DB accomplishes some valuable purpose.
Env:
django==2.2.12
psycopg2-binary==2.8.5
In Django, model validation is a distinct step from model saving. It appears that whatever you're doing is triggering validation.
There are a number of good reasons for those to be separate steps. One is that you can express many more constraints in arbitrary Python code than you can with database constraints. Another is that it allows you to generate much more descriptive error messages than you would get by trying to parse non-standardized database errors. Another is that sometimes you simply want to know whether something's valid but don't want to actually save it.
By default, Django does not validate models before saving them. Some Django components, though, like the admin (more generally, ModelForms) do trigger validation.
So, you need to figure out why validation is being triggered in your case, and if that's not what you want, prevent it.
I don't understand well, how does django's autofield work... If I will run two app instances using gunicorn, will it be possible that my models get same autofield id?
I have a model Message and I want to check it's instance's id, but I want to be absolutly sure, that the ids are unique and are going by adding order.
The ids are unique for the specific model regardless of if it's within the same app or difference app. The id fields are sequential and increments by 1. Even if you delete an object, Django will not replace that ID.
There is no need to add the ID field when creating the model as Django takes care of that by itself.
If you want the id to be a unique set of character (for example- instead of the first object id being 1, you want it to be a unique number such as 12345678-1234-5678-1234-567812345678), you can use UUID (Universally Unique Identifier). In that case add the following field within your Message model-
Before running the below you would need to remove all migrations of the Message app and older records which still uses the id field.
class Message(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
I'm working on a table consisting of all events performed on a user despite that these events are represented by 4 different models.
The models are:
WebhookSubscription
WebhookEvent
TokenRefresh
LogEvent
I want these to all be visible to the user in their dashboard, but in a single table ordered by timestamp. I could do a single query for each model then append to a dictionary which I'll then sort by date, however, I don't want to go against a native solution if there is one (and I don't believe this is an edge case so I could foresee it).
Is there a native way of retrieving multiple models in a single QuerySet?
There is no native way to retrieve multiple un-related models in a single QuerySet. What you can do is to use model inheritance, have a base model for all event models. With the following model structure;
class Event(models.Model):
timestamp = models.DateTimeField()
user = models.ForeignKey(User)
...
class WebhookSubscription(Event):
...
class WebhookEvent(Event):
...
class TokenRefresh(Event):
...
class LogEvent(Event):
...
You can query directly using the Event model like;
events = Event.objects.filter(user=user).order_by('timestamp')
This would give you Event instances, which won't hold data for child models. You can get the child instance from a parent just like following a OneToOneField (thats how django hadnles model inheritance actually, creating two tables and linking them with a foreign key):
event.webhooksubscription
event.webhookevent
event.tokenrefresh
event.logevent
These would return child model instances if exists, and raise an ObjectNotFound exception if the parent does not have a related specified child model instance.
This approach would let you do operations like sorting and slicing at the database level, with the downside of added model complexity (You'll need a separate query to get child model data)
in Django 1.10 -
I want to create multiple objects by importing - I'm uploading a file with data and creating objects with the given data. Before creating them I want to validate fields to make sure as much as I can that creation will pass successfully and collect as much data as I can about invalidate fields. For example, to find out whether a char field is too long.
I can use 'if' statement for each field but it's not robust.
I thought of using the model Serializer. The problem is that there are models to create that uses other models that also should be created. So when trying to validate the model that depends on the other one - it fails since it's not existed yet.
For example:
class FirstModel(BaseModel):
title = models.CharField(max_length=200)
identifier = models.CharField(max_length=15)
class SecondModel(BaseModel):
identifier = models.CharField(max_length=15)
firstModel = models.ForeignKey(FirstModel, related_name='first_model')
I think that my question is actually -
How can I validate only part of a model fields before creating it on DB?