How to populate django admin form from model property? - python

I have model which among other fields contains price property which is calculated dynamically. I want to display this property in model admin page. So I've created custom ModelForm:
class ShipmentForm(forms.ModelForm):
price = forms.IntegerField()
class Meta:
model = models.Shipment
fields = [
'title',
'price',
]
However I can't get price value in that form.
Here's how I change form in admin panel:
class ShipmentAdmin(admin.ModelAdmin):
form = ShipmentForm

See ModelAdmin.readonly_fields (Django 1.10 docs link).
A read-only field can not only display data from a model’s field, it can also display the output of a model’s method or a method of the ModelAdmin class itself.
This means that you can do:
class ShipmentAdmin(admin.ModelAdmin):
readonly_fields = ('price', 'something_else')
def something_else(self, instance):
# calculate something else here
Where price is a model method, and something_else is a ModelAdmin method.

Related

how to give condition on displaying value in Django admin

Hi i have user model consist of several fields, in that payment_type is one field which return integer value , so based on that value i need to show some string sentence.
class Users(models.Model):
payment_type=models.IntegerField()
in my admin i need to make condition to display. I am new to django so support
For choices, you can use get_FOO_display in admin list_display or write your own customized method to get more control of what get displayed in admin panel
#admin.register(User)
class UserAdmin(BaseUserAdmin):
list_display = ('get_payment_type_display', )
# or you can write your own method
#admin.register(User)
class UserAdmin(BaseUserAdmin):
list_display = ('get_payment_type', ) # method
# call get_<field>_display
def get_payment_type(self, obj):
return obj.get_payment_type_display()
get_payment_type.short_description = 'Payment Type'

Understanding UpdateView to change the Form and FormWidget

I still didn't understood the UpdateView. Where does it fetch the form from?
It has exactly the fields declared in the model, but doesn't use the form defined in forms.py.
I did however follow the answer given at:
How does one use a custom widget with a generic UpdateView without having to redefine the entire form?
In my case I use an IntegerField in model.py and use Radiobuttons in the Form.
So what the UpdateView does is giving me an IntegerField instead of a ChoiceField. Even when I assigned the RadioSelect Widget or a Choice Field:
The View:
class UpdateEinflussideen(UpdateView):
model = Einflussideen
EINFLUSS = [(10,'hoch'),(4,'mittel'),(1,'gering')]
form_class = forms.models.modelform_factory(Einflussideen,
widgets={'einfluss': forms.ChoiceField(
choices=EINFLUSS, widget=forms.RadioSelect())},
)
template_name = 'verbrauchererfassung/update_einflussideen.html'
success_url = reverse_lazy('verbraucher')
The Model:
class Einflussideen(models.Model):
idee = models.CharField(max_length=100)
einfluss = models.IntegerField()
verbraucher = models.ForeignKey(Verbraucher)
Variables in python are case-sensitive. Change the atribute form_Class to the form_class. Also the widgets argument should contain a dict with the Widget instances in the values:
form_class = forms.models.modelform_factory(Einflussideen,
widgets={'einfluss': forms.RadioSelect(choices=EINFLUSS)})

Django Rest Order on custom field from serializer?

I'm trying to use Django Rest to return a json representation of a model based on a ordering from a custom field that is not attached to the model, but is attached to the serializer. I know how to do this with model specific fields, but how do you use django rest to return an ordering when the field is only within the serializer class? I want to return a list of Pics ordered by 'score'. Thanks!
------Views.py
class PicList(generics.ListAPIView):
queryset = Pic.objects.all()
serializer_class = PicSerializerBasic
filter_backends = (filters.OrderingFilter,)
ordering = ('score')
------Serializer.py
class PicSerializer(serializers.ModelSerializer):
userprofile = serializers.StringRelatedField()
score = serializers.SerializerMethodField()
class Meta:
model = Pic
fields = ('title', 'description', 'image', 'userprofile', 'score')
order_by = (('title',))
def get_score(self, obj):
return Rating.objects.filter(picc=obj).aggregate(Avg('score'))['score__avg']
You could move the logic of the method get_score to the manager of the class Pic. In this answer there is an example of how to do it.
Once you have it in the manager, the score field would become "magically" available for every object of the class Pic everywhere (serializer, views...) and you'll be able to use it for ordering.

unmodifiable attribute in django admin

I have simply model class:
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
I want to set attribute title unmodifiable in django admin. What should I do to set this?
Add the field name to readonly_fields of that model's ModelAdmin class. According to the documentation:
By default the admin shows all fields as editable. Any fields in this option (which should be a list or tuple) will display its data as-is and non-editable.
In your situation this looks like:
readonly_fields = ("title",)

Django admin choice field dynamically populated by generic foreign key's model fields

Say I have the following simple models for some tagging application (this is simplified from the actual code):
# Model of tag templates
class TagTemplate(models.Model):
name = models.CharField()
content_type = models.ForeignKey(ContentType)
class Tag(models.Model):
template = models.ForeignKey(TagTemplate)
object_id = models.PositiveIntegerField()
* content_object = generic.GenericForeignKey('template__content_type', 'object_id')
# Each tag may display the
class TagTemplateItemDisplay(models.Model):
template = models.ForeignKey(TagTemplate)
content_type_field = models.CharField()
font_size = models.IntegerField()
I have two questions:
1) In the line marked with the *, I understand from the documentation that I need to pass the two field names as per the contenttype framework. In my case the content_type field is specified within the template model. I'd like to avoind a duplicate content_type field within the 'tag' model to get the GenericForeignKey working. Is this possible? Or do I need some custom manager to implement a duplicate content_type within the tag model?
2) I'd like to use the admin site with these models. Is it possible to dynamically create a choice dropdown for the 'content_type_field' field where the contents corresponds to a list of fields from the chosen content_type of the parent model (ie. tagTemplate) when using Tabularinline layout?
eg. in the admin site I pick a model (content_type field) for a new tagTemplate record that contains the fields ('name', 'age', 'dob'), I'd like the TabularInline forms to dynamically update the 'content_type_field' to contain the choices name, age and dob. If i then pick a different model in the parent tagTemplate content_type field, the choices in the child tagTemplateItemDisplay content_type_field of the inline are updated again.
You can subclass the form for that model
class TagTemplateForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(TagTemplateForm, self).__init__(*args, **kwargs)
if self.instance.content_type == SomeContentType:
**dynamically create your fields here**
elif self.instance.content_type == SomeOtherContentType:
**dynamically create your other fields here**
Then in your TagAdmin model you need to have:
form = TagTemplateForm
to override the default form created for the admin site.
Not a complete solution but should get you started.
For the dynamic form generation, you might start by reading over this

Categories

Resources