Having NULL as a primary key value - python

I would like to have an entity as follows:
class EntitySharedLinkPermission(models.Model):
OFF = None
COMPANY_VIEW = "Company View"
COMPANY_EDIT = "Company Edit"
PUBLIC_VIEW = "Public View"
PUBLIC_EDIT = "Public Edit"
name = models.CharField(max_length=12, primary_key=True)
class Meta: db_table = 'entity_shared_link_permission'
However, I cannot have NULL as a primary key value here. What should I do here instead? One idea was to just remove the primary key on this table and have a unique key instead (no PK in the table) to get around this, but surely there must be a better solution.

Simply put, you can't have null as primary key column value. You should always supply non null value to the primary key. Also, don't go for unique, it just isn't the solution though it masquerades as being one. If you can't always supply non null value, introduce a new identity column to your table instead.

If you don't expect the list of items to change often, and the set is small, then it looks to me like you're trying to set up a "choices" field, for which Django already has nice support. Here's the example that the Django docs use, which you could easily adapt to your situation:
from django.db import models
class Student(models.Model):
FRESHMAN = 'FR'
SOPHOMORE = 'SO'
JUNIOR = 'JR'
SENIOR = 'SR'
YEAR_IN_SCHOOL_CHOICES = (
(FRESHMAN, 'Freshman'),
(SOPHOMORE, 'Sophomore'),
(JUNIOR, 'Junior'),
(SENIOR, 'Senior'),
)
year_in_school = models.CharField(
max_length=2,
choices=YEAR_IN_SCHOOL_CHOICES,
default=FRESHMAN,
)
def is_upperclass(self):
return self.year_in_school in (self.JUNIOR, self.SENIOR)
However, if you expect the list of permissions to be fluid and change often, you should consider making the permissions a Model of their own, and simply use a ForeignKey (or ManyToMany) relationship,

Related

how to define a foreign key with pony entities

I would like to define a foreign key with pony entities.
If I understand it right, there is no need to define a primary key as long as it is named id. so the primary key of Jobs is id, and I want to define a foreign key job_id on Recipe which is related to id of Jobs. I tried Required(Jobs.id) but this gives a type error. do you have any hint on how to do it? thank you
class Jobs(db.Entity):
path = Required(str)
date = Required(str)
class Recipe(db.Entity):
job_id = Required(int) # must be foreign
path = OptionalField(str)
date = OptionalField(str)
I found the answer. the tricky thing is that the relationship had to be defined in both classes
class Jobs(db.Entity):
path = Required(str)
date = Required(str)
jobs = Set("Recipe")
class Recipe(db.Entity):
job_id = Required(Jobs) # must be foreign
path = OptionalField(str)
date = OptionalField(str)

How to use a field on a foreign key (another model) as part of my model primary key value

