I would like to have a field in my model that auto creates a unique primary key for each record.
I've been using:
models.AutoField(primary_key=True)
But this generates simple integer incremented ID's.
What I'd really like is some sort of random 16 digit alphanumeric primary key that is generated automatically and guaranteed to be unique.
What is the best way to implement this?
egreene's answer is sufficient, but if you'd like to have more control over your models' UUIDs you can define an abstract base class that automatically assigns a unique UUID using Python's built-in function.
import uuid
from django.db import models
def make_uuid():
"""Return UUID4 string."""
return str(uuid4())
class UUIDModel(models.Model):
uuid = models.CharField(
editable=False, max_length=36, db_index=True,
unique=True, default=make_uuid
)
class Meta:
abstract = True
class RealModel(UUIDModel):
name = models.CharField(max_length=36)
def do_something(self):
pass
The UUIDModel abstract base class could also easily be used as an ingredient in other mix-in abstract classes, letting you mix and match different attributes when making new models.
You want to create a UUID field. The extension here django-uuidfield, https://github.com/dcramer/django-uuidfield should work.
After installing with pip install django-uuidfield, you can add the field like so:
from uuidfield import UUIDField
class MyModel(models.Model):
uuid = UUIDField(auto=True)
Disclaimer: the code is from the github README.
Related
I think it's a dumb question, but I can't solve this problem anyway. I'm building a simple card game with chatrooms in Django. When a mod creates a room, to enter this room you need to use the following URL:
cardgame/room/<int:pk>
where inside of <int: pk> is replaced by the id of the room created. My problem is that some random user could enter the room of id=x just using a link like cardgame/room/x without being invited. I wanted to encrypt the id number whenever a room is created, just like when you create a Google meet call but I dont know how to this using Django/Python.
How can I do this?
Possible duplicate of
Using a UUID as a primary key...
import uuid
from django.db import models
class MyUUIDModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
This changes the default behaviour of django models, which are creating id as an AutoField. Either you can do this or add an additional uuid field
What about adding a UUID field to your model to create a universally unique identifiers and then using that as the path variable instead?
Something like this:
class Room(models.Model):
unique_id = models.UUIDField(default=uuid.uuid4, unique=True)
I need extend a model from another model.
Case:
core/models.py
class Master(models.Model):
code = models.CharField(max_length=30, unique=True)
name = models.CharField(max_length=100, blank=False, null=False)
class Meta:
abstract = True
class City(Master):
zipcode = models.IntegerField()
custom/models.py
from core.models import City
class City(City)
newfield = models.CharField(max_length=20)
custom is an app.
I have tried with proxy model but it is not what I need, since proxy model adds a new table. https://docs.djangoproject.com/en/2.2/topics/db/models/#proxy-models
I need is that when I migrate add the new field to City.
More info.
In core the table is created and in custom you can add new fields that the client needs. The idea is that core is only maintained as standard.
Proxy models don't add new tables. From the docs link you mentioned:
The MyPerson class operates on the same database table as its parent Person class.
If you want one table called core_city, and another called custom_city, the second one having an extra field, you simply subclass it. Perhaps it would be easier to use an alias:
from core.models import City as CoreCity
class City(CoreCity):
newfield = models.CharField(max_length=20)
custom_city will have all fields from core_city, plus a newfield. The description of how this works (and an example) is covered in the docs section Multi-table inheritance.
If what you want is to have one single database table, then you should use a proxy Model, however they really don't allow you to create new fields. The field should be created in the parent model, or otherwise exist in the database and not be handled by Django migrations at all.
You are looking for Abstract base classes models:
Abstract base classes are useful when you want to put some common information into a number of other models. You write your base class and put abstract=True in the Meta class.
This is the base class:
#core/models.py
class City(Master):
zipcode = models.IntegerField()
class Meta:
abstract = True # <--- here the trick
Here your model:
#custom/models.py
from core.models import City as CoreCity
class City(CoreCity):
newfield = models.CharField(max_length=20)
For many uses, this type of model inheritance will be exactly what you want. It provides a way to factor out common information at the Python level, while still only creating one database table per child model at the database level.
You can update or create your class constants after its defined like this
from core.models import City
City.newfield = models.CharField(max_length=20)
You may need to use swappable models, using them you can define a City class and change it with whichever model you need later,
but that way you can't import and use the base City model directly, you may need to provide a method like get_city_model for that, as your public API.
class City(Master):
zipcode = models.IntegerField()
class Meta:
swappable = 'CORE_CITY_MODEL'
and maybe replace it later with some other model, then just set CORE_CITY_MODEL to that model in the form of 'app_name.model_name'.
The django.contrib.auth is a good example of this, you may consider checking User model and get_user_model method. Although I think you may face problems if you change your city model after you did run migrate, it may not move your data to the new table, but I'm not sure about this.
What's the proper way to log user activity in Django?
For example let's say a user has Groups, and I'd like to keep a record of when Object1 has been added or removed.
The method that comes to mind is to create a new record every time and pull the latest record but this feels wrong (and causes some filtering problems, eg: you can't just filter on is_member=True since you'll get stale results). Is there a proper way to log these in Django?
You can use django-auditable-models for that. It will hook in the django workflow, and will avoid that you have to write all logic yourself.
You can use loggers in Django.
https://docs.djangoproject.com/en/1.8/topics/logging/#topic-logging-parts-loggers
To log something like that I recommend you to create an core app with a TimeStampModel model:
from django.db import models
from django.utils.timezone import now
class TimeStampModel(models.Model):
"""
TimeStampModel class allows us to follow creation and update of each inherit instance
"""
created_at = models.DateTimeField(auto_now_add=now(), editable=False)
updated_at = models.DateTimeField(auto_now=now(), editable=False)
class Meta:
abstract = True
Now, inherit each models from TimeStampModel that you want to record creation or update date.
E.g:
from django.db import models
from core.models import TimeStampModel
class Token(TimeStampModel):
uuid = models.CharField(max_length=255, primary_key=True)
# ...
You can also add a delete attribute (Boolean) to realize logical delete. And the last update, will be the date of deletion.
Two Scoops of Django 1.8 recommends also this practice.
In Django 1.7, I couldn't quickly find a simple one-liner to get a related model class from the parent model.
Often these two models are in different files and one already imports the other leading to circular (i.e. broken) imports.
Here's a simple example:
# File: classroom_model.py
from django.db import models
class Classroom(models.Model):
class_code = models.IntegerField()
# File: student_model.py
from classroom_model import Classroom
class Student(models.Model):
classroom = models.ForeignKey(Classroom, related_name="student_set")
```
Here, a desire could be to gain access to the Student model class in Classroom, for example, to write a #classmethod that creates students (e.g. classroom.create_student(name).
Two ways:
1) Simplest way is to change the reference in the ForeignKey definition from a direct model reference to a string, e.g.:
classroom = models.ForeignKey("Classroom")
then remove the import line:
from classroom_model import Classroom
2) The other way is to define in classroom_model.py that:
Student = Classroom.student_set.related.model```
This would be used inside a method where it is used.
I have the following model:
from django.db import models
class PopulationData(models.Model):
slot = models.IntegerField(db_index=True)
sample = models.IntegerField()
value = models.FloatField()
class Meta:
unique_together = (('slot', 'sample'),)
And I would like to create also a compound index on the column pair that have the UNIQUE constraint, like so:
CREATE INDEX my_compound_index ON myapp_populationdata (slot, sample);
Right now I have a separate code connected to the post_syncdb signal that issues the previous SQL statement. Is there any way to indicate it from the model specification? (Note: I'm using the 1.3 branch).
Starting from django-1.5 you can make compound index using index_together meta option:
https://docs.djangoproject.com/en/dev/ref/models/options/#index-together
Note index_together is deprecated since django-4.2. Instead, use much more powerful indexes meta option. With it you can create not only compound indexes, but also other types of indexes, e.g. function-based indexes, partial (conditional) indexes, covering indexes:
https://docs.djangoproject.com/en/dev/ref/models/options/#django.db.models.Options.indexes
Starting from Django-1.11 use Meta.indexes option https://docs.djangoproject.com/en/1.11/ref/models/indexes/:
from django.db import models
class PopulationData(models.Model):
slot = models.IntegerField(db_index=True)
sample = models.IntegerField()
value = models.FloatField()
class Meta:
unique_together = (('slot', 'sample'),)
indexes = [
models.Index(fields=['slot', 'sample']),
]
Since a unique constraint also creates an index, it would be counterproductive to create both.
for example, from the postgres docs:
There's no need to manually create indexes on unique columns; doing so would just duplicate the automatically-created index.
Credit to Mark Byers for the doc link
If for some reason you still want to create a multi-column index, you can do so via index_together:
class PopulationData(models.Model):
...
class Meta:
index_together = [['slot', 'sample']]
I think that's not currently implemented in the django ORM.
If you use a migration tool (like south) that might be a good place to add that sql statement or if you preffer to avoid raw sql you could use sqlalchemy (core) but this case sounds simple enough to just go with sql.
Note: index_together may be deprecated in the future:
https://docs.djangoproject.com/en/dev/ref/models/options/#index-together
Use indexes in the Meta class instead:
from django.db import models
class Customer(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
class Meta:
indexes = [
models.Index(fields=['last_name', 'first_name']),
models.Index(fields=['first_name'], name='first_name_idx'),
]