I'm trying to use postgresql ArrayField in my django project setting it a default, but I can't get rid of the warning ArrayField default should be a callable instead of an instance so that it's not shared between all field instances. HINT: Use a callable instead, e.g. use list instead of []
This is my code:
def get_default_subscriptions():
return 'Noticias, Promociones, Pagos, Compras'.split(', ') # this returns a list
class myModel(models.model):
# other fields
subscriptions = ArrayField(models.CharField(max_length=200), default=get_default_subscriptions()) # this is a callable, so, why the warning?
Docs say about this: If you give the field a default, ensure it’s a callable such as list (for an empty default) or a callable that returns a list (such as a function). Incorrectly using default=[] creates a mutable default that is shared between all instances of ArrayField.
Can you give me an idea of what am I doing wrong?
Use default=get_default_subscriptions (without paranthesis) instead of default=get_default_subscriptions()
To add a bit of clarification to Arakkal's answer, a callable is a function or bound method. What you passed was the return of a function call and not the function itself.
You actually called get_default_subscriptions inline instead of giving Django the function itself so it can call it when it needs to.
Related
so I've got this model:
class Action(models.Model):
d_changes = ArrayField(models.FloatField(), default=list(), verbose_name='D Changes')
w_changes = ArrayField(models.FloatField(), default=list(), verbose_name='A Changes')
And when I want to create a migration or a fixture I always receive the following warning for both fields:
backend.Action.d_changes: (postgres.E003) ArrayField default should be a callable instead of an instance so that it's not shared between all field instances.
HINT: Use a callable instead, e.g., use `list` instead of `[]`.
For my migrations its not such a big deal, since everything still works fine. But when I try to create a fixture of my db, my .json File always ends up with this bit in the very top of my .json file:
System check identified some issues:
WARNINGS:
[33;1mbackend.Action.d_changes: (postgres.E003) ArrayField default should be a callable instead of an instance so that it's not shared between all field instances.
HINT: Use a callable instead, e.g., use `list` instead of `[]`.[0m
[33;1mbackend.Action.w_changes: (postgres.E003) ArrayField default should be a callable instead of an instance so that it's not shared between all field instances.
HINT: Use a callable instead, e.g., use `list` instead of `[]`.[0m
Which breaks my .json file and thus I cannot use loaddata, as I always receive a DeserializationError(), so I have to manually remove that part.
So what exactly is wrong with the model fields? I mean I'm literally using default=list() which is a callable?
Thanks for the help :)
You have to do this:
class Action(models.Model):
d_changes = ArrayField(models.FloatField(), default=list, verbose_name='D Changes')
w_changes = ArrayField(models.FloatField(), default=list, verbose_name='A Changes')
list() is not callable list is callable. because list() has been already called.
In a django project i have created a model class having a foreign key.
model class
When i tried to get objects in a variable by classname.objects.get(parameters=value).
assigning objects into a variable
Now when to display the object's attributes html by django template.
iterating through objects
now when i run the program i am getting error of 'Bid' object is not iterable.
how to correct this code to working?
thankyou
filter() will always give you a QuerySet, even if only a single object matches the query.
If you know there is only one object that matches your query, you can use the get() method on a Manager which returns the object directly.
That means you .get() will only return a single element which is not iterable.
So, you could use .filter instead of .get() in your view (listingpage) and fix it.
bids = Bid.objects.filter(title = title_id)
I am trying to dynamically add an attribute to at runtime using the following snippets of code:
View
...
for appellation in queryset:
if appellation.id in used_id_set:
appellation.is_used_flag()
print(appellation.is_used)
# prints true as expected
else:
appellation.is_not_used_flag()
first = queryset.first()
print(first.is_used)
# prints AttributeError: 'Appellation' object has no attribute 'is_used'
In Model
...
def is_used_flag(self):
self.is_used = True
def is_not_used_flag(self):
self.is_used = False
Why does it work correctly when in the loop but when I try to retrieve the attribute from an instance after it does not work? I have run into the same issue using setattr, appellation.is_used = True and modifying __dict__. Also is there a better way to do this?
I have referenced these posts:
Why can't you add attributes to object in python? I do have a dict but it does not seem to "persist" after the loop
How to assign a new class attribute via __dict__? Same issue as mentioned above
Dynamically defining instance fields in Python classes Same as above
Update
Since both answers mention similar things, I should clarify what my intentions are. I do not want to actually persist the value in the DB. I just want to serialize it and use it in the front end.
The Queryset API in django (often) returns other querysets, which are in turn evaluated by accessing the database. By doing queryset.first() you're executing another database call, where your attributes have not been yet set.
If you need to save this is_used flag between querysets (persist the change), I suggest you add a BooleanField on your model, or perhaps find another way to do what you want, as in memory attributes will not get returned by using the queryset API.
If you want the change to persist you will need to call self.save() after setting is_used, assuming that is_used is a field on the Appellation model.
models.py
from django.db import models
class Appellation(models.Model):
# ... rest of code ...
is_used = models.BooleanField(default=False)
def is_used_flag(self):
self.is_used = True
self.save()
def is_not_used_flag(self):
self.is_used = False
self.save()
Note that Django instances are still Python objects so adding an attribute dynamically will work in the same way, this is why it prints True as expected in the code you provided.
According to the Django REST Framework docs, passing default=CreateOnlyDefault(<arg>) to a serializer field
can be used to only set a default argument during create operations. During updates the field is omitted.
It takes a single argument, which is the default value or callable that should be used during create operations.
How is this different from declaring read_only=True, default=<arg>, where <arg> is that single argument you would pass to CreateOnlyDefault?
When CreateOnlyDefault is used, the value will only be used on creation not on updates.
For example:
class MySerializer:
created = serializers.DateTimeField(
read_only=True,
default=serializers.CreateOnlyDefault(timezone.now)
)
modified = serializers.DateTimeField(
read_only=True,
default=timezone.now
)
With that serializer, modified field will be updated every on every update whereas created field will stay the same from creation.
It's mean it can be provided by the API client or not, so when it's checked by the validator if nothing is provided its create a 'Default' value.
In Django's document
Django Document
It has following code.
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):
fields = ('name', 'title', 'view_birth_date')
def view_birth_date(self, obj ):
return obj.birth_date
view_birth_date.empty_value_display = '???'
I don't understand in the custom method view_birth_date(self, obj ) where this obj parameter came from?
Note in the last line, it called this function,
view_birth_date.empty_value_display = '???'
but did not pass any parameter for obj. I don't understand where how obj got a value.
Thanks!
I don't understand in the custom method view_birth_date(self, obj) where this obj parameter came from?
This method is called by Django's machinery and obj is passed also by it. It's just a predefined interface.
view_birth_date.empty_value_display = '???'
but did not pass any parameter for obj. I don't understand where how obj got a value.
This line has nothing to do with your question. Again, according to the interface, Django when looking at your method (function) looks for empty_value_display attribute to find out what value the developer expects to see when the current value is empty.
Yes, looks weird but it's just how Django works, how its creators made it work. They chose this interface -- you just have to use the docs to find out the interface.