Varsayılan olmadan userprofile'a boş değer atanamayan bir 'new_field' alanı eklemeye çalışıyorsunuz


109

Django 1.7'den Güney veya başka bir geçiş sistemi kullanmama gerek olmadığını biliyorum, bu yüzden sadece basit komut kullanıyorum python manage.py makemigrations

Ancak, aldığım tek şey şu hata:

You are trying to add a non-nullable field 'new_field' to userprofile without a default;
we can't do that (the database needs something to populate existing rows).

İşte models.py:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    website = models.URLField(blank=True)
    new_field = models.CharField(max_length=140)

Seçenekler nelerdir?


3
Sorunun, yeni bir tablo oluştururken değil, mevcut tabloyu değiştirdiğinizde ortaya çıktığını eklemek istedim.
x-yuri

Yanıtlar:


93

Varsayılan bir değer sağlamanız gerekir:

new_field = models.CharField(max_length=140, default='SOME STRING')

Bir web sitesi alanının bir kopyasına new_field'a ihtiyacım olursa ne olur? Nasıl görünmeli? default = websiteişi yapmıyor
Irmantas Želionis

8
Taşımayı önce sahte bir varsayılan değerle yapmak, ardından her kayıt boyunca yinelemek ve olarak ayarlamak için bir veri geçişi oluşturmak istersiniz . new_fieldwebsite
dgel

varsayılan CharField için isteğe bağlı olmalıdır
Florent

90

Eğer erken gelişim döngüsünde ve umurumda değil , mevcut yaklaşık veritabanı verilerinin sadece çıkarın ve sonra geçirebilirsiniz. Ancak önce geçişler dizinini temizlemeniz ve satırlarını tablodan kaldırmanız gerekir (django_migrations)

