28 Mayıs 2014 Çarşamba

Django iç içe model kullanımına izin vermektedir. Bu konuya Model Admin Seçenekleri başlıklı yazıda değinilmiştir. Ama burada tekrar hatırlatalım. Örneğin elimiz de şöyle iki model bulunduğunu varsayalım.
class Exam(models.Model):
    name = models.CharField(max_length=100, verbose_name="Exam Name ")

    def __unicode__(self):
        return self.name

class Question(models.Model):
    question = models.TextField(verbose_name="Question Title ")
    exam = models.ForeignKey(Exam, verbose_name="Question Exam ")

    def __unicode__(self):
        return self.question
Sınav ve Soru olmak üzere iki adet modelimiz var. Ve aralarında gördüğünüz gibi ForeignKey ilişkisi bulunmaktadır. Yani bir Sınav birden fazla soruya sahip olabilmektedir. İşte biz burada admin.py dosyası içerisinde inline seçeneğini kullanarak sınav eklerken aynı zamanda sınava ait soruları da ekleyebiliyoruz. Bunun için admin.py dosyası içerisinde şu kodları yazmalıyız.
class QuestionInline(admin.StackedInline):
    model = Question
    inlines = (AnswerInline,)


class ExamAdmin(admin.ModelAdmin):
    inlines = [
        QuestionInline
    ]
admin.site.register(Exam, ExamAdmin)
Bu tanımaları yaptıktan sonra artık bir sınav eklerken aynı zamanda sorularını da ekleyebilirsiniz.
Bunun yanında soruların da cevapları olacaktır. Django bu şekilde iç içe birden fazla modelin kullanılmasını kendi admin'i ile sağlamıyor. Bu yüzden başka bir uygulama kullanmamız gerekiyor. Bu yazının asıl amacı da bu uygulamanın kullanımını göstermek. Django nested inlines'i indirmek için https://github.com/Soaa-/django-nested-inlines adresine gidiyoruz.
İsterseniz indirerek kurabilirsiniz. Biz kendi uygulamamız içerisine kuracağız. Bunun için uygulamanın ana dizininde iken şu komutu verin.
pip install -e git+git://github.com/Soaa-/django-nested-inlines.git#egg=django-nested-inlines
Bu komutu verdikten sonra uygulama dizini içerisinde src adında bir dizin oluşacak ve içerisinde de nested-inlines bulunacaktır. İlk önce uygulamayı projemize dahil etmeliyiz. Bunun için settings.py dosyası içerisinde INSTALLED_APPS demetinde 'django.contrib.admin''den önce uygulamayı dahil ediyoruz.
INSTALLED_APPS = (
    'nested_inlines',
    'django.contrib.admin',
...
)
Artık kullanabiliriz. Modellerimiz şu şekilde.
class Exam(models.Model):
    name = models.CharField(max_length=100, verbose_name="Exam Name ")

    def __unicode__(self):
        return self.name

class Question(models.Model):
    question = models.TextField(verbose_name="Question Title ")
    exam = models.ForeignKey(Exam, verbose_name="Question Exam ")

    def __unicode__(self):
        return self.question


class Answer(models.Model):
    answer = models.CharField(max_length=300,verbose_name="Question answer ")
    question = models.ForeignKey(Question, verbose_name="Answer Question ")

    def __unicode__(self):
        return self.answer

Sınav içerisinde sınava ait soruları ve bu sorulara ait cevapları ekleyebileceğiz. Bunun için admin.py dosyasına şu kodları yazıyoruz.
from nested_inlines.admin import NestedModelAdmin, NestedStackedInline, NestedTabularInline

class AnswerInline(NestedTabularInline):
    model = Answer

class QuestionInline(NestedStackedInline):
    model = Question
    inlines = (AnswerInline,)

class ExamAdmin(NestedModelAdmin):
    inlines = [
        QuestionInline
    ]

admin.site.register(Exam, ExamAdmin)
Bu işlemleri yaptıktan sonra sınavı kaydederken hata alabilirsiniz. Eğer hata alırsanız src/django-nested-inlines/nested_inlines/templates/admin/edit_inline/ yolunu takip ederek dizini açınız. Dizin içerisinde stacked.html,tabular.html adında iki dosya bulunmaktadır. Bu dosyalar içerisini açınız ve şu satırı bulunuz.
{% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
Bu satırı şu silerek yerine şu satırı yazınız.
{% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
Sorunun düzelmiş olması gerekiyor. Şimdi kullanabilirsiniz. Kaynakça

1 yorum :