37

I've made a model (models.py):

class opetest(models.Model):
    name = models.CharField(max_length=200)
    author = models.ForeignKey(User, related_name='author')
    description = models.TextField(u'Test description', help_text = u'Some words about quiz')
    pub_date = models.DateTimeField('date published', blank=False)
    vacancies = models.ManyToManyField(Vacancy, blank=True)
    students = models.ManyToManyField(User, blank=True, related_name='opetests') #This field I want to edit on "User change page"
    estimate = models.IntegerField(default = 0, help_text = u'Estimate time in hours. \'0\' - unlimited')

then I try to add inline block to allow assign opetest on 'change user' page (admin.py):

class ProfileAdmin(UserAdmin):
    filter_horizontal = ('opetests',)

admin.site.unregister(User)
admin.site.register(User, ProfileAdmin)

And I got an error:

'ProfileAdmin.filter_horizontal' refers to field 'opetests' that is missing from model 'User'.

I want to show opetests like Groups on change user page. How can I achieve that?

baobee
  • 433
  • 1
  • 4
  • 8
  • 1
    If the answer below answered your question, can you please tick it? If it didn't, please let us know what else you need, and we can try and help. – victorhooi Nov 15 '11 at 00:08

1 Answers1

78

Hmm, I don't think you want inlines here.

You want to be using the Django admin's filter_horizontal:

https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.filter_horizontal

class ProfileAdmin(UserAdmin)
    filter_horizontal = ('opetest',)

That will give you the widget that you're describing, used to add/remove Groups on the User Change page.


Ok, based on your edits, updated answer - basically, what we have is a UserProfile, linked to each user.

The UserProfile contains a m2m relationship to opetest - which we show in the admin with a filter_horizontal. End result is something like this:

Opetest with Filter horizontal

models.py

from django.db import models
from django.contrib.auth.models import User

class opetest(models.Model):
    name = models.CharField(max_length=200)
    author = models.ForeignKey(User, related_name='author')
    description = models.TextField(u'Test description', help_text = u'Some words about quiz')
    pub_date = models.DateTimeField('date published', blank=False)
    #vacancies = models.ManyToManyField(Vacancy, blank=True)
    students = models.ManyToManyField(User, blank=True, related_name='opetests') #This field I want to edit on "User change page"
    estimate = models.IntegerField(default = 0, help_text = u'Estimate time in hours. \'0\' - unlimited')

class UserProfile(models.Model):
    user = models.OneToOneField(User, unique=True)
    ope = models.ManyToManyField(opetest)
    test_flag = models.BooleanField()

admin.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from secondapp.models import UserProfile, opetest

admin.site.unregister(User)

class opetestAdmin(admin.ModelAdmin):
    pass

class UserProfileInline(admin.StackedInline):
    model = UserProfile
    filter_horizontal = ('ope',)

class CustomUserAdmin(UserAdmin):
    #filter_horizontal = ('user_permissions', 'groups', 'ope')
    save_on_top = True
    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'last_login')
    inlines = [UserProfileInline]

admin.site.register(User, CustomUserAdmin)
admin.site.register(opetest, opetestAdmin)

Let me know if you have any questions, or need anything further.

victorhooi
  • 16,775
  • 22
  • 90
  • 113
  • filter_horizontal parameters should refer to model fields. But opetest here is a model. – baobee Nov 07 '11 at 23:08
  • Hmm, why don't you create the `opetest` field on UserProfile, and have that map to `opetest`? It's a m2m field, so it shouldn't really matter which end of the relationship it's on - then you can just use `filter_horizontal` on the `opetest` field? – victorhooi Nov 07 '11 at 23:13
  • Sorry Victor, can you please describe, how can I create field on UserProfile and map it to opetest? – baobee Nov 07 '11 at 23:19
  • So, I've added field but it doesn't work: 'class ProfileAdmin(UserAdmin):' 'usertests = models.ManyToManyField(opetest, blank=True)' 'ProfileAdmin.filter_horizontal' refers to field 'usertests' that is missing from model 'User'.' filter_horizontal = ('usertests',) – baobee Nov 07 '11 at 23:39
  • Hmm, can you edit your question, and paste your full `models.py` and `admin.py` please? I'm a bit confused about the previous text, as you have `class ProfileADmin(UserAdmin)`, which looks like `admin.py`, but then in the next line you define a model field. If you paste your full code, we can help you get it working easier. – victorhooi Nov 08 '11 at 00:36
  • it was an experiment because I don't know how to add field "on the fly" on ProfileADmin. Can you help me? So, I have 'start' models and rolled back the changes. – baobee Nov 08 '11 at 06:49
  • @baobee: What do you mean by "on the fly"? Do you mean dynamically at run-time? *confused*. If you paste your source code, and what you're trying to achieve, we may be able to help you more =). – victorhooi Nov 08 '11 at 11:53
  • Can it be used outside of django admin? I wanted to use it in an intermediate view I created which technically isn't an official admin view, I just add the url in get_urls. – radtek Feb 18 '15 at 20:33