Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
95 views
in Technique[技术] by (71.8m points)

python - Django, Many-to-one relationship with Abstract entities

Say object contains multiple types of objects (Models) in an array, like a Page, that could contain a Post, Blog, Picture, in any quantity or order, where the user scrolls down and sees the following element and that depending on the page, is next element one of these types of elements. Thus a Page could contain:

  1. A Post
  2. A Post
  3. A Picture

Or something pretty different such as:

  1. A Picture
  2. A Blog
  3. A Picture

An element could be an abstract entity that has an attribute as a ForeignKey relating itself with Page, and its inheritance would gain access to that relationship:

class Page(models.Model):
    ...
    
class PageElement(models.Model):
    page = models.ForeignKey(Page, verbose_name="Page", on_delete=CASCADE)

    class Meta:
        abstract = True

class Post(PageElement):
    ...

class Blog(PageElement):
    ...

class Picture(PageElement):
    ...

With this approach, you can serialize Page with a REST serializer, but you wouldn't have access to an pageElement_set, instead you would need to call post_set, blog_set, picture_set and loose the order of the objects.

By just adding a related_name key in the ForeignKey, we get an error:

pages.Picture.page: (fields.E305) Reverse query name for 'Picture.page' clashes with reverse query name for 'Post.page'.
        HINT: Add or change a related_name argument to the definition for 'Picture.page' or 'Post.page'.

The question is: How do you implement such relationships in Django?

So that you can have an order set of PageElement instances, and be able to have the desired order.

question from:https://stackoverflow.com/questions/65895225/django-many-to-one-relationship-with-abstract-entities

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Since you want to query multiple Models in order and you can see that your models are in Model is a PageElement relationship, then instead of inheriting from an abstract Model you need to have a OneToOneField with a common model:

class PageElement(models.Model):
    POST = 'PO'
    BLOG = 'BL'
    PICTURE = 'PI'
    ELEMENT_TYPE_CHOICES = [
        (POST, 'Post'),
        (BLOG, 'Blog'),
        (PICTURE, 'Picture'),
    ]
    element_type = models.CharField(
        max_length=2,
        choices=ELEMENT_TYPE_CHOICES,
        default=POST,
    )
    # common fields

class Post():
    page_element = models.OneToOneField(
        PageElement,
        on_delete=models.CASCADE,
        related_name = "post"
    )

class Blog():
    page_element = models.OneToOneField(
        PageElement,
        on_delete=models.CASCADE,
        related_name = "blog"
    )

class Picture():
    page_element = models.OneToOneField(
        PageElement,
        on_delete=models.CASCADE,
        related_name = "picture"
    )

You can inherit from a common abstract class that has the OneToOneField for ease if needed.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...