sqlite 继承类Django -手动创建的父类的ID即使在保存后也不会生成,子类的指针也不起作用

lrpiutwd  于 2023-03-03  发布在  SQLite
关注(0)|答案(1)|浏览(109)

问题说明

你好,当我试图从另一个类继承时,在保存多对多字段时遇到了一些问题。我覆盖了扩展了"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,但它没有。
另一个问题可能是横幅上的字符域。虽然因为它被正确地保存到数据库中,我不认为这是问题所在。
这可能完全是一个数据库问题,但当我尝试删除数据库并迁移时,它仍然抱怨表不存在(即使这曾经对我有效)。这就是为什么我如上所述手动创建表的原因。

ffscu2ro

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 out from . import views or anything that imports from the view of any app. Additionally comment out so that urlpatterns is an empty list.

  1. python www.example.com进行迁移 manage.py makemigrations
  2. python www.example.com迁移 manage.py migrate
  3. python www.example.com迁移-运行同步数据库 manage.py migrate --run-syncdb
    1.载入夹具(如果已创建)

相关问题