2011-01-06 5 views
5

Ya he solucionado el problema de conseguir la identificación del objeto que está siendo editado utilizando este código:¿Cómo obtengo el ID del objeto real en una página de administración de Django (dentro de formfield_for_foreignkey)?

class CompanyUserInline(admin.StackedInline): 
    """ 
    Defines tabular rules for editing company users direct in company admin 
    """ 
    model = CompanyUser 

    def formfield_for_foreignkey(self, db_field, request, **kwargs): 

     if db_field.name == "user": 
      users = User.objects.filter(Q(is_superuser=False)) 
      query = Q() 
      for u in users: 
       aux = CompanyUser.objects.filter(user=u) 
       if aux.count() == 0: 
        query |= Q(pk=u.id) 

      try: 
       cpu = CompanyUser.objects.filter(company__id=int(request.path.split('/')[4])) 
       for p in cpu: 
        query |= Q(pk=p.user.id) 
      except: 
       pass 

      kwargs["queryset"] = User.objects.filter(query).order_by('username') 

     return super(CompanyUserInline, self).formfield_for_foreignkey(db_field, request, **kwargs) 

embargo, la int (request.path.split ("/") [4]) es realmente feo. Quiero saber cómo obtengo el ID del Django AdminModel. Estoy seguro de que está en algún lugar dentro de ella, ¿alguien sabe?

¡Gracias de antemano! ; D

Respuesta

7

Por lo que sé, no es posible acceder a la instancia actual a través de formfield_for_... -methods, ¡ya que solo se llamarán para una única instancia de campo!

Un mejor punto para enganchar en esta lógica donde se puede acceder a toda la instancia/formulario sería get_form. ¡También puede sobrescribir el queryset de un campo de formulario allí!

+0

¿Dónde puedo encontrar algunos documentos sobre el get_form? Intenté pasar el objeto y funcionó, pero no tengo idea de cómo usar el método para sobrescribir el queryset del campo de formulario allí ... =/ –

+2

Vea el código original en http: //code.djangoproject. com/browser/django/trunk/django/contrib/admin/options.py. Si 'form' sería la forma devuelta por el método orignal' get_form', 'form.base_fields' debería ser un diccionario de los objetos de campo. –

+0

Ok! ¡Gracias hombre! Lo echaré un vistazo y publicaré aquí la solución. Si lo logro! ¡Gracias de nuevo! ; D –

-1

Estaba lidiando con una situación similar, y me di cuenta de que la identificación que necesitaba de la solicitud, podía hacerlo desde el modelo en sí, ya que era una clave externa para ese modelo. Por lo tanto, sería algo así como:

cpu = CompanyUser.objects.filter(company__id=self.company_id) 

o lo que sea que dicte la estructura de su modelo.

+0

¿Podría agregar un poco más de contexto y explicación a esta respuesta? ¿A qué método va esta línea? ¿Que clase? ¿Qué módulo? – jononomo

4

Después de algo de investigación en todo, hemos sido capaces de agarrar los argumentos que van pasando a la vista de administración (después de haber sido analizado por urls.py Django admin) y el uso que (self_pub_id) para agarrar el objeto:

class PublicationAdmin(admin.ModelAdmin): 

    def formfield_for_manytomany(self, db_field, request, **kwargs): 
     if db_field.name == "authors": 
      #this line below got the proper primary key for our object of interest 
      self_pub_id = request.resolver_match.args[0] 

      #then we did some stuff you don't care about 
      pub = Publication.objects.get(id=self_pub_id) 
      kwargs["queryset"] = pub.authors.all() 
     return super(PublicationAdmin, self).formfield_for_manytomany(db_field, request, **kwargs) 

Una solución más elegante es utilizar la recomendación de respuestas aceptadas y aprovechar la función de miembro get_form ModelAdmin. De este modo:

class ProfileAdmin(admin.ModelAdmin): 
    my_id_for_formfield = None 
    def get_form(self, request, obj=None, **kwargs): 
     if obj: 
      self.my_id_for_formfield = obj.id 
     return super(ProfileAdmin, self).get_form(request, obj, **kwargs) 

    def formfield_for_foreignkey(self, db_field, request, **kwargs): 
     if db_field.name == "person": 
      kwargs["queryset"] = Person.objects.filter(profile=self.my_id_for_formfield) 
     return super(ProfileAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs) 
+0

¡Hola, esto es hacky! Pero funciona. Cruzamos nuestro propio camino de nuevo. – FizxMike

+0

Puede almacenar todo el objeto, no es necesario almacenar solo el id. ¡Buena solución, sin embargo! – Sylvain

0

hice que funcione mediante la creación de una propiedad() en model.py que devuelve el ID de

models.py:

class MyModel(models.Model): 
    myfield = models.CharField(max_length=75) 
    ... 
    def get_id(self): 
     return str(self.id) 
    getid = property(get_id) 

admin.py:

from myapp.models import MyModel 

class MyModelAdmin(admin.ModelAdmin): 
    list_display = ['mylink',] 
    def mylink(self, object): 
     return '<a href="http://mywebsite/'+object.getid+'/">Edit</a>' 
    mylink.allow_tags = True 

admin.site.register(MyModel, MyModelAdmin) 
+0

Eso es fácil. Quería una forma de usar la identificación en formfield_for_foreignkey, no simplemente mostrarla al usuario. –

+0

De acuerdo, esto no responde la pregunta. – FizxMike

2

Lo hice funcionar reescribiendo change_view()

class CartAdmin(admin.ModelAdmin): 

def change_view(self, request, object_id, form_url='', extra_context=None): 
    self.object_id = object_id 
    return self.changeform_view(request, object_id, form_url, extra_context) 


def formfield_for_foreignkey(self, db_field, request, **kwargs): 
    print self.object_id 
    return super(CartAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs) 

entonces se puede llamar self.object_id dentro formfield_for_foreignkey()

Cuestiones relacionadas