2011-06-09 22 views
9

Ben appengine üzerinde django-nonrel deniyorum ve çoktan çoğa ilişkisi uygulamak için djangotoolbox.fields.ListField kullanmaya çalışıyorum. Belgede okuduğum gibi, ListField, çoktan çoğa ilişkileri desteklemeyen djamgo-nonrel için bir çözüm bulmak için kullanabileceğiniz bir şeydir. ListField için Django-nonrel form alanı

Bu

maketimin bir alıntıdır: Yani

class MyClass(models.Model): 
    field = ListField(models.ForeignKey(AnotherClass)) 

ben başka bir sınıfın birden çok örneği ile bir ilişki göstermek için başka bir sınıfa yabancı anahtarların bir listesini oluşturarak ediyorum bu hakkı alıyorum eğer

Bu yaklaşımla her şey iyi çalışıyor ... İstisnalar Yok. Kod ve görünümlerde `MyClass 'nesneleri oluşturabilirim. Ben yönetici arayüzü kullanmaya çalışırken Ama Ben gerçi ben daha önce yapmadığım bir şey denemek istiyorum şu hatayı

No form field implemented for <class 'djangotoolbox.fields.ListField'> 

olsun. Kendi alanımı oluştur. Peki aslında yönetici arayüzünde MyClass örneklerini düzenlemek için kendi formum. İşte ne yaptım:

class MyClassForm(ModelForm): 
    field = fields.MultipleChoiceField(choices=AnotherClass.objects.all(), widget=FilteredSelectMultiple("verbose_name", is_stacked=False)) 
    class Meta: 
     model = MyClass 

sonra yönetici arayüzü

class MyClassAdmin(admin.ModelAdmin): 
    form = MyClassForm 

admin.site.register(MyClass, MyClassAdmin) 

olsa bu işe edeceğini için kullanılacak form olarak MyClassForm geçmesine ama O yapmaz. Yönetici arayüzüne gittiğimde, daha önce olduğu gibi aynı hatayı alıyorum. Herkes burada yanlış yaptığımı söyleyebilir miyim ... ya da ListField, SetField, SetField, vb kullanarak başka herhangi bir öneri veya başarı öyküleri varsa yönetici arayüzünde çok takdir edilecektir.

cevap

10

Tamam, burada

Bu benim modeli ben olmak istedim

class MyClass(models.Model): 
    field = ListField(models.ForeignKey(AnotherClass)) 

neye benzediğini ne zaman ... bu her çalışma ben baştan başlayacağız almak için ne yaptığını ise liste alanı için çoklu seçim aracı kullanarak bu modelin örneklerini oluşturmak/düzenlemek için yönetici arayüzünü kullanabilir. Bu nedenle, aşağıdaki sınıflar aşağıdaki gibi özel sınıflar oluşturdum. Bu sınıflar, liste alanının yönetici içinde kullanılmasına izin verir. Sonra ben bir yönetici modeli oluşturduk bu yaptıktan sonra yönetici sitesinde

class MyClassForm(ModelForm): 
    def __init__(self, *args, **kwargs): 
     super(MyClasstForm,self).__init__(*args, **kwargs) 
     self.fields['field'].widget.choices = [(i.pk, i) for i in AnotherClass.objects.all()] 
     if self.instance.pk: 
      self.fields['field'].initial = self.instance.field 

    class Meta: 
     model = MyClass 

kullanmak için bir form oluşturulur ve bu artık benim kodunda çalışıyor yönetici sitesinde

class MyClassAdmin(admin.ModelAdmin): 
    form = MyClassForm 

    def __init__(self, model, admin_site): 
     super(MyClassAdmin,self).__init__(model, admin_site) 

admin.site.register(MyClass, MyClassAdmin) 

ile kayıtlı. Bu yaklaşımın google_appengine için hiç de uygun olmayabileceğini aklınızdan çıkarmayın, çünkü nasıl çalıştığı konusunda çok usta değilim ve bu da verimsiz sorgular yaratabilir.

+0

Rman, Yukarıdaki örneği uygulayan sorunlar yaşıyorum, girişinizi http://stackoverflow.com/questions/7782535/django-nonrel-with-mongdb-listfield adresinde yayınlayabilir misiniz? – bobsr

0

Bu ilişkisiz olabilir ama yönetici arayüzü için, .. ayarlarda django.contrib.admin sonra listelenen djangotoolbox olduğundan emin olmak Bildiğim kadarıyla anladığım kadarıyla

3

INSTALLED_APPS, bir M2M sahip çalışıyoruz Kutu dışı bir işlev olmayan django-nonrel'deki ilişki. Hızlı bir hack istiyorsanız başlayanlar için, bu basit sınıfı ile gidip elle yabancı anahtarları girmek için bir CharField kullanabilirsiniz:

class ListFormField(forms.Field): 
    """ A form field for being able to display a djangotoolbox.fields.ListField. """ 

    widget = ListWidget 

    def clean(self, value): 
     return [v.strip() for v in value.split(',') if len(v.strip()) > 0] 

Ama istersen sana normalde modelleri listesinden bir çoklu seçim var Ayrıca django-nonrel'de işlevsel olmayan ModelMultipleChoiceField'ı kullanmak zorundayım. Burada, bir M2S ilişkisini bir MultipleSelectField kullanarak taklit ettim:

Sırasıyla, 2 sınıf, SomeClass ve AnotherClass arasında bir M2M ilişkinizin olduğunu varsayalım. SomeClass for formundaki ilişkiyi seçmek istersiniz. Ayrıca, referansları SomeClass'ta bir ListField olarak tutmak istediğinizi varsayalım. (Doğal olarak App Engine üzerinde çalışıyorsanız, patlayan endeksleri önlemek için here açıklandığı gibi M2M ilişkileri oluşturmak istiyorsunuz).

class SomeClass(models.Model): 
    another_class_ids = ListField(models.PositiveIntegerField(), null=True, blank=True) 
    #fields go here 

class AnotherClass(models.Model): 
    #fields go here 

Ve formda:

Yani sevdiği modelleri var

class SomeClassForm(forms.ModelForm): 

    #Empty field, will be populated after form is initialized 
    #Otherwise selection list is not refreshed after new entities are created. 
    another_class = forms.MultipleChoiceField(required=False) 

def __init__(self, *args, **kwargs): 
    super(SomeClassForm,self).__init__(*args, **kwargs) 
    self.fields['another_class'].choices = [(item.pk,item) for item in AnotherClass.objects.all()] 

    if self.instance.pk: #If class is saved, highlight the instances that are related 
     self.fields['another_class'].initial = self.instance.another_class_ids 

def save(self, *args, **kwargs): 
    self.instance.another_class_ids = self.cleaned_data['another_class']   
    return super(SomeClassForm, self).save() 

class Meta: 
    model = SomeClass 

Umarım bu size başlangıç ​​için gitmeliyiz, bunu ayarlamak normal formlar için bu işlevi uygulamaya yönetici paneli için o kadar zor olmamalı.

+0

Teşekkür soran tarafından bu tür bir kullanım için özel form sınıfı önlemek olabilir. İhtiyacım olan şeylere nasıl ulaşacağımı anlamama yardımcı oldu. Şimdi kendi formlarımda bir 'ListMield'ı' SelectMultiple 'olarak görüntüleyebilirim. Bunu yönetici sayfalarında çalışmak için daha fazla çalışma yapmak zorundayım. – Rman

+0

Yönetici sayfalarında bunun çalışması için hangi işlerin yapılması gerektiğini açıklayabilir misiniz? – raymi

0

Sen modeli nesnesi için örnek kod için

class ModelListField(ListField): 
    def __init__(self, embedded_model=None, *args, **kwargs): 
    super(ModelListField, self).__init__(*args, **kwargs) 
    self._model = embedded_model.embedded_model 

    def formfield(self, **kwargs): 
    return FormListField(model=self._model, **kwargs) 

class ListFieldWidget(SelectMultiple): 
    pass 

class FormListField(MultipleChoiceField): 
    widget = ListFieldWidget 

    def __init__(self, model=None, *args, **kwargs): 
    self._model = model 
    super(FormListField, self).__init__(*args, **kwargs) 
    self.widget.choices = [(unicode(i.pk), i) for i in self._model.objects.all()] 

    def to_python(self, value): 
    return [self._model.objects.get(pk=key) for key in value] 

    def clean(self, value): 
    return value 
İlgili konular