如何将数据(即特定模型字段值)从Mezzanine Displayable模型迁移到新的自定义Mezzanine Page模型?

时间:2015-09-11 19:05:03

标签: python django mezzanine

我正在升级旧的Django / Mezzanine项目,需要将旧的Displayable模型(Job)转换为Page模型(JobPage)。

Job模型如下所示:

class Job(Displayable):
    job_title = models.CharField(max_length=300)
    job_type = models.IntegerField(choices=job_values.TYPES)
    location = models.IntegerField(choices=job_values.LOCATION)
    job_group = models.IntegerField(choices=job_values.GROUPS)

    job_description = RichTextField(blank=True, null=True)
    job_qualifications = RichTextField(blank=True, null=True)

    contact_name = models.CharField(max_length=200, blank=True, null=True)
    contact_attach = models.CharField(max_length=500, blank=True, null=True)
    contact_email = models.EmailField()

    def __unicode__(self):
        return self.job_title

    @property
    def job_id_on_page(self):
        return slugify(self.job_title)

    def get_page_slug(self):
        return "/%s#%s" % (job_values.URLS[self.job_group],     self.job_id_on_page)

    def get_absolute_url(self):
        return self.get_page_slug()

   def save(self, *args, **kwargs):
        self.title = self.job_title
        self.slug = "job-listing/%s" % slugify(self.job_title)

我创建了Job Page模型,如下所示:

class JobPage(Page):
    job_title = models.CharField(max_length=300)
    job_type = models.IntegerField(choices=job_values.TYPES)
    location = models.IntegerField(choices=job_values.LOCATION)
    job_group = models.IntegerField(choices=job_values.GROUPS)

    job_description = RichTextField(blank=True, null=True)
    job_qualifications = RichTextField(blank=True, null=True)

    contact_name = models.CharField(max_length=200, blank=True, null=True)
    contact_attach = models.CharField(max_length=500, blank=True, null=True)
    contact_email = models.EmailField()

    def save(self, *args, **kwargs):
        self.title = self.job_title
        self.slug = "job-listing/%s" % slugify(self.job_title)

        super(JobPage, self).save(*args, **kwargs)

    def __unicode__(self):
        return self.job_title

并跑了:

python manage.py makemigratons
python manage.py migrate

我传输数据的策略是进行Django数据迁移(看到我正在使用Mezzanine 4+和Django 1.8并且不推荐使用灯具):

python manage.py makemigrations --empty jobapp

我进入jobapp/migrations,打开空迁移,然后输入以下内容:

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

from django.db import models, migrations

from mezzanine.utils.urls import slugify

def dump_into_jobpage(apps, schema_editor):
    Job = apps.get_model('jobapp','Job')
    JobPage = apps.get_model('jobapp','JobPage')

    fields = ['job_title', 'job_type', 'location', 'job_group',
              'job_description', 'job_qualifications', 'contact_name',
              'contact_attach', 'contact_email']
    site_id = JobPage._meta.get_field('site_id')
    data_dict = {"site_id":1}

    for j in Job.objects.all():
        for field in fields:
            try:
                value = getattr(j, field)
                data_dict[field] = value
            except:
                pass

        data_dict['title'] = data_dict['job_title']
        data_dict['slug'] = 'job-listing/%s' %     slugify(data_dict['job_title'])

        JobPage(**data_dict).save()

class Migration(migrations.Migration):

dependencies = [
        ('jobapp', '0028_jobpage'),
    ]

    operations = [
        migrations.RunPython(dump_into_jobpage)
    ]
然后我跑了:

python manage.py migrate

并进入:

python manage.py shell

检查所有正确迁移的数据,包括原生Page slug字段(稍后会导致问题)。我成功打印了slug模型的所有Job Page字段。

问题在我runserver开始,转到管理页面,然后尝试点击'页面'所以我可以看到一切顺利进行。当然,它并没有顺利进行。我收到以下错误:

Error during template rendering

**In template /home/vagrant/.virtualenvs/newcorpsite/local/lib/python2.7/site-packages/mezzanine/pages/templates/admin/pages/page/change_list.html, error at line 40**
'NoneType' object has no attribute 'replace'
30                  <option value="{{ model.add_url }}">{{ model.meta_verbose_name|capfirst }}</option>
31                  {% endif %}
32              {% endfor %}
33          </select> 
34      </div>
35      {% endif %}
36  
37      {% if cl.result_count == 0 %}
38      <p class="paginator">0 {{ cl.opts.verbose_name_plural }}</p>
39      {% else %}
40  
          **<div id="tree">
             {% page_menu "pages/menus/admin.html" %}
          </div>**

41      {% endif %}
42  
43  </div>
44  {% endblock %}

追溯到:

self.html_id = self.slug.replace("/","-")

所以基本上没有slug字段用于JobPage中的一个或多个,即使我只是在PYTHON SHELL中看到了塞子属性。

我对这个有点疯狂。任何人都知道为什么这些字段值不会粘住?

1 个答案:

答案 0 :(得分:0)

我上面发布的代码是在尝试弄清楚如何执行此操作的许多失败迭代之后创建的。在那些失败的迭代期间,我将JobPage模型添加到数据库中,然后再次将其删除几次,因为我遇到了不同的错误并尝试了不同的字段和字段类型。显然,当您删除页面模型时,其对象不会从<your_app>.pages_page数据库中消失(pages_page是Mezzanine Page模型数据库)。它反而留下旧条目。如果您然后直接删除其中一个对象:

Page.objects.get(field=value).delete()

或删除/不填写字段,该对象实际上不会消失,而是留下null / None数据库条目。但是,Page对象会保留其id字段。我不知道我是否在某个地方出现了奇怪的设置,如果它是夹层的东西,或者它是一个Django的东西,但那就是失败了。我收到了NoneType错误,因为Mezzanine在Page数据库中看到pages_page的条目,并尝试在管理员菜单中为其创建项目。很棒,除了该页面的所有条目都是None。我无法删除python shell中的None对象,因为我收到错误Cannot use None as a query value,但我可以打印单个id,将其写下来,然后手动删除使用Page的{​​{1}} shell中的mysql个对象。

此时,我能够使用上面的所有代码成功创建新的id

另一个警告,我不得不将此迁移添加到JobPage模型,因为通过Django数据迁移创建它们并没有填充JobPage字段:

content_model

如果没有# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations def update_jobpage(apps, schema_editor): JobPage = apps.get_model('jobapp','JobPage') JobPage.objects.all().update(content_model='jobpage') class Migration(migrations.Migration): dependencies = [ ('jobapp', '0029_auto_20150911_1624'), ] operations = [ migrations.RunPython(update_jobpage) ] 字段,Mezzanine就无法使用其内置的content_model函数来确定自定义内容类型(在本例中为get_content_model(),其转换为{{1}它试图放在Admin菜单上的JobPage是基于的。因此它会抛出错误并阻止您使用该页面。

我在这里错过了什么吗?当我删除模型时,为什么旧​​的jobpage条目没有消失?为什么直接在Python中删除它们会留下Page对象,所以我不得不在MySQL中手动删除它们?