Django: Bazı model alanları neden birbiriyle çatışıyor?


174

Kullanıcılara 2 bağlantı içeren bir nesne oluşturmak istiyorum. Örneğin:

class GameClaim(models.Model):
    target = models.ForeignKey(User)
    claimer = models.ForeignKey(User)
    isAccepted = models.BooleanField()

ancak sunucuyu çalıştırırken aşağıdaki hataları alıyorum:

  • 'Target' alanı için erişimci 'User.gameclaim_set' ile ilgili alanla çakışıyor. 'Target' tanımına related_name bağımsız değişkeni ekleyin.

  • 'Davacı' alanı için erişimci 'User.gameclaim_set' ile ilgili alanla çakışıyor. 'Davacı' tanımına related_name bağımsız değişkeni ekleyin.

Hataları neden aldığımı ve bunları nasıl düzeltebileceğimizi açıklayabilir misiniz?


Bu hata mesajları gerçekten iyi. Onları nasıl düzelteceklerini zaten açıklıyorlar. Ve ** [ related_namedokümantasyonda] ** ( docs.djangoproject.com/en/dev/ref/models/fields/#arguments ) üzerine okumak neden ortaya çıktıklarını açıklayacaktır.
Lutz Prechelt

Yanıtlar:


294

Kullanıcı için iki yabancı anahtarınız var. Django, Kullanıcı'dan GameClaim'e otomatik olarak ters bir ilişki oluşturur gameclaim_set. Bununla birlikte, iki FK'niz gameclaim_setolduğu için, açıkça imkansız olan iki özelliğiniz olacaktır . Bu nedenle, Django'ya ters ilişki için hangi ismi kullanacağınızı söylemeniz gerekir.

related_nameFK tanımındaki niteliği kullanın . Örneğin

class GameClaim(models.Model):
    target = models.ForeignKey(User, related_name='gameclaim_targets')
    claimer = models.ForeignKey(User, related_name='gameclaim_users')
    isAccepted = models.BooleanField()

49
İyi cevap, ama kabalıktan kaçınmakta başarılı olduğunuzu düşünmüyorum: P django'nun dahili olarak nasıl çalıştığının farkında değilseniz "neden" açık değil.
Kenny

14
Sadece çerçeveyi öğrenen biri için bu belli olmaz.
jkyle

3
Teşekkürler, hata mesajı da benim için açık değildi, ama ters ilişki hakkında açıklamanız çok yardımcı oldu.
ruquay

1
Çatışma iyi bir grup olduğundan, onları özellikle açıklayıcı bir hata mesajı
yapmaz

7
Ayrıca, tüm modeller için ters ilişkileri kullanmanız gerekmediği de belirtilmelidir. Bazı durumlarda model ilişkisinin tek yönlü olmasını isteyebilirsiniz. Bu durumda related_name = '+' kullanırsınız. Bu, Django'ya tek yönlü bir ilişki oluşturmasını ve ters ilişkiyi görmezden gelmesini söyler.
Tommy Strand

8

UserModel aynı ada sahip iki alan, bir tane oluşturmaya çalışıyor GameClaimskabul ettiklerini Userolarak targetve başka GameClaimso var Userolarak claimer. İşte belgeler üzerinderelated_name otomatik olarak oluşturulan olanları çelişmeyen böylece özelliklerin adlarını set izin vermenin Django'nın yolu olan.


7

OP soyut bir temel sınıf kullanmıyor ... ama eğer öyleyse, FK'de related_name kodlamanın zor olduğunu göreceksiniz (örneğin ..., related_name = "myname") bu çatışma hatalarına yol açacaktır. - temel sınıftan devralınan her sınıf için bir tane. Aşağıda verilen bağlantı, basit ancak kesinlikle açık olmayan geçici çözümü içermektedir.

Django belgelerinden ...

Bir ForeignKey veya ManyToManyField üzerinde related_name özniteliğini kullanıyorsanız, alan için her zaman benzersiz bir ters ad belirtmeniz gerekir. Bu normalde soyut temel sınıflarda soruna neden olur, çünkü bu sınıftaki alanlar alt sınıfların her birine dahil edilir ve her seferinde öznitelikler (related_name dahil) için tam olarak aynı değerlere sahiptir.

Daha fazla bilgi burada .


2

Bazen ekstra biçimlendirme kullanmanız gerekir related_name - aslında, kalıtımın kullanıldığı her zaman.

class Value(models.Model):
    value = models.DecimalField(decimal_places=2, max_digits=5)
    animal = models.ForeignKey(
        Animal, related_name="%(app_label)s_%(class)s_related")

    class Meta:
        abstract = True

class Height(Value):
    pass

class Weigth(Value):
    pass

class Length(Value):
    pass

Burada çakışma yok, ancak related_name bir kez tanımlandı ve Django benzersiz ilişki adları oluşturmaya özen gösterecek.

Değer sınıfındaki çocuklarda şunlara erişebilirsiniz:

herdboard_height_related
herdboard_lenght_related
herdboard_weight_related

0

Örneğin, aşağıdaki yapı göz önüne alındığında, bir django projesine bir uygulama olarak bir alt modül eklediğim zaman bu rastlamak gibi görünüyor:

myapp/
myapp/module/
myapp/module/models.py

Aşağıdakileri INSTALLED_APPS öğesine eklersem:

'myapp',
'myapp.module',

Django, myapp.mymodule models.py dosyasını iki kez işliyor gibi görünüyor ve yukarıdaki hatayı atıyor. Bu, ana modülü INSTALLED_APPS listesine dahil etmeyerek çözülebilir:

'myapp.module',

Dahil myappyerinemyapp.module bu gibi görünüyor, bu yüzden tüm veritabanı tabloları yanlış adları ile oluşturulacak nedenlere bunu yapmak için doğru yol olarak.

Bu soruna bir çözüm ararken bu yazıyla karşılaştım, bu yüzden buraya koyacağımı düşündüm :)


0

Sadece Ürdün'ün cevabına ekleyerek (Ürdün ipucu için teşekkürler), uygulamaların üstündeki seviyeyi içe aktarırsanız ve ardından uygulamaları örn.

myproject/ apps/ foo_app/ bar_app/

Yani uygulamaları, foo_app ve bar_app içe aktarıyorsanız, bu sorunu alabilirsiniz. Tüm ayarlarda listelenen uygulamalar, foo_app ve bar_app'ım vardı.STALLED_APPS

Yine de uygulamaları içe aktarmaktan kaçınmak istersiniz, çünkü o zaman aynı uygulama 2 farklı ad alanında yüklüdür

apps.foo_app ve foo_app

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.