1

I have an abstract model from which a couple of my main models are inherited. Main difficulty in this case is that I have a need in reference to the same model, like a ForeignKey to self. I have read that the ForeignKey is not possible in abstract models and GenericForeignKey can help, however I can`t really make it work.

As I understand structure should be something like following:

class BaseModel(models.Model):
    versions = GenericRelation('self')
    date_created = models.DateTimeField(default=datetime.datetime.now)
    is_deleted = models.BooleanField(default=False)

    content_type = models.ForeignKey(ContentType, blank=True, null=True)
    object_id = models.PositiveIntegerField(blank=True, null=True)
    content_object = GenericForeignKey('content_type', 'object_id')

class FirstModel(BaseModel):
    some_fields...

class AnotherModel(BaseModel):
    another_fields...

But with this approach I get an error:

>>> item1 = FirstModel.objects.get(id=1)
>>> item2 = FirstModel.objects.get(id=2)
>>> item2.content_object = item1
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/home/michael/.virtualenvs/diagspecgen/lib/python3.6/site-packages/django/contrib/contenttypes/fields.py", line 245, in __set__
    ct = self.get_content_type(obj=value)
  File "/home/michael/.virtualenvs/diagspecgen/lib/python3.6/site-packages/django/contrib/contenttypes/fields.py", line 163, in get_content_type
    return ContentType.objects.db_manager(obj._state.db).get_for_model(
AttributeError: 'ReverseGenericRelatedObjectsDescriptor' object has no attribute '_state'

Is that I am trying to reach is absolutely impossible and the only solution is to explicitly create needed fields in existing models?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Michael
  • 1,170
  • 2
  • 14
  • 35
  • Should it be possible for the `ForeignKey` on a `FirstModel` object to be a reference to a `AnotherModel` object? – ikkuh Jan 02 '18 at 15:24
  • @ikkuh no, I meant ForeignKey from, for exaple, FirstModel and to same FirstModel. It is possible, but not in Abstract Model. There is the answer https://stackoverflow.com/questions/367461/setting-up-a-foreign-key-to-an-abstract-base-class-with-django where people told ForeigKeys are not possible in Abstract models, instead GenericForeignKey could be applied, however there is no example there – Michael Jan 02 '18 at 15:30

1 Answers1

2

I tried to replicate your problem with ForeignKey on a abstract model, but it seems to work fine with Django version 1.11.1:

class BaseModel(models.Model):
    other = models.ForeignKey('self', null=True, blank=True)

    class Meta:
        abstract = True

class FirstModel(BaseModel):
    pass

class AnotherModel(BaseModel):
    pass

Using the models:

>>> fm1 = FirstModel.objects.create()
>>> fm2 = FirstModel.objects.create()
>>>
>>> fm1.other = fm2
>>> fm1.save()

The following assignment to other results in an error:

>>> am = AnotherModel.objects.create()
>>> am.other = fm1
ValueError: Cannot assign "<FirstModel: FirstModel object>": "AnotherModel.other" must be a "AnotherModel" instance.
ikkuh
  • 4,473
  • 3
  • 24
  • 39
  • Thanks, really works. My bad, wasn\`t attentive when checked implemetation and I thought `verbose_name` changes callable name of ForeignKey field, but that was `related_name` instead – Michael Jan 02 '18 at 16:23