4

I know, that question was asked but it is not clear to me.

I have put all fields 'readonly field' for Essai_TemperatureInline.

I would like to add new Inline in the admin for records not created by current user.

How to do if I want to add new records?

class Essai_TemperatureInline(admin.TabularInline):
    model = Essai_Temperature
    extra = 5
    ordering = ('choix__name', 'choix__lapropriete',)

    def get_readonly_fields(self, request, obj=None):
        if request.user.is_superuser == False:
            notBelongToMe = Material.objects.exclude(user=request.user)
            jj = 0
            if obj:
                while jj < len(notBelongToMe):
                    if notBelongToMe[jj] == obj:
                        return self.readonly_fields + (
                            'name',
                            'nature_unit',
                            'choix',
                            'valT',
                            'val10',
                            'val_ref',
                        )
                    jj += 1

    return self.readonly_fields

class MaterialAdmin(admin.ModelAdmin):
    inlines = (MediaInline, UniteProperty2Inline, Essai_TemperatureInline)
Wtower
  • 18,848
  • 11
  • 103
  • 80
user3172700
  • 107
  • 2
  • 13

2 Answers2

3

Unfortunately, you can't. At least not in a nice way, trough Python, as you would expect if you know how to do it with regular ModelAdmin. It's a bug in the admin, documented in Ticket #15602

What you can do is make use of JavaScript. Use this selector:

.inline-group tr.has_original

The has_original class is applied to every inline that represents an already-saved model instance.

So, in the Essai_TemperatureInline class, make all your fields editable (non-readonly), and then use JS (jQuery, I guess) to make some of the fields readonly:

django.jQuery('.inline-group tr.has_original #id_somefield').attr('readonly', 'readonly');

See The Documentation about how to add your own JS to admin pages. Basically:

class ArticleAdmin(admin.ModelAdmin):
    class Media:
        css = {
            "all": ("my_styles.css",)
        }
        js = ("my_code.js",)

security note:

This can obviously easily be tricked over, with Firebug or similar browser tool. So make sure to take that into account if necessary, and do some checks, probably somewhere on formset.clean()

Community
  • 1
  • 1
frnhr
  • 12,354
  • 9
  • 63
  • 90
  • If I could find a tutorial for inline-group that would be fine. inline-group tr.has_original is probably in a file (for example) 'addline.js' in a class Media inside Essai_TemperatureInline – user3172700 Apr 04 '14 at 16:08
  • @user3172700 sorry, what? :) I don't get what you mean. – frnhr Apr 04 '14 at 19:01
  • How to do that ? :class Essai_TemperatureInline(admin.TabularInline): model = Essai_Temperature class Media: js = ['static/js/jquery-1.7.2.js', '/static/js/addline.js',] – user3172700 Apr 05 '14 at 03:01
  • @user3172700 I think that's correct, see my updated answer. I would put it on the `ModelAdmin`, just to be sure, though it should work on the `Inline` class as well. – frnhr Apr 05 '14 at 04:11
  • the difficulty is how to transcribe with javascript "Material.objects.exclude(user=request.user)" ? with .inline-group tr.has_original – user3172700 Apr 07 '14 at 07:38
  • I'm sorry I don't follow, what do you mean by "transcribe with JS". If you'd like to filter what objects appear in the `Inline` then a custom `queryset()` method is what you're after, see [this answer](http://stackoverflow.com/a/6741937/236195). But that's a separate question. – frnhr Apr 07 '14 at 09:17
0

If you do not really care if the field is read only but you only need to prevent users from changing it, I have found a workaround:

In the clean method of the inline modelform raise a vailidation error:

class Essai_TemperatureForm(forms.ModelForm):
    def clean(self):
        if self.has_changed() and self.initial:
            raise ValidationError(
                'You cannot change this inline',
                code='Forbidden'
            )
        return super().clean()

    class Meta(object):
    model = Essai_Temperature
    fields='__all__'
raratiru
  • 8,748
  • 4
  • 73
  • 113