Подтвердить что ты не робот

Непрямой встроенный в Django admin

У меня есть следующие модели:

class UserProfile(models.Model):
    user = models.OneToOneField(User)

class Property(models.Model):
    user = models.ForeignKey(User)

Я хотел бы создать TabularInline, отображающий каждое Свойство, связанное с конкретным UserProfile на его странице администратора Django. Проблема здесь, конечно, в том, что свойство не имеет ForeignKey непосредственно к UserProfile, поэтому я не могу просто написать

class PropertyTabularInline(admin.TabularInline):
    model = Property

class UserProfileAdmin(admin.ModelAdmin):
    inlines = (PropertyTabularInline,)

Как я могу легко делать то, что хочу?

4b9b3361

Ответ 1

Вы можете перезаписать страницу администрирования пользователя, чтобы отобразить модели Profile и Property.

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from myapp.models import *

class ProfileInline(admin.TabularInline):
    model = Profile

class PropertyInline(admin.TabularInline):
    model = Property

class UserAdmin(UserAdmin):
    inlines = (ProfileInline, PropertyInline,)

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

Вы также можете удалить любые нежелательные/неиспользуемые свойства пользователя (например, группы или разрешения)

здесь: https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#extending-the-existing-user-model

и здесь: https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#a-full-example

Ответ 2

class PropertyTabularInline(admin.TabularInline):
    model = Property

    def formfield_for_dbfield(self, field, **kwargs):
        if field.name == 'user':
            # implement your method to get userprofile object from request here.
            user_profile = self.get_object(kwargs['request'], UserProfile)
            kwargs["queryset"] = Property.objects.filter(user=user_profile)
        return super(PropertyInLine, self).formfield_for_dbfield(field, **kwargs)

как только это будет сделано, вы можете добавить этот встроенный пользователь UserProfileAdmin, например:

class UserProfileAdmin(admin.ModelAdmin):
    inlines = (PropertyTabularInline,)

Не тестировали, но это должно работать.

Ответ 3

Это можно сделать, сделав одно изменение в ваших моделях.

Вместо создания отношения OneToOne от UserProfile до User, подкласса User, создающего UserProfile. Код должен выглядеть так:

class UserProfile(User):
    # some other fields, no relation to User model

class Property(models.Model):
    user = models.ForeignKey(User)

Это приведет к созданию модели UserProfile, у которой скрытое отношение OneToOne к модели User, оно не будет дублировать модель пользователя.

После выполнения этого изменения ваш код будет работать. Есть некоторые изменения под капотом, например, UserProfile больше не имеет собственного идентификатора, вы можете получить доступ к полям из User внутри UserProfile и трудно переопределить модель User, используя settings.AUTH_USER_MODEL (для этого потребуется создать некоторые пользовательская функция возвращает правильный тип и меняет миграцию вручную), но если это не проблема для вас, это может быть хорошим решением.