unmodifiable attribute in django admin - python

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",)

Related

How to populate django admin form from model property?

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.

Django: "UserProfileRole.userProfile" must be a "UserProfile" instance

I'm having a strange riddle to solve:
I extended my django-1.4 user-objects with a UserProfile, as described at https://docs.djangoproject.com/en/dev/topics/auth/ and wanted to implement project-specific roles. So my models look like the following:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
projects = models.ManyToManyField(Project, through='UserProjectRole')
[...]
class UserProjectRole(models.Model):
userProfile = models.ForeignKey(UserProfile)
project = models.ForeignKey(Project)
group = models.ForeignKey(Group)
[...]
I needed to pass a css-class, so I created a model-form for UserProjectRole and implemented the userProfile-Field with a widget:
class ProjectRoleForm(forms.ModelForm):
userProfile = forms.ModelMultipleChoiceField(label='Users',
queryset=UserProfile.objects.all(),
widget=forms.SelectMultiple(attrs={'class': 'select-multiple'}))
class Meta:
model = UserProjectRole
The form is presented correctly, however, it's crashing during save-process with the following error
Cannot assign "[<UserProfile: MyUser>]": "UserProjectRole.userProfile" must be a "UserProfile" instance.
Does anyone have an idea?
My guess is it's because you are using a forms.SelectMultiple widget. Which gives you a list of UserProfile instances ( [<UserProfile: MyUser>] ) and not a single UserProfile instance which is of course required to set on a ForeignKey field (UserProjectRole.userProfile). Thus I suggest to try using a forms.Select widget instead.

Django admin List Display + ForeignKey = Empty Change List

I've got a weird problem in django admin list_display. Whenever I add a foreign key to a list_display the whole change list view goes blank showing only the total no of entries.
models.py:
class Organization(models.Model):
org_id = models.AutoField(primary_key=True)
org_name = models.CharField(max_length=288)
def __unicode__(self):
return self.org_name
class Meta:
db_table = u'organization'
class Server(models.Model):
server_id = models.AutoField(primary_key=True)
server_name = models.CharField(max_length=135,verbose_name="Server Name")
org = models.ForeignKey(Organization,verbose_name="Organization")
def __unicode__(self):
return self.server_name
class Meta:
db_table = u'server'
admin.py:
class ServerAdmin(admin.ModelAdmin):
list_display = ('server_name','org')
admin.site.register(Server,ServerAdmin)
Now I'd expect this code to show me the organization name in the ChangeList View, But instead I get this:
If I remove the org in the list_display of ServerAdmin class, I get this:
I didn't modify the template or override any ModelAdmin methods. I'm using Mysql(5.1.58) as my database that comes with ubuntu 11.10 repository.
I'll be really glad if I could a get a sloution for this problem guys. Thanks in advance.
I second Stefano on the fact that null=True, blank=True is to be added. But, I think you only need to add it to the org_name field of the Organization model. That should make your way through. It has to be done because you have run inspectdb to create models from your legacy DB. And probably the organization table in the DB has an empty string stored. So, adding the above would allow the Admin to have a blank field/column displayed.
Moreover, you can also try using callbacks in situations where you don't want to make changes to your model definition like the above.
Try adding null=True, blank=True to all your model fields.
Usually django admin will silenty fail (thus show no records in the list) if the row does not validate the model constraints.
See: https://stackoverflow.com/a/163968/1104941
Does the following work for you?
admin.py:
class ServerAdmin(admin.ModelAdmin):
list_display = ('server_name','org__org_name')
admin.site.register(Server,ServerAdmin)
I had a similar problem and solved it like this (using your example):
class ServerAdmin(admin.ModelAdmin):
list_display = ('server_name', 'get_org')
def get_org(self, obj):
return obj.org.org_name
get_org.short_description = 'Org'
admin.site.register(Server,ServerAdmin)

how can I make a Django model form with a field name in the form different from the model field name?

I have a model and a form like this:
class Content(models.Model):
title = models.CharField(_("title"), max_length=16)
category = models.ForeignKey(Category, verbose_name = _('category'))
class ContentForm(forms.ModelForm):
class Meta:
model=Content
fields = ('title', 'category', )
I would like to have the name of the field in the form to be f_category (of course the name of the field in the model is to stay category). Is it possible to do that, without having to construct the whole form manually (which is difficult because the field is a ForeignKey and has to be a select field with a list of options)?
To clarify: by name I mean the name as in the HTML form code: <input type="select" name="f_category" />
Your comment reveals what you actually need to do - this is why you should always describe your actual problem, not your proposed solution. Naturally, there is a proper way to deal with two identical forms on the same page in Django - use the prefix parameter when instantiating the field.
form1 = MyForm(prefix='form1')
form2 = MyForm(prefix='form2')
Now when you output form1 and form2, all the fields will automatically get the relevant prefix, so they are properly separated.
I'm not sure what you mean by "the name of the field in the form". Do you mean the label? Or the id? Or something else? Configuring the label is pretty easy:
class ContentForm(forms.ModelForm):
category = forms.ModelChoice(queryset=Category.objects.all(), label='f_category')
class Meta:
model=Content
fields = ('title', 'category', )

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