Django admin: Encomenda de ForeignKey e ManyToManyField relações referenciando Usuário
-
16-09-2019 - |
Pergunta
Eu tenho um aplicativo que faz uso de UserProfile
do Django para estender o built-in Django modelo User
. Parece um pouco como:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
# Local Stuff
image_url_s = models.CharField(max_length=128, blank=True)
image_url_m = models.CharField(max_length=128, blank=True)
# Admin
class Admin: pass
Eu adicionei uma nova classe para o meu modelo:
class Team(models.Model):
name = models.CharField(max_length=128)
manager = models.ForeignKey(User, related_name='manager')
members = models.ManyToManyField(User, blank=True)
E ele é registrado no Administrador:
class TeamAdmin(admin.ModelAdmin):
list_display = ('name', 'manager')
admin.site.register(Team, TeamAdmin)
Infelizmente, na inteface admin, quando vou para selecionar um gerente partir da caixa drop-down, ou membros da equipe definida através do campo multi-select, eles são ordenados pela numérico ID de usuário. Para a vida de mim, eu não consigo descobrir como obter esses ordenados.
Eu tenho uma classe semelhante com:
class Meta:
ordering = ['name']
Isso funciona muito bem! Mas eu não "próprio" a classe User
, e quando eu tente este truque em UserAdmin
:
class Meta:
ordering = ['username']
eu recebo:
django.core.management.base.CommandError: One or more models did not validate:
events.userprofile: "ordering" refers to "username", a field that doesn't exist.
user.username
não quer trabalhar. Eu poderia especificar, como image_url_s
se eu quisesse. . . como posso dizer ao administrador para classificar minhas listas de usuários por username
? Obrigado!
Solução
Uma maneira seria definir um formulário personalizado para usar para o seu modelo de equipe do admin, e substituir o campo manager
usar um queryset com a ordem correta:
from django import forms
class TeamForm(forms.ModelForm):
manager = forms.ModelChoiceField(queryset=User.objects.order_by('username'))
class Meta:
model = Team
class TeamAdmin(admin.ModelAdmin):
list_display = ('name', 'manager')
form = TeamForm
Outras dicas
Este
class Meta:
ordering = ['username']
deve ser
ordering = ['user__username']
se é em sua classe admin UserProfile. Isso vai parar a exceção, mas eu não acho que ele ajuda você.
Como encomendar o modelo User como você descreve é ??bastante complicado, mas veja http: // código .djangoproject.com / ingressos / 6089 # comentário: 8. para uma solução
Isso pode ser perigoso, por algum motivo, mas isso pode ser feito em uma única linha no arquivo models.py
do seu projeto:
User._meta.ordering=["username"]
Para mim, a única solução trabalho era usar Proxy modelo. Como indicado na documentação, você pode criar modelos próprios de proxy, mesmo para built-in modelos e personalizar qualquer coisa como em modelos regulares:
class OrderedUser(User):
class Meta:
proxy = True
ordering = ["username"]
def __str__(self):
return '%s %s' % (self.first_name, self.last_name)
Depois disso, no seu modelo apenas mudar Chave estrangeira para:
user = models.OneToOneField(OrderedUser, unique=True)
ou até mais adequado
user = models.OneToOneField(OrderedUser, unique = True, parent_link = True)