Modify variable just in the Django admin but not in database - python

I want to modify a single value when I open an instance of a model in the Django admin.
Basically I want to display a value that is the opposite of the one stored in the database. So here is what I did in admin.py :
class MyModelAdminForm(forms.ModelForm):
import_file = forms.FileField(required=False)
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
super(MyModelAdminForm, self).__init__(*args, **kwargs)
print(self.instance.value)
self.instance.value = self.instance.get_reverted_value()
print(self.instance.value)
I works I can see it with the prints, but the admin still displays the original value that is stored in database.
Any idea ?
Thanks in advance

What about:
def __init__(self, *args, **kwargs):
super(MyModelAdminForm, self).__init__(*args, **kwargs)
self.fields['value'].value = self.instance.get_reverted_value()

Related

Get an attribute of the model from ModelForm without the instance (overriding __init__)

I have a MultipleChoiceField and for displaying the values that had been previous selected in the admin, I have to override method init from a ModelForm. I have the following class with its form:
class Profile(models.Model):
name = models.CharField(max_length=64)
contract = models.CharField(max_length=100)
class ProfileForm(forms.ModelForm):
CONTRACT_CHOICES = (
('scholar', _(u'Scholar')),
('freelance', _(u'Freelance')),
('contract', _(u'Contract')),
('volunteer', _(u'Volunteer'))
)
contract = forms.MultipleChoiceField(choices=CONTRACT_CHOICES)
def __init__(self, *args, **kwargs):
initial = kwargs.get('initial',{})
initial['contract'] = ['scholar', 'contract', 'freelance'] #Here I would have to be able to get the attribute contract from the Profile class, not this list
kwargs['initial'] = initial
super(ProfileForm, self).__init__(*args, **kwargs)
With the initial['contract']=['scholar','contract','freelance'] works (this values are shown as selected) but I have to achieve this with the attribute contract from Profile. I know that you can access to the model from a ModelForm with the attribute instance, but there's one problem: you can only have access to instance once the native method of init is called. And in this case, I have to call it later because otherwise it doesn't work for me. I already have tried to do it the following way:
def __init__(self, *args, **kwargs):
super(ProfileForm, self).__init__(*args, **kwargs)
self.fields['contract'].initial = self.instance.contract
But that doesn't work (it shows no errors but the selected attributes doesn't appear as selected). And furthermore, the following doesn't work either:
def __init__(self, *args, **kwargs):
super(ProfileForm, self).__init__(*args, **kwargs)
self.fields['contract'].initial = ['scholar', 'contract', 'freelance']
It has only worked as the first way, but with the problem that I don't know how to access to the attribute contract.
Any ideas? Thanks in advance

Get the django user in save while using django.form

I have a problem getting the user in django when I use django forms. My code looks something like this.
The view:
#login_required
def something(request):
item = ItemForm(request.POST)
item.save(user=request.user)
The form:
class ItemForm(ModelForm):
class Meta:
model = Item
fields = '__all__'
def save(self, *args, **kwargs):
user = kwargs['user']
super(ItemForm, self).save(user=user)
The model
class Item(models.Model):
field = models.CharField(max_length=100,)
field2 = models.CharField(max_length=100,)
def check_permissions(self, user):
return user.groups.filter(name='group').exists()
def save(self, *args, **kwargs):
if self.check_permissions(kwargs['user']):
super(Item, self).save()
My problem is that when I call the default save in ItemForm I get an error because the user param is unexpected. I need the user in the model to make the permission check but I dont know how to get it.
I finally solved the problem. The way I found was to save the form without the user but with the commit flag set to False and then calling the function save from the model with the user param.
The form save method now looks like this
def save(self, *args, **kwargs):
item = super(ItemForm, self).save(commit=False)
item.save(user=kwargs['user'])

Django ModelForm with dynamic model init kwargs

I have a model with an __init__ method:
class Foo(models.Model):
name = models.CharField(max_length=50)
def __init__(self, *args, **kwargs):
self.bar = kwargs.pop('bar', False)
super(Foo, self).__init__(*args, **kwargs)
if self.bar:
# do something
pass
Now, i need to create a specific ModelForm:
class FooForm(ModelForm):
class Meta:
model = Foo(bar='something')
fields = ('name',)
That does not work apparently:
TypeError: 'Foo' object is not callable
Is there any way i can overcome this?
Update
More information on what i want to achieve: I have an Image model with an ImageField. It has different storage methods depending on the form that uses it.
The model:
class Image(models.Model):
image = models.ImageField(upload_to=imageUploadTo)
user = models.ForeignKey('auth.User')
def __init__(self, *args, **kwargs):
self.overwrite = kwargs.pop('overwrite', False)
super(Image, self).__init__(*args, **kwargs)
if self.overwrite:
self.image.storage = OverwriteStorage()
Now i want to be able to create forms that overwrite the old image and forms that use the default behavior. What's the best way to achieve this?
No, that's not how it works at all, and this has nothing to do with your custom init. You don't call things inside Meta. In your case, you pass the parameter when you initialize the form in your view.

django admin: show list of items filtered

Am working on a django admin interface and I have a model which has a foreign key. In that field, am getting a drop down menu when the admin pages are viewed. Is there a way to filter the drop down result only where is_active=1 for example?
Regards,
limit_choices_to is what you are after.
If you only want the limited selection in your ModelAdmin you should tweak your ModelForm accordingly.
Something like this should do it:
class YourAdminForm(forms.ModelForm):
class Meta:
model = YourModel
def __init__(self, *args, **kwargs):
super(YourAdminForm, self).__init__(*args, **kwargs)
qs = self.fields['your_fk_field'].queryset
self.fields['your_fk_field'].queryset = qs.filter(is_active=1)
According to the docs
class MyModelAdmin(admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "car":
kwargs["queryset"] = Car.objects.filter(is_active=1)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
If you need access to current object check this How do I get the actual object id in a Django admin page (inside formfield_for_foreignkey)?

Dynamic forms in django-admin

I want to make admin add-form dynamic. I want to add few formfields depending on setting in related object.
I have something like this:
class ClassifiedsAdminForm(forms.ModelForm):
def __init__(self,*args, **kwargs):
super(ClassifiedsAdminForm, self).__init__(*args, **kwargs)
self.fields['testujemy'] = forms.CharField(label = "test")
And in admin.py:
class ClassifiedAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
return ClassifiedsAdminForm
As you can see, I want to add "testujemy" CharField to admin add-form and change-form. However, this way doesnt work. Is there any way to add field in init? It is working in normal view.
I've managed to do it using type().
class ClassifiedAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
adminform = ClassifiedsAdminForm()
fields = adminform.getNewFields()
form = type('ClassifiedsAdminForm', (forms.ModelForm,), fields)
return form
Hope it will help someone.

Categories