Memperbarui hanya bidang tertentu dalam model.Model

92

Saya punya model

class Survey(models.Model):
    created_by = models.ForeignKey(User)
    question = models.CharField(max_length=150)
    active = models.NullBooleanField()
    def __unicode__(self):
        return self.question

dan sekarang saya hanya ingin memperbarui activebidang. Jadi saya melakukan ini:

survey = get_object_or_404(Survey, created_by=request.user, pk=question_id)
survey.active = True
survey.save(["active"]) 

Sekarang saya mendapatkan kesalahan IntegrityError: PRIMARY KEY must be unique.

Apakah saya benar dengan metode pembaruan ini?

Pengguna Terdaftar
sumber

Jawaban:

187

Untuk memperbarui subset bidang, Anda dapat menggunakan update_fields:

survey.save(update_fields=["active"]) 

The update_fieldsArgumen ditambahkan dalam Django 1,5. Di versi sebelumnya, Anda dapat menggunakan update()metode ini:

Survey.objects.filter(pk=survey.pk).update(active=True)
Alasdair
sumber
17

Biasanya, cara yang benar untuk memperbarui bidang tertentu dalam satu atau lebih contoh model adalah dengan menggunakan update()metode pada queryset masing-masing. Kemudian Anda melakukan sesuatu seperti ini:

affected_surveys = Survey.objects.filter(
    # restrict your queryset by whatever fits you
    # ...
    ).update(active=True)

Dengan cara ini, Anda tidak perlu memanggil save()model Anda lagi karena akan disimpan secara otomatis. Selain itu, update()metode ini mengembalikan jumlah contoh survei yang terpengaruh oleh pembaruan Anda.

pemistahl
sumber
2
Terima kasih. Saya mencobanya dengan .getalih - alih .filterdan ini tidak berhasil. Tetapi dengan filter itu berfungsi dengan baik. Tahukah Anda apa yang salah dengan kode saya di atas?
Pengguna Terdaftar
Masalah Anda mungkin terkait dengan question_id. Dari mana asalnya nilai ini? Dan baris mana yang menaikkan IntegrityError?
pemistahl
question_idberasal dari url (?P<question_id>\d+). Kesalahan saya adalah bahwa pada server kerja, django 1.4 diinstal dan kode saya 1.5. Tetapi dengan kode Anda, itu berfungsi dengan baik.
Pengguna Terdaftar
2
@RegisteredUser, sepertinya tidak ada metode "update" pada objek, hanya pada queryset. Saat Anda menggunakan .filter (), Anda mendapatkan queryset (menahan nol atau lebih objek) kembali. Saat Anda menggunakan .get () Anda mendapatkan satu objek.
mgojohn
Secara default, memanggil save()(@Alasdair solution) adalah solusi yang lebih aman, karena metode ini dapat memicu hal-hal seperti validasi, atau kode kustom apa pun, daripada yang update()tidak.
David D.