Django ImageField not deleted if default is set - python

Model:
class MyModel(models.Model):
watermark_image = models.ImageField(null=True, blank=True, default=settings.WATERMARK_DEFAULT)
When I try to empty the field in the admin clicking on its checkbox, file is not deleted unless i remove default attribute from model! Why?

The default attribute in a model field has exactly that purpose:
If an object has no watermark_image attribute use the default image.
Why is this important?
Imagine if you have a field that cannot be blank, because it would otherwise lead to a database inconsistency.
For example if you would have a User model that has a profile_picture field.
When looping through a list of users in a list like this:
[user.profile_picture for user in User.objects.all()]
When you have a default value set on the model level for the profile_picture attribute you do not have to worry about this code. If you would not have that default value this code could raise an AttributeError for users that have no profile_picture set.
Therefore it is impossible to delete an attribute that has a default value set in the admin, because it would eliminate the purpose of the default keyword argument in the model attribute.

Related

Reverse accessor clasher with Django [duplicate]

D:\zjm_code\basic_project>python manage.py syncdb
Error: One or more models did not validate:
topics.topic: Accessor for field 'content_type' clashes with related field 'Cont
entType.topic_set'. Add a related_name argument to the definition for 'content_t
ype'.
topics.topic: Accessor for field 'creator' clashes with related field 'User.crea
ted_topics'. Add a related_name argument to the definition for 'creator'.
topics.topic: Reverse query name for field 'creator' clashes with related field
'User.created_topics'. Add a related_name argument to the definition for 'creato
r'.
topicsMap.topic: Accessor for field 'content_type' clashes with related field 'C
ontentType.topic_set'. Add a related_name argument to the definition for 'conten
t_type'.
topicsMap.topic: Accessor for field 'creator' clashes with related field 'User.c
reated_topics'. Add a related_name argument to the definition for 'creator'.
topicsMap.topic: Reverse query name for field 'creator' clashes with related fie
ld 'User.created_topics'. Add a related_name argument to the definition for 'cre
ator'.
You have a number of foreign keys which django is unable to generate unique names for.
You can help out by adding "related_name" arguments to the foreignkey field definitions in your models.
Eg:
content_type = ForeignKey(Topic, related_name='topic_content_type')
See here for more.
http://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ForeignKey.related_name
Example:
class Article(models.Model):
author = models.ForeignKey('accounts.User')
editor = models.ForeignKey('accounts.User')
This will cause the error, because Django tries to automatically create a backwards relation for instances of accounts.User for each foreign key relation to user like user.article_set. This default method is ambiguous. Would user.article_set.all() refer to the user's articles related by the author field, or by the editor field?
Solution:
class Article(models.Model):
author = models.ForeignKey('accounts.User', related_name='author_article_set')
editor = models.ForeignKey('accounts.User', related_name='editor_article_set')
Now, for an instance of user user, there are two different manager methods:
user.author_article_set — user.author_article_set.all() will return a Queryset of all Article objects that have author == user
user.editor_article_set — user.editor_article_set.all() will return a Queryset of all Article objects that have editor == user
Note:
This is an old example — on_delete is now another required argument to models.ForeignKey. Details at What does on_delete do on Django models?
"If a model has a ForeignKey, instances of the foreign-key model will have access to a Manager that returns all instances of the first model. By default, this Manager is named FOO_set, where FOO is the source model name, lowercased."
But if you have more than one foreign key in a model, django is unable to generate unique names for foreign-key manager.
You can help out by adding "related_name" arguments to the foreignkey field definitions in your models.
See here:
https://docs.djangoproject.com/en/dev/topics/db/queries/#following-relationships-backward
If your models are inheriting from the same parent model, you should set a unique related_name in the parent's ForeignKey. For example:
author = models.ForeignKey('accounts.User', related_name='%(app_label)s_%(class)s_related')
It's better explained in th
If your models are inheriting from the same parent model, you should set a unique related_name in the parent's ForeignKey. For example:
author = models.ForeignKey('accounts.User', related_name='%(app_label)s_%(class)s_related')
It's better explained in the docs
I had a similar problem when I was trying to code a solution for a table that would pull names of football teams from the same table.
My table looked like this:
hometeamID = models.ForeignKey(Team, null=False, on_delete=models.CASCADE)
awayteamID = models.ForeignKey(Team, null=False, on_delete=models.CASCADE)
making the below changes solved my issue:
hometeamID = models.ForeignKey(Team, null=False, on_delete=models.CASCADE,related_name='home_team')
awayteamID = models.ForeignKey(Team, null=False, on_delete=models.CASCADE,related_name='away_team')
But in my case i am create a separate app for some functionality with same model name and field ( copy/paste ;) ) that's because of this type of error occurs i am just deleted the old model and code will work fine
May be help full for beginners like me :)
This isn't an ultimate answer for the question, however for someone it may solve the problem.
I got the same error in my project after checking out a really old commit (going to detached head state) and then getting the code base back up to date. Solution was to delete all *.pyc files in the project.
Do as the error message instructs you to:
Add a related_name argument to the
definition for 'creator'.

How to make a username as a foreign key of another model in django

