问题说明
你好,当我试图从另一个类继承时,在保存多对多字段时遇到了一些问题。我覆盖了扩展了"Banner"类的"CharacterBanner"类的保存函数。我尝试创建并保存一个新的Banner示例,以便可以将CharacterBanner指向新创建并保存的示例。目前的主要问题是父类的ID(横幅)没有被生成,即使它正在保存,所以我不能正确地添加一个指针到字符横幅。其他字段正在正确地保存。
另外,即使我可以得到一个id,我也不确定如何将CharacterBanner指针分配给我创建的Banner。这就是为什么我在数据库中同时设置了banner_ptr和banner_ptr_id。当我迁移时,它似乎确实期望banner_ptr_id。
代码
我有一个"Banner"模型,希望它包含以下字段
CHARACTER = "Character"
WEAPON = "Weapon"
BANNER_TYPE = [(CHARACTER, "Character"), (WEAPON, "Weapon"),]
class Banner(models.Model):
name = models.CharField(max_length = 64)
enddate = models.DateField()
banner_type = models.CharField(max_length = 64,choices=BANNER_TYPE)
我还有一个"CharacterBanner"模型,它将Banner模型作为父模型。
网站models.py
class CharacterBanner(Banner):
rateups = models.ManyToManyField(Character,blank=True)
banner_ptr = models.OneToOneField(
Banner, on_delete=models.CASCADE,
parent_link=True,
primary_key=True,
)
def save(self, *args, **kwargs):
self.banner_type = "Character"
if not self.id:
newBanner = Banner(name=self.name, enddate=self.enddate,banner_type = self.banner_type)
print(newBanner.id)
newBanner.save()
super(Banner, newBanner).save(*args, **kwargs)
print(newBanner.id)
# self.banner_ptr = newBanner
self.banner_ptr_id = newBanner.id
super(CharacterBanner,self).save(*args, **kwargs)
在这种情况下,两个打印都是"无"。
我有另一个类叫"WeaponBanner",它的多对多模型有"Weapons",我需要能够从一个单一类型的模型Banner中查询WeaponBanner和CharacterBanner。因此,将Banner作为一个抽象类(以我目前的理解)是行不通的,并且通常是我不想追求的解决方案。我不知道是否有某种方法可以实现OneToOne字段。
网站forms.py
def save(self, commit=True):
cleaned_data = super().clean()
if not commit:
raise NotImplementedError("Can't create object without database save")
rateups = cleaned_data.get('rateups')
kwargs = {'name': cleaned_data.get('name'), 'enddate': cleaned_data.get('enddate')}
character_banner = self.Meta.model(**kwargs)
print("ptr_id", character_banner.banner_ptr_id)
character_banner.save()
character_banner.rateups.set(rateups)
print(character_banner)
character_banner.save()
return character_banner
网站views.py
def post(self, request,*args, **kwargs):
context ={}
form = self.form_class(request.POST)
if form.is_valid():
form.save()
return redirect(to=self.success_url)
我不认为观点在这里很重要,但无论如何我会包括它
下面是我为相关类创建表的方法:
CREATE TABLE IF NOT EXISTS analyze_banner (
id INT PRIMARY KEY,
name TEXT,
enddate DATE,
banner_type TEXT
);
CREATE TABLE IF NOT EXISTS analyze_characterbanner(
banner_ptr INT,
banner_ptr_id INT
);
CREATE TABLE IF NOT EXISTS analyze_characterbanner_rateups(
id INT PRIMARY KEY,
characterbanner INT,
character_id INT
);
我目前有banner_ptr和banner_ptr_id,因为在迁移时,我知道系统需要banner_ptr_id列,而当我尝试修复www.example.com中的问题时,系统似乎需要banner_ptr列。models.py it seems to want a banner_ptr column.
输出
我尝试在CharacterBanner的覆盖保存功能中创建一个Banner,这样我就可以创建一个Banner,并使banner_ptr指向该newBanner。但是,当我打印www.example.com时,在我保存之前和之后都是None。我不确定ID是如何生成的,但我认为要生成Banner ID,我需要创建并保存Banner,然后在保存后生成ID。newBanner.id it is None before and after I save. I am unsure how ids are generated but I thought that to generate a Banner id I would need to create and save a Banner then after saving the id would be generated.
未注解的自身。横幅_ptr =新横幅:
ValueError: save() prohibited to prevent data loss due to unsaved related object 'banner_ptr'
我在模型中没有banner_ptr的字段,但是在最近的一系列更改之前,我没有这个字段。我还没有添加banner_ptr模型字段,因为我不知道它应该是什么样子,但是我在数据库中有一个banner_ptr列。
在这种情况下,在数据库中查找生成的Banner,它被保存,但ID、名称和结束日期字段为空。同时banner_type被分配(具有正确的值)。
自我评论。横幅_ptr =新横幅:
"<CharacterBanner: >" needs to have a value for field "banner_ptr" before this many-to-many relationship can be used.
另一个错误似乎是对上面的错误的补充,因为它抱怨需要分配banner_ptr。
在这种情况下,在数据库中查找生成的横幅,它被保存(非空字段的正确值),但只有ID为空字段。此外,每次它被保存3次。我认为这与此有关:
newBanner.save()
super(Banner, newBanner).save(*args, **kwargs)
其他Stackexchange帖子,我发现是接近我的:
Django ManyToMany model validation-似乎没有太大帮助
ValueError [Object] needs to have a value for field "item_ptr" before this many-to-many relationship can be used-似乎非常相关,但解决方案没有帮助。我假设newItem创建是无效的,所以ptr指向无。这肯定是我的情况,但clean函数似乎不是问题,因为除了id之外,每个字段都被正确分配。
https://forum.djangoproject.com/t/django-save-prohibited-to-prevent-data-loss-due-to-unsaved-related-object-predictions/17730/3-这一个只是使它与评论的评论相同
https://forum.djangoproject.com/t/django-save-prohibited-to-prevent-data-loss-due-to-unsaved-related-object-predictions/17730/10-似乎没有帮助,因为我们只需要使用commit false保存,因为
当然,我已经尝试和修补这些文章中给出的解决方案,以最好的我的能力,但我不能让他们中的任何工作。
溶液概要
我尝试过使用各种不同的手动生成的表,这些表具有不同的名称,我尝试过许多不同的方法来保存信息并将其提供给Banner类。
我希望手动生成的父类在保存后有一个ID,但它没有。
另一个问题可能是横幅上的字符域。虽然因为它被正确地保存到数据库中,我不认为这是问题所在。
这可能完全是一个数据库问题,但当我尝试删除数据库并迁移时,它仍然抱怨表不存在(即使这曾经对我有效)。这就是为什么我如上所述手动创建表的原因。
1条答案
按热度按时间ffscu2ro1#
在此找到以下解决方案:https://stackoverflow.com/a/60360715/20995582
我决定尝试一下,看看我是否真的可以重置数据库,让它工作,即使它不工作。https://stackoverflow.com/users/2487835/lex-podgorny的解决方案为我工作。
通过以下步骤使其工作:
第0步是做一个固定装置,这样你所有的相关数据都可以恢复。另外,如果你是生产,不能删除数据库,这是行不通的。
1.删除migrations文件夹并将其替换为仅包含空init. py的migrations文件夹
1.删除数据库sqlite3
1.这是我错过的一步: 在您正在更改的应用程序的www.example.com中,注解掉
from . import views
或从任何应用程序视图导入的任何内容。此外,注解掉该内容,以便urlpatterns为空列表。urls.py of the app(s) you are changing, comment outfrom . import views
or anything that imports from the view of any app. Additionally comment out so that urlpatterns is an empty list.1.载入夹具(如果已创建)