I'm new to Django and I feel sometimes it is not clear in which .py of myApp I should write solutions and examples I see.
In my models.py I have a model called Project and a model called Order. In admin section (http://127.0.0.1:8000/admin/myApp/), I would like the user to type a project number when creating a new project. Every project can have multiple Orders. I would like the Order primary key to be composed of the Project number it belongs to, plus a consecutive number. The user can only change the consecutive number part of the Oder primary key but not alter the Project number the order belongs to.
For instance for Project with project_number(primary key) = 951, Orders primary keys can be 951-1, 951-2, etc
Another project with project_number(primary key) = 1015 can also have orders 1,2, etc but they won't conflict with orders of project 951 because they will be labelled 1015-1, 1015-2, etc.
Is it possible to achieve this in models.py?
How would I have to modify order_number field below?
Notice I need the order_number field to fetch its project_number from order_project field and I won't know the order_project exact value until the user is creating the order and associating it with a project.
If what I'm asking can't be done please suggest a way to solve this and clearly explain in which .py of myApp I should write the code.
class Project(models.Model):
project_number = models.IntegerField(unique=True,primary_key=True)
project_name = models.CharField(max_length=400)
class Order(models.Model):
order_project = models.ForeignKey("Project", on_delete=models.CASCADE,verbose_name = "Project to which this order is associated",related_name= "orders_for_project")
order_number = models.CharField(unique=True,primary_key=True,max_length = 10)
UPDATE:
Following suggestions from the community my code now looks like this:
class Project(models.Model):
project_number = models.IntegerField(unique=True,primary_key=True)
project_name = models.CharField(max_length=400)
class Order(models.Model):
order_project = models.ForeignKey("Project", on_delete=models.CASCADE,verbose_name = "Project to which this order is associated",related_name= "orders_for_project")
order_number = models.IntegerField(default=1,validators=[MinValueValidator(1)])
class Meta:
#TODO capture error and present it in human readable form
constraints = [ models.UniqueConstraint(fields= ['order_project','order_number'], name = 'unique_order_id'),]
def __str__(self):
return str(self.order_project.project_number) + ("-") + str(self.order_number) + (" : ") + str(self.order_description)
I do not fully understand why my Order primary key could not be formed considering the value of the primary key of Project but this is a workaround solution
You can keep Order's primary key independent from Product's PK, just set uniqueness constraint on order_project_id + order_number combination:
class Order(models.Model):
order_project = models.ForeignKey("Project", on_delete=models.CASCADE,verbose_name = "Project to which this order is associated",related_name= "orders_for_project")
order_number = models.IntegerField()
class Meta:
unique_together = ('order_project', 'order_number')
Then if you want to display order number in {order_project_id}-{order_number} format you can just generate this value using those 2 fields in runtime.

Reverse lookup 'QuerySet' object has no attribute

I have the following Models where I define a trucking company and their insurance company.
Models.py:
class Truckers(models.Model):
DOT_Number = models.IntegerField(primary_key=True)
Address = models.CharField( max_length=200)
class CaliIns_FK(models.Model):
DOTNmb = models.ForeignKey(Truckers, on_delete=models.CASCADE)
CoName = models.CharField(max_length=20)
There are many truckers and not as many insurance companies. I am trying to get a list of every Trucker that has insurance.
I tried the following as per django:
truck = Truckers.objects.all()
filtered = truck.caliinsfk_set.filter(truckers__isnull=True)
and
filtered = truck.caliins_fk_set.filter(truckers__isnull=True)
getting error:
AttributeError: 'QuerySet' object has no attribute 'caliinsfk_set'
Given you want Truckers objects with no related CaliIns_FK, you can .filter() your Trucks:
Truckers.objects.filter(caliins_fk__isnull=True)
or given the ForeignKey has a related_name, it should be:
Truckers.objects.filter(myrelatedname__isnull=True)
(with myrelatedname the value in related_name for the ForeignKey)
Here we thus obtain a QuerySet for which there is no related CaliIns_FK object.
This results in a query with a LEFT OUTER JOIN so if the "set" of related CaliIns_FKs is empty, it will have a row with NULL:
SELECT truckers.*
FROM truckers
LEFT OUTER JOIN caliins_fk ON truckers.DOT_Number = caliins_fk.DOTNmb_id
WHERE caliins_fk.id IS NULL
Note that one typically does not uses plural names for models, or the name of a primary key in a foreign key. According to PEP-8, attributes also are written in lowercase and with underscores. A more Django-ish approach would be:
class Trucker(models.Model):
dot_number = models.IntegerField(primary_key=True)
address = models.CharField( max_length=200)
CaliInsurance(models.Model):
trucker = models.ForeignKey(Trucker, on_delete=models.CASCADE)
coname = models.CharField(max_length=20)
In that case the query thus looks like:
Trucker.objects.filter(caliinsurance__isnull=True)

Declare "MUL key" field in python. (django framework)

I have a column which should be MUL key, but I couldn't find out how I can do that. Here's the code:
class table(models.Model):
field2 = Models.int(max_length=9, null= False, default = 0)
Non-unique indexes are defined in the metadata options for the model.
class Table(models.Model):
...
class Meta:
indexes = [
models.Index(fields=['field2'])
]
MUL keys are simply non-unique indexes (other index types are PRI for Primary Key and UNI for Unique, which are both unique indexes. You can add a non-unique index to any field using the db_index argument:
field2 = models.IntegerField(null=False, default=0, db_index=True)
PS: I assume that the code in the question has a typo and you actually meant IntegerField and not int. Also, max_length has no effect when used with IntegerFields.

Composite primary key in django

I have a legacy db table which has composite primary key. I don't think I will be able to change the structure to include a surrogate key, as there is some code written that uses that table. And in django, I cannot use that table, as it doesn't have a primary key(non-composite).
Do django models support composite primary keys? If not, is there any workaround without changing the structure of the table?
P.S. I am using postgresql.
Try similar below code:
class MyTable(models.Model):
class Meta:
unique_together = (('key1', 'key2'),)
key1 = models.IntegerField(primary_key=True)
key2 = models.IntegerField()
or if you want only unique mixed fields:
class MyTable(models.Model):
class Meta:
unique_together = (('key1', 'key2'),)
key1 = models.IntegerField()
key2 = models.IntegerField()
EDIT: I would like to note that there is a problem with this approach if there are 3 columns. Update queries don't work because it tries to update (puts pk fields right after "SET") the fields that are unique together and obviously fails.
The accepted answer is fine. However, it's a little old. unique_together may be deprecated in favor of UniqueConstraint. So, the better way of doing this would be;
UniqueConstraint(fields = ['key1', 'key2'], name = 'constraint_name')
I solved this with virtual field inherited from django AutoField, that combines a values from several fields into single JSON dict.
That makes such models, compatible with django admin and genetic views.
$ pip install django-viewflow --pre
from viewflow.fields import CompositeKey
class Seat(models.Model):
id = CompositeKey(columns=['aircraft_code', 'seat_no'])
aircraft_code = models.ForeignKey(
Aircraft, models.DO_NOTHING,
db_column='aircraft_code'
)
seat_no = models.CharField(max_length=4)
This makes possible to access as to legacy databases, as to PostgreSQL TimeScaleDB tables
Another option is to set managed=False in the model's Meta, then manually create the table.
class MyTable(models.Model):
foo = models.IntegerField(primary_key=True)
bar = models.IntegerField()
baz = models.IntegerField()
class Meta:
managed = False
db_table = 'myapp_mytable'
def __repr__(self):
return f'<MyTable: MyTable object ({self.foo}, {self.bar}, {self.baz)>'
In a postgres shell:
CREATE TABLE myapp_mytable (
foo INTEGER NOT NULL,
bar INTEGER NOT NULL,
baz INTEGER NOT NULL,
PRIMARY KEY(foo, bar, baz)
);
It appears to behave correctly:
>>> MyTable.objects.create(foo=1, bar=1, baz=1)
<MyTable: MyTable object (1, 1, 1)>
>>> MyTable.objects.create(foo=1, bar=1, baz=2)
<MyTable: MyTable object (1, 1, 2)>
>>> MyTable.objects.create(foo=1, bar=1, baz=2)
django.db.utils.IntegrityError: duplicate key value violates unique constraint "myapp_mytable_pkey"
DETAIL: Key (foo, bar, baz)=(1, 1, 2) already exists.
Note that this is only tested in Django 3.x, so I'm not sure if it works in older versions.

Categories