Yöneticiye model örnekler üzerinden erişilemez


87

Başka bir model nesnesi örneğini almaya çalışıyorum ve bu hatayı yükseltiyorum:

 Manager isn't accessible via topic instance

İşte modelim:

class forum(models.Model):
    # Some attributs

class topic(models.Model):
    # Some attributs

class post(models.Model):
    # Some attributs

    def delete(self):
        forum = self.topic.forum
        super(post, self).delete()
        forum.topic_count = topic.objects.filter(forum = forum).count()

İşte benim görüşüm:

def test(request, post_id):
    post = topic.objects.get(id = int(topic_id))
    post.delete()

Ve anlıyorum:

post.delete()
forum.topic_count = topic.objects.filter(forum = forum).count()
Manager isn't accessible via topic instances

Yanıtlar:


126

Söz konusu hata, Managermodelin bir örneği üzerinden bir modele erişmeye çalıştığınızda ortaya çıkar . Sen kullanmış küçük harf sınıf isimleri. Bu, hatanın bir örneğe erişip erişmemesinden kaynaklanıp kaynaklanmadığını söylemeyi zorlaştırır Manager. Bu hataya neden olabilecek diğer senaryolar bilinmediğinden, topicdeğişkeni bir şekilde karıştırdığınızı ve böylece topicsınıf yerine modelin bir örneğini gösterdiğiniz varsayımına devam ediyorum .

Suçlu bu çizgi:

forum.topic_count = topic.objects.filter(forum = forum).count()
#                   ^^^^^

Kullanmalısınız:

forum.topic_count = Topic.objects.filter(forum = forum).count()
#                   ^^^^^
#                   Model, not instance.

Ne yanlış gidiyor? objectsBir olduğu Managerdeğil örneklerine, sınıf düzeyinde kullanılabilir. Ayrıntılar için nesneleri almaya yönelik belgelere bakın. Para teklifi:

Managers"tablo düzeyinde" işlemler ve "kayıt düzeyinde" işlemler arasında bir ayrım sağlamak için model örneklerinden ziyade yalnızca model sınıfları aracılığıyla erişilebilir .

(Vurgu eklendi)

Güncelleme

Aşağıdaki @Daniel'den gelen yorumlara bakın. Sınıf isimleri için başlık büyüklüğünü kullanmak iyi bir fikirdir (hayır, ZORUNLU: P). Örneğin Topicyerine topic. Sınıf adlarınız, bir örneğe mi yoksa bir sınıfa mı atıfta bulunuyorsanız, bazı karışıklıklara neden olur. Yana Manager isn't accessible via <model> instancesçok özeldir Hep belirgin öz böylece olmayabilir bir çözeltiye hatayı sunabiliyoruz duyuyorum.


Ancak, topicsağladığı koda göre bir örnek değil, gerçek model sınıfı gibi görünüyor.
Daniel DiPaolo

@Daniel: doğru. Yine de, hata Manager isn't accessible via Foo instancesyalnızca Managerbir örneği kullanarak erişmeye çalıştığınızda mümkündür . Kaynak koduna bakın: code.djangoproject.com/svn/django/trunk/django/db/models/…
Manoj Govindan

4
Aslında, sınıf isimleri için küçük harf kullanmamak için belki başka bir neden ("en iyi uygulama" dışında) :) Potansiyel topicolarak yerel bir örnek değişkeni olarak kullanıyor ve sınıfa yapılan referansı uzaklaştırıyor gibi görünüyor.
Daniel DiPaolo

2
Kullanmalıydıntopic.model_class().objects
Nimo

7
Ayrıca kullanabilirsiniz topic.__class__.objects. model_class()Yukarıda @Nimo tarafından bahsedilmiş gibi görünüyor işe yaramıyor
sleepycal

54
topic.__class__.objects.get(id=topic_id)

Django v1.10'dan itibaren çalışır.
James

3
Bu __class__, soy sınıfının gerçek adını bilmediğimiz için soyut modellerdeki yöntemler için daha iyi çalışır. Bu durumda kullandımself.__class__.objects.get
Cometsong

33

Django <1.10 için

topic._default_manager.get(id=topic_id)

Yine de bu şekilde kullanmamalısın. _Default_manager ve _base_manager özeldir, bu nedenle, Yönetici'yi özel bir işlevde kullanmak istediğinizde olduğu gibi, bunları yalnızca Konu modelinin içindeyseniz kullanmanız önerilir.

class Topic(Model):
.
.
.
    def related(self)
        "Returns the topics with similar starting names"
        return self._default_manager.filter(name__startswith=self.name)

topic.related() #topic 'Milan wins' is related to:
# ['Milan wins','Milan wins championship', 'Milan wins by one goal', ...]

5
Teşekkürler, bu cevap tam da aradığım cevaptı. Keşke birden fazla oy kullanabilseydim. Bunun için benim kullanım durumum, soyut bir modele işlevsellik eklediğiniz zamandır, burada (bu seviyede) nihai model sınıfının ne dendiğini bilmeyeceksiniz.
fadedbee

2
Veya kullanın topic.__class__.objects.get(id=topic_id).
Bentley4

1
Bu eski bir cevap, ancak Django v1.10'dan itibaren bu özel yöntemleri artık görmüyorum. Ancak, self.__class__.objectshile diğer cevabınıza göre yapar.
James

5

Çok fazla parantez de olabilir, örn.

ModelClass().objects.filter(...)

doğru yerine

ModelClass.objects.filter(...)

Bazen bpython (veya bir IDE) otomatik olarak parantez eklediğinde aklıma geliyor.

Elbette sonuç aynı - sınıf yerine bir örneğiniz var.


0

konu bir ContentType örneği olsaydı (ki değil), bu işe yarardı:

topic.model_class().objects.filter(forum = forum)

model_class()ContentTypemodelin bir yöntemidir . Dahil olmak üzere diğer model örneklerinin topicbir model_classyöntemi yoktur.
Alasdair

Üzgünüm, soruyu yanlış okumuş olmalıyım. Görünüşte benzer bir soruyu çözmeye çalışıyordum ...
Nimo

0

Bu hataya benzer bir sorun yaşadım. Ve kodunuza dönüp baktığınızda, bu sizin de sorununuz olabilir gibi görünüyor. Sanırım sorununuz, "id" ile "int (topic_id)" ve topic_id'yi karşılaştırmanızın ayarlanmaması.

def test(request, post_id):
    post = topic.objects.get(id = int(topic_id))
    post.delete()

Kodunuzun "topic_id" değil "post_id" kullanması gerektiğini tahmin ediyorum

def test(request, post_id):
    post = topic.objects.get(id = int(post_id))
    post.delete()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.