2017-06-10 25 views
6

Tôi có một mô hình Django (gọi là BiomSearchJob) hiện đang hoạt động và tôi muốn thêm mối quan hệ nhiều-nhiều mới để làm cho hệ thống có thể tùy chỉnh hơn cho người dùng. Trước đây, người dùng có thể gửi một công việc mà không chỉ định một tập hợp các TaxonomyLevelChoices nhưng để thêm nhiều tính năng hơn cho hệ thống, người dùng bây giờ có thể chọn mức phân loại riêng của họ.Retroactively đặt giá trị mặc định ManyToManyField mới thành kiểu hiện tại

Dưới đây là mô hình:

class TaxonomyLevelChoice(models.Model): 
    taxon_level = models.CharField(
     verbose_name="Taxonomy Chart Level", max_length=60) 
    taxon_level_proper_name = models.CharField(max_length=60) 

    def __unicode__(self): 
     return self.taxon_level_proper_name 

class BiomSearchJob(models.Model): 
    ... 
    # The new many-to-many relation 
    taxonomy_levels = models.ManyToManyField(
     'TaxonomyLevelChoice', blank=False, max_length=3, 
     default=["phylum", "class", "genus"]) 

    name = models.CharField(
     null=False, blank=False, max_length=100, default="Unnamed Job", 
     validators=[alphanumeric_spaces]) 
    ... 

Hiện nay, tất cả BiomSearchJobs ngầm có ba cấp độ phân loại hiện niêm yết trong thời gian default= (mà không phải là người sử dụng có thể lựa chọn) và do đó đều như nhau trong cơ sở dữ liệu. Sau khi chạy migrate, tôi thấy rằng các công việc trước đó không ngay lập tức có ba quan hệ phân loại cấp, chúng chỉ trả lại một tập rỗng khi gọi job.taxonomy_levels.all() (nếu job là một phiên bản BiomSearchJob).

Có cách nào để thêm lại mối quan hệ này một cách hiệu quả mà không cần phải thực hiện mọi thứ theo cách thủ công không? Lý tưởng nhất là, chỉ cần chạy migrate Tôi muốn có BiomSearchJobs hiện có để có phylum, classgenus được liệt kê trong thuộc tính taxonomy_levels.

Trả lời

7

Tôi nghĩ bạn đang tìm kiếm di chuyển dữ liệu, đó là di chuyển cho phép thay đổi dữ liệu chỉ trên cơ sở dữ liệu.

Bạn có thể tạo ra nó theo cách này:

python manage.py makemigrations <your app> --name=retroactively_add_levels 

Sau đó chèn mã này vào tệp di cư vừa tạo:

# -*- coding: utf-8 -*- 
from __future__ import unicode_literals 

from django.db import migrations 


def add_taxonomy_levels(apps, schema_editor): 
    BiomSearchJob = apps.get_model('<your app>', 'BiomSearchJob') 
    TaxonomyLevelChoice = apps.get_model('<your app>', 'TaxonomyLevelChoice') 
    for job in BiomSearchJob.objects.all(): 
     for choice in TaxonomyLevelChoice.objects.filter(taxon_level_proper_name__in=["phylum", "class", "genus"]): 
      job.taxonomy_levels.add(choice) 

class Migration(migrations.Migration): 

    dependencies = [] 

operations = [ 
    migrations.RunPython(add_taxonomy_levels, reverse_code=migrations.RunPython.noop) 
] 

Nó hoạt động khá nhiều như một truy vấn SQL sẽ làm gì nhưng nó thúc đẩy trên Django ORM.

Hy vọng điều này sẽ hữu ích.

3

Cách tiếp cận của bạn không thể hoạt động, vì bạn ngầm muốn tạo truy vấn trên thuộc tính cá thể: Django không thể đoán được điều đó.

Từ Django's Doc, mặc định có thể là một chức năng, trong khi

Đối với các trường như ForeignKey rằng bản đồ để mô hình trường hợp, giá trị mặc định nên giá trị của lĩnh vực họ tham khảo (pk trừ to_field được thiết lập) thay vì mô hình trường hợp.

Vì vậy .... Bạn có thể chuyển mảng PK (ví dụ ID), hoặc bạn sử dụng hàm để nhận bộ truy vấn.

class TaxonomyLevelChoice(models.Model): 
    taxon_level = models.CharField(
     verbose_name="Taxonomy Chart Level", max_length=60) 
    taxon_level_proper_name = models.CharField(max_length=60) 

    def __unicode__(self): 
     return self.taxon_level_proper_name 

def get_default_taxonomy_levels(): 
    ... 
    return YourQuerySet 


class BiomSearchJob(models.Model): 
    ... 
    # The new many-to-many relation 
    taxonomy_levels = models.ManyToManyField(
     'TaxonomyLevelChoice', blank=False, max_length=3, 
     default=get_taxonomy_levels_default) 

    name = models.CharField(
     null=False, blank=False, max_length=100, default="Unnamed Job", 
     validators=[alphanumeric_spaces]) 
    ... 

Tôi đoán bạn sẽ gặp sự cố di chuyển nếu bạn di chuyển trước khi TaxonomyLevelChoice trường hợp chưa được tạo.

Tôi muốn tìm giải pháp hàm do câu trước, với một số phương pháp bộ nhớ cache giả, khi thực hiện truy vấn mỗi khi bạn tạo BiomSearchJob không phải là giải pháp có thể chấp nhận được.

tôi muốn làm:

DEFAULT_TAXONOMY_LEVELS = None 

def get_default_taxonomy_levels(): 
    if DEFAULT_TAXONOMY_LEVELS: 
     return DEFAULT_TAXONOMY_LEVELS 
    ... 
    DEFAULT_TAXONOMY_LEVELS = YourQuerySet 
    return YourQuerySet 

Edit: Theo câu hỏi là để retro-tích cực thiết lập một Nhiều người đến Nhiều giá trị mặc định, tôi muốn đề nghị một lệnh để làm như vậy trên trường hiện có, như tôi don không nghĩ rằng di cư sẽ xử lý điều đó cho bạn.

Các vấn đề liên quan