I am very new to Django. I want to link a model which has 2 field 'username' and 'password'. I want to make 'username' field as as Foreign in another model. But as per Django we can only pass the whole Model Object, who is referring to as it's foreign key.
am I wrong somewhere? please give me any solution regarding this basic problem.
No you can link to any unique field of a Django model. So if your models look like:
class Target(models.Model):
name = models.CharField(max_length=128, unique=True)
class SourceModel(models.Model):
target = models.ForeignKey(Target, to_field='name', on_delete=models.CASCADE)
You can assign the value of the target column to the target_id then. So for example:
Target.objects.create(name='target1')
SourceModel.objects.create(target_id='target1')
So you do not need to pass a Target object itself. You can use the …_id "twin" field to use the target column value. The database will normally enforce referential integrity, and thus will prevent passing a non-existing value to the foreign key column.

Cannot delete some instances of model because of FK

Python 3.6 and Django 1.11.7.
I've got two Models look like the following:
class User():
name = models.CharField()
...
class UserInfo():
user = models.OneToOneField(User, on_delete=models.PROTECT, primary_key=True, related_name='info')
I wanted to delete some user instance A, and I explicitly deleted user A's info. But when I tried to delete the user model user.delete(), I got the ProtecedError:
ProtectedError: ("Cannot delete some instances of model 'User' because they are referenced through a protected foreign key: 'UserInfo.user'", <QuerySet [<UserInfo: UserInfo object>]>)
Then I tried to put the delete inside a try/catch looks like follows:
try:
user.delete()
except ProtectedError:
UserInfo.objects.filter(user=user).delete()
user.delete()
But still got the same exception. What might went wrong in my operation?
You are using a protect clause on the related objects:
on_delete=models.PROTECT
You can check it in the documentation on:
https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.ForeignKey.on_delete
You have it pointed here:
PROTECT[source]
Prevent deletion of the referenced object by raising ProtectedError, a subclass of django.db.IntegrityError.
Remove the on_delete=models.PROTECT on your user field. And run manage.py makemigrations
ForeignKey fields have a default value of CASCADE for the on_delete argument. This means that deleting the user object will cascade down and also delete the userinfo object linked to that user.
Looks like this is the behaviour you are looking for.
You can read more about this in the documentation documentation
Also note although on_delete has a default value fo CASCADE this argument will be required from Django 2.0.

Django: something wrong with ManyToManyField.limit_choices_to

I have a model with ManyToManyField. This field has limit_choices_to attribute which is set to callable. My problem is that this callable isn't called every time form is validated/instantiated in my view. It is called only once, after making changes in code. Django says:
If a callable is used for limit_choices_to, it will be invoked every
time a new form is instantiated. It may also be invoked when a model
is validated, for example by management commands or the admin. The
admin constructs querysets to validate its form inputs in various edge
cases multiple times, so there is a possibility your callable may be
invoked several times.
Any ideas why it doesnt working?
My code:
def limit_name_choices():
if Name.objects.count():
return {"pk__gt": Name.objects.last().pk}
else:
return {}
class Robject(models.Model):
project = models.ForeignKey(to=Project, null=True, blank=True)
names = models.ManyToManyField(
"Name",
related_name="robject_names",
limit_choices_to= limit_name_choices,
blank=True
)
[...]
SOLVED:
Bug was fixed in 1.11.3 release.

Django get_or_create does not return a usable Model object in clean method of ModelForm

Hello,
I have bound a ModelForm to one of my model that contains a ForeignKey to another model everything driven by a CreateView. What I want to achieve is to create the model object corresponding to the foreign key if it doesn't exist before the form is overall validated and the final object created in database.
Below the models I use:
class UmsAlerting(models.Model):
alert_id = models.IntegerField(primary_key=True, editable=False)
appli = models.ForeignKey('UmsApplication')
env = models.ForeignKey('UmsEnvironment')
contact = models.ForeignKey('UmsContacts')
custom_rule = models.ForeignKey('UmsCustomRules', null=True, blank=True)
class UmsApplication(models.Model):
appli_id = models.IntegerField(primary_key=True)
trigram_ums = models.CharField(max_length=4L)
class UmsContacts(models.Model):
contact_id = models.IntegerField(primary_key=True)
mail_addr = models.CharField(max_length=100L)
class UmsEnvironment(models.Model):
env_id = models.IntegerField(primary_key=True)
env_name = models.CharField(max_length=5L)
The model bound to the form is UmsAlerting. The model object I want to create if it doesn't exist is UmsContacts. I managed to use the field's clean method in my ModelForm of the contact field and use the get_or_create method like below:
def clean_contact(self):
data = self.cleaned_data['contact']
c, _ = UmsContacts.objects.get_or_create(mail_addr=data)
return c
It perfectly works when the contact is already in the database but when it needs to be created my form return a ValidationError on the contact field saying "This field cannot be null". If I submit the same form a second time without changing anything the UmsAlerting object is well created with no validation error.
My guess is that, for a reason I don't get, when get_or_create is used to create a UmsContacts object it cannot be used to create the new UmsAlerting object. So in clean_contact method the get is working and returns the UmsContacts object but the create part doesn't. It'd be like the UmsContacts object is saved when the whole form is validated but not before as I'd want it to.
Anyone could help me find out what is the problem ? Is using the clean method not the best idea ? Is there another strategy to use to take around this problem ?
Thanks in advance for your help.
It's probably because the object you are creating expects value for contact_id. If you use contact_id field for just setting object id -then you do not have to create it at all. Django takes care of Id's automatically.
Also. field clean method should return cleaned data not object. That creates whole lot more problems on its own.

Categories