Django model foreign key removal - django

I have following model:
class Client(models.Model):
user = models.OneToOneField(DjangoUser, unique=True)
address = models.ForeignKey(Address,blank=True)
class Address(models.Model):
(...)
Then I do:
client=Client()
client.address=address #any Address instance
client.save()
And now: how can I remove foreign association key from client?
client.address=None
seem not to work.

To be able to null out a foreign key, it's not enough to set in blank. You must also specify that null=True is also set on the field. See The Difference Between Blank and Null.

Your current models setup does not allow null=True, thus you cannot set it to None.

address = models.ForeignKey(Address,blank=True, null=True)
the key is null=True as well as blank=True
also, make sure to syncdb etc

Related

How to make a model parameter unique by a other parameter in Django?

I want my id field to be unique per each customer field. Just like the option unique_for_date from Django (https://docs.djangoproject.com/en/1.11/ref/models/fields/#unique) but in this case, not date but customer.
class Sample(NGObject):
id = models.CharField(max_length=128, null=True, blank=False)
customer = models.ForeignKey(Customer, related_name="blood_samples", on_delete=models.SET(get_default_customer))
I believe this should be done, before the save() method?
When a User writes the wrong ID (that already exists) I would also like to present the information in the Admin Form just like it would for normal unique error.
class Meta:
unique_together = ('sample_id', 'customer',)
This has done the trick :)

Why the field description of my django model is not null?

I have created a model like this,
class fleets(models.Model):
fleet_id = models.IntegerField(primary_key=True)
fleet_name = models.CharField(max_length=20)
description = models.CharField(max_length=40, null=True)
And when I observe in the postgresql admin the table I see is like what I want,
fleet_id as pk and not null
fleet_name not null
description null
But, why when I want to add some fleet with the django-admin it says is not possible? I forget some parameter?
Thank you very much!!
When adding a field to your model and specifying null=True you are saying that field can be null. For fleet_idand fleet_name, these cannot be null since you have not specified null=True so they are Not Null.
For the django-admin, the docs specify to avoid null=True on CharField. What you want here is blank=True instead of null=True.
See the docs here.
models.CharField(blank=True) # No problem, blank is stored as ''
models.CharField(null=True) # NULL allowed, but will never be set as NULL

Setting default value of field in model to another model instance

Model
class SlackPermission(models.Model):
#fields
class GithubPermission(models.Model):
#fields
class Employee(models.Model):
#fields
slack_permission = models.OneToOneField(SlackPermission, on_delete=models.CASCADE, related_name='Slack',default=SlackPermission.objects.get(pk=1))
github_permission = models.OneToOneField(GithubPermission, on_delete=models.CASCADE, related_name='Github',default=GithubPermission.objects.get(pk=1))
Error:
ValueError: Cannot serialize: <GithubPermission: GithubPermission object (1)>
There are some values Django cannot serialize into migration files.
I am creating API just to create Employee. Where there is not option of giving slackpermissions and githubpermissions. How do I give default value in there?
The problem is that the default is calculated immediately, and for migrations, it can not really serialize that.
That bing said, it is not very useful to do this anyway. You can just pass the primary key as default value. This is specified in the documentation on the default=… parameter [Django-doc]:
For fields like ForeignKey that map to model instances, defaults should be the value of the field they reference (pk unless to_field is set) instead of model instances.
So we can write this as:
class Employee(models.Model):
full_name = models.CharField(max_length=100)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
slack_permission = models.OneToOneField(
SlackPermission,
on_delete=models.CASCADE,
related_name='Slack',
default=1
)
github_permission = models.OneToOneField(
GithubPermission,
on_delete=models.CASCADE,
related_name='Github',
default=1
)
Note that you should ensure that there exists an object with that primary key. Therefore it might not be ideal to do that.
The issue here is that you are attempting to set a field value to an object instance. So your default value should be just 1 if you are certain of the pk.
Also, I am not sure the advantage of creating two separate models for these permission values. Seems like they can just be fields in your employee model. Seems like these permissions share identical fields as well which will allow you to flatten them a bit.

Django: Does "primary_key=True" also mean "unique"?

Hello i am testing Django authentication and nesting user data. I created a simple MyProfil model for my users. I wanted to test making a custom id and set the primary_key=True as id = models.UUIDField.
models.py
class MyProfil(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
owner = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
aboutme = models.TextField(max_length=300, blank=True)
city = models.TextField(max_length=300, blank=True)
so far everything works in my favor but i have a question, that i could not answer myself even after reading the django doc.
Question
Does primary_key=True on my id Field also mean unique or do i have to declare it?
Yes. Since a primary key means a value that can uniquely identify an object. In the documentation on the primary_key parameter, we see:
Field.primary_key
If True, this field is the primary key for the model.
If you don’t specify primary_key=True for any field in your model,
Django will automatically add an AutoField to hold the primary key,
so you don’t need to set primary_key=True on any of your fields
unless you want to override the default primary-key behavior. For
more, see Automatic primary key fields.
primary_key=True implies null=False and unique=True. Only one primary key is allowed on an object.

Why can I save a django model instance without defining all non-null fields

When I define a non nullable field in django it allows me to save a model instance without specifying any value for this non-nullable field. This is not what I would expect. How can I force this to yield an error?
Postgres 9.1
django 2.1
windows
python 3.6
from django.db import models
class Wwtp(models.Model):
name = models.CharField(max_length=100, null=False,
blank=False, unique=True)
short_name = models.CharField(
max_length=10, null=False, blank=False, unique=True)
As expected, I am not allowed to save it with an explicit empty short_name.
mdl.Wwtp.objects.create(name='Wwtp4', short_name=None)
But I am allowed to save an instance of Wwtp without specifying short_name:
mdl.Wwtp.objects.create(name='Wwtp4')
and when I try:
mdl.Wwtp.objects.create()
it gives me
django.db.utils.IntegrityError: duplicate key value violates unique constraint "api_wwtp_short_name_key"
DETAIL: Key (short_name)=() already exists.
Apparently django filled the database with an empty value for short_name while it is not allowed to do so... How can I force the database to not allow this?
You can't with CharField. The empty value is an empty string '', not NULL. You already have blank=False set, so if you clean your model or model forms before saving them, you'll catch that. But it cannot be enforced at the database level.
Note that blank=False, null=False is the default, so you really don't have to specify that.
Also, if you really only want to support PostgreSQL, you could make a custom migration using RunSQL to create your column on the table, manually adding the SQL needed to add the constraint (e.g. using CHECK). See here for how to ensure Django also knows the column was created and doesn't try to add it in the next migration. There's an example here.
[Edit] In Django 2.2, you can add a CheckConstraint in the model's Meta class constraints attribute:
from django.db.models import CheckConstraint, Q
(...)
class Meta:
constraints = [
CheckConstraint(
check=~Q(name=''),
name='name_not_empty'),
CheckConstraint(
check=~Q(short_name=''),
name='short_name_not_empty']