【问题标题】:How to handle a legacy database in the Django framework如何在 Django 框架中处理遗留数据库
【发布时间】:2021-01-16 13:46:10
【问题描述】:

我正在开发一个需要访问一个非常大的 (MySQL) 数据库的 Django 应用程序,该数据库没有任何外键。我需要对多个表进行查询。我这样做的方式非常低效,并且涉及到多个循环:

{% for flower in especies_id %}
    <td>{{flower.especies}}</td>
    {% for family in family_id %}
        {% if family.family_id == flower.family_id %}
                <td><a class="nav-item active" href="/home">
                {{family.family_name}}</td></a>
        {% endif %}
    {% endfor %}
{% endfor %}

有没有办法用 Django shell 或者 JavaScript 来处理这个数据库?还是完全重构数据库?

(编辑): 数据库有〜3000个条目 两个表之间的关系是使用一个附加的: flower2estate,其中包含 Estate_id、flower_id

模型.py:

    class Listflower(models.Model):
       
        especies_id = models.AutoField(primary_key=True)
        family_id = models.IntegerField(blank=True, null=True)
        especies = models.CharField(max_length=255, blank=True, null=True)
        
    
        class Meta:
            managed = False
            db_table = 'listflower'

class Estate(models.Model):
    estate_id = models.AutoField(primary_key=True)
    estate_name = models.CharField(max_length=100, blank=True, null=True)
 

    class Meta:
        managed = False
        db_table = 'estates'

class Flower2Estate(models.Model):
        estate_id = models.IntegerField(primary_key=True)
        especies_id = models.IntegerField()
    
        class Meta:
            managed = False
            db_table = 'flower2estate'
            unique_together = (('estado_id', 'especie_id'),)

Views.py:

def flowers(request):
    list_flower = ListFlower.objects.all().order_by('especies_id')
    paginator = Paginator(list_flower, 3)
    page = request.GET.get("page")
    try:
        flowers = paginator.page(page)
    except PageNotAnInteger:
        flowers = paginator.page(1)
    except EmptyPage:
        flowers= paginator.page(paginator.num_pages)
    return render(request, 'accounts/flowers.html', {'page':page,"flowers" 

:flowers,"especies_id":flowers})

我需要获取“花”和相应的“庄园”,而无需在 3000 个条目之间循环。

【问题讨论】:

  • 请展示你的模型和你的观点。你循环的列表有多大?
  • 当然,也许,取决于!我们需要更多地了解您正在使用的内容才能说出来。 Django通常可以处理,但可能并不容易。
  • 添加了包含信息的编辑,谢谢

标签: python mysql django database web


【解决方案1】:

您可以向遗留模型添加一些方法来更有效地检索相关项目:

class Listflower(models.Model):
    especies_id = models.AutoField(primary_key=True)
    family_id = models.IntegerField(blank=True, null=True)
    especies = models.CharField(max_length=255, blank=True, null=True)
    

    class Meta:
        managed = False
        db_table = 'listflower'

    def get_family(self):
        return FamilyModel.objects.get(family_id=self.family_id)


class Estate(models.Model):
    estate_id = models.AutoField(primary_key=True)
    estate_name = models.CharField(max_length=100, blank=True, null=True)
 

    class Meta:
        managed = False
        db_table = 'estates'

    def get_flowers(self):
        flower_ids = Flower2Estate.objects.filter(estate_id=self.estate_id).values_list('especies_id', flat=True)
        return Listflower.objects.filter(especies_id__in=flower_ids)

但是,如果这不是您最后一次使用这些数据,那么更好的方法是使用 fks 定义常规 django 模型并编写一次脚本以将遗留数据转换为新的模型结构。挑战不应超过一个小时。

更新

class FlowerFamily(models.Model):
    # assuming you old family model has 
    # "family_id" and "family_name" fields
    family_id = models.IntegerField(blank=True, null=True)
    family_name = models.CharField(max_length=255, blank=True, null=True)


class Flower(models.Model):
    # you might want preserve old model fields in the new model
    # at least id fields
    especies_id = models.IntegerField(blank=True, null=True)
    family_id = models.IntegerField(blank=True, null=True)
    especies = models.CharField(max_length=255, blank=True, null=True)

    family = models.ForegnKey(FlowerFamily, related_name='flowers')


class NewEstate(models.Model):
    estate_id = models.IntegerField(blank=True, null=True)
    estate_name = models.CharField(max_length=100, blank=True, null=True)
    flowers = models.ManyToManyField(Flower, related_name='estates')




# this is a slightly primitive example
# in real life you might want to use get_or_create instead of direct creation 
# in case script fails and you'll need to run it again
# also objects.get() might better be used with try-except ObjectDoesNotExist
def convert_legacy():
    # create new instances
    for ff in YourOldFamilyModel.objects.all():
        new_ff = FlowerFamily(family_id=ff.family_id, family_name=ff.family_name)
        new_ff.save()

    for fl in Listflower.objects.all():
        new_fl = Flower(...)

        family = FlowerFamily.objects.get(family_id=fl.family_id)

        new_fl.family = family
        new_fl.save()
    
    # same thing for Estate
    for ...:
        new_estate ...
        new_estate.save()

        # and restore relations
        flower_ids = Flower2Estate.objects.filter(estate_id=new_estate.estate_id).values_list('especies_id', flat=True)

        for new_lf in Flower.objects.filter(especies_id__in=flower_ids):
            new_estate.flowers.add(new_fl)
        
    
    

【讨论】:

  • 感谢您的回答。数据库已经加载得更快了。关于脚本我从哪里开始,你能给我指点吗?
  • 这太棒了!现在正在做测试,可能会使用try catch,完成后我会更新谢谢!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-17
  • 2012-10-14
  • 1970-01-01
  • 2013-08-07
  • 2016-02-15
  • 2015-10-27
相关资源
最近更新 更多