我正在升级旧的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中看到了塞子属性。
我对这个有点疯狂。任何人都知道为什么这些字段值不会粘住?
答案 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中手动删除它们?