rm  your_app/migrations/*

rm db.sqlite3
python manage.py makemigrations
python manage.py migrate

8
Bir şey daha. mysql -u[user] [database] -e "delete from django_migrations where app=[your_app]"
Geçiş

Yol budur. Django'nun göç ve model tespitinde vb. Berbat olduğunu düşünüyorum. Bunun için büyük bir güncelleme istiyorum.
WesternGun

Taşıma işlemlerinden tüm dosyaları sildim ve django_migrations'daki tüm satırları sildim ve şimdi çalıştırırken "django.db.migrations.exceptions.NodeNotFoundError: Geçiş hikayeleri.0001_initial bağımlılıklar varolmayan üst düğüme ('kaynaklar', '0002_auto_20180903_1224') referans veriyor göç.
brainLoop

1
Ayrıca __init__.py , geçişlerden silmediğinizden veya daha sonra geri yüklediğinizden emin olun , aksi takdirde makemigrasyonlar stackoverflow.com/a/46362750/1649917
nmu

python manage.py sqlmigrate name_of_your_app nb_of_the_migrationayrıca gereklidir
zar3bski

38

Seçeneklerden biri, 'new_field' için varsayılan bir değer belirtmektir:

new_field = models.CharField(max_length=140, default='DEFAULT VALUE')

başka bir seçenek de 'new_field'ı boş değer atanabilir alan olarak bildirmektir:

new_field = models.CharField(max_length=140, null=True)

"New_field" i null yapılabilir bir alan olarak kabul etmeye karar verirseniz "new_field" için geçerli girdi olarak "no input" u kabul etmek isteyebilirsiniz. O zaman blank=Trueifadeyi de eklemelisin :

new_field = models.CharField(max_length=140, blank=True, null=True)

null=TrueVe / veya ile bile, blank=Truegerekirse bir varsayılan değer ekleyebilirsiniz:

new_field = models.CharField(max_length=140, default='DEFAULT VALUE', blank=True, null=True)

7
«CharField ve TextField gibi dize tabanlı alanlarda null kullanmaktan kaçının. Dize tabanlı bir alanda null = True varsa bu, "veri yok" için iki olası değere sahip olduğu anlamına gelir: NULL ve boş dize. » - Model alanı referansı
Chema

7

Geliştirme döngüsünün başındaysanız, bunu deneyebilirsiniz -

Bu modeli ve tüm kullanımlarını kaldırın / yorumlayın. Taşıma işlemleri uygulayın. Bu, bu modeli siler ve ardından modeli tekrar ekler, geçişleri çalıştırır ve yeni alan eklenmiş temiz bir modeliniz olur.


Ve taşıma tablosunu django_migrations burada belirtildiği gibi temizleyin: stackoverflow.com/questions/26185687/… Veya sadece bir GUI kullanın ve gerekli satırları silin.
RusI

5

Herhangi birinin a ayarlaması durumunda ForeignKey, bir varsayılan ayarlamadan null yapılabilir alanlara izin verebilirsiniz:

new_field = models.ForeignKey(model, null=True)

Veritabanında zaten depolanan verileriniz varsa, varsayılan bir değer de ayarlayabilirsiniz:

new_field = models.ForeignKey(model, default=<existing model id here>)

4

"Web sitesi" boş olabilirse, boş olarak new_fieldda ayarlanmalıdır.

Şimdi new_field, "web sitesinden" değeri almak için eğer boşsa kaydetme üzerine mantık eklemek istiyorsanız, yapmanız gereken tek şey, aşağıdaki gibi kaydetme işlevini geçersiz kılmaktır Model:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    website = models.URLField(blank=True, default='DEFAULT VALUE')
    new_field = models.CharField(max_length=140, blank=True, default='DEFAULT VALUE')

    def save(self, *args, **kwargs):
        if not self.new_field:
            # Setting the value of new_field with website's value
            self.new_field = self.website

        # Saving the object with the default save() function
        super(UserProfile, self).save(*args, **kwargs)

3

İçinde zaten veri bulunan tabloya referans ekleyemezsiniz.
Değişiklik:

user = models.OneToOneField(User)

to:

user = models.OneToOneField(User, default = "")

yapmak:

python manage.py makemigrations
python manage.py migrate

tekrar değiştirin:

user = models.OneToOneField(User)

tekrar geçiş yapın:

python manage.py makemigrations
python manage.py migrate

2

New_file içinde boolean özelliğini null ekleyin.

new_field = models.CharField(max_length=140, null=True)

./manage.py syncdbDB'yi yenilemek için bir çalıştırdıktan sonra . ve sonunda koşuyorsun ./manage.py makemigrations ve./manage.py migrate



2

Tabloda zaten veritabanı girişleriniz var UserProfilemı? Eğer öyleyse, yeni sütunlar eklediğinizde, DB onu neye ayarlayacağını bilemez çünkü olamaz NULL. Bu nedenle, sütundaki bu alanları ne olarak ayarlamak istediğinizi sorar new_fields. Ben zorunda silmek sorunu çözmek için bu tablodan tüm satırları.

(Bunun bir süre önce yanıtlandığını biliyorum, ancak bu sorunla karşılaştım ve bu benim çözümümdü. Umarım bunu gören yeni herkese yardımcı olur)


1
Tabloya satır eklemedim ve hala bunu alıyorum. Tomasz'ın önerdiği gibi, modeli değiştirmek için tüm geçiş geçmişini silmem, geçiş tablosunu temizlemem gerekiyor.
WesternGun

1

Dürüst olmak gerekirse, bunu aşmanın en iyi yolu, ihtiyaç duyduğunuz ve biraz farklı adlandırılmış tüm alanlarla başka bir model oluşturmaktı. Taşıma işlemleri çalıştırın. Kullanılmayan modeli silin ve geçişleri yeniden çalıştırın. Voila.


1

Söz konusu modelin tablosunu kırpmakta sorun yaşıyorsanız, Nonebilgi isteminde bir defaya mahsus bir varsayılan değer belirtebilirsiniz . default=NoneKodunuzun varsayılanı yoksa taşıma işlemi gereksiz olacaktır . Tabloda artık varsayılan gerektiren veri olmadığı için gayet iyi uygulanabilir.


1

Geliştirme döngümün başındaydım, bu yüzden bu herkes için işe yaramayabilir (ama neden işe yaramadığını anlamıyorum).

blank=True, null=TrueHatayı aldığım sütunlara ekledim . Sonra koştumpython manage.py makemigrations komutu .

Bu komutu çalıştırdıktan hemen sonra (ve çalıştırmadan önce python manage.py migrate), blank=True, null=Truetüm sütunlardan kaldırdım . Sonra koştumpython manage.py makemigrations tekrar . Sadece sütunları kendim değiştirme seçeneği verildi, seçtim.

Sonra koştum python manage.py migrateve her şey yolunda gitti !


0

Django'nun aslında söylediği:

Userprofile tablosunun içinde veri var ve new_fieldboş değerler olabilir , ancak bilmiyorum, bu yüzden özelliği null yapılamaz olarak işaretlemek istediğinizden emin misiniz, çünkü eğer yaparsanız, NULL olan değerler varsa bir hata alabilirsiniz.

userprofileTablodaki değerlerden hiçbirinin NULL olmadığından eminseniz - serbest kaldı ve uyarıyı dikkate almayın.

Bu tür durumlarda en iyi uygulama, seçenek 2'de belirtildiği gibi boş değerleri işlemek için bir RunPython geçişi oluşturmaktır.

2) Şimdilik yoksay ve mevcut satırları NULL ile kendim işlememe izin ver (örneğin, önceki bir veri geçişinde NULL değerleri işlemek için bir RunPython veya RunSQL işlemi eklediğiniz için)

RunPython geçişinde UserProfile, boş new_fielddeğere sahip tüm örnekleri bulmanız ve oraya doğru bir değer (veya Django'nun sizden modelde ayarlamanızı istediği için varsayılan bir değer) koymanız gerekir. Bunun gibi bir şey alacaksın:

# please keep in mind that new_value can be an empty string. You decide whether it is a correct value.
for profile in UserProfile.objects.filter(new_value__isnull=True).iterator():
    profile.new_value = calculate_value(profile)
    profile.save() # better to use batch save

İyi eğlenceler!


Bunun belgelerde nerede yazıldığını bulamıyorum. Bağlantıyı gönderebilir misin lütfen
Cody

0

Models.py içinde

class UserProfile(models.Model): user = models.OneToOneField(User) website = models.URLField(blank=True) new_field = models.CharField(max_length=140, default="some_value")

Varsayılan olarak bazı değerler eklemeniz gerekir.


-1

SSH size 2 seçenek veriyorsa, 1 sayısını seçin ve "Hiçbiri" yazın. Sadece bu ... şu an için.

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.