Sven,

I'm going to leave it the way it is for the time being, although you
could certainly change my mind.  I am nowhere near being an expert
on Django models.  

In summary, using `models.ForeignKey` with the `related_name`
parameter gives us the ability to do the query we want in order to
retrieve the objects we want.

More of my thinking on this is below.  It's confused.  And, if you'd
like to try to educate me, I'll certainly listen.

Yes, I admit that I'm dragging my feet and going slow on this one.
I'm uneasy about the fact that what we've had until now is 180
degrees in the opposite direction from the change we are
considering.

But, after doing more reading and searching, I've also found this:
https://docs.djangoproject.com/en/1.11/ref/models/fields/#django.db.models.ForeignKey.related_name

That seems to suggest that `models.ForeignKey` when used with the
`related_name` parameter creates the backward relation from the
other model back to this one.  Isn't that what we want?

I also did the following search, and several of the top replies seem to
suggest that `ForeignKey` plus `related_name` does create that
reverse relation:
https://www.ixquick.com/do/search?query=django%20foreignkey%20related_name

For example, the above query led me to this:

    related_name will be the attribute of the related object that
    allows you to go 'backwards' to the model with the foreign key
    on it. For example, if ModelA has a field like: model_b =
    ForeignKeyField(ModelB, related_name='model_as'), this would
    enable you to access the ModelA instances that are related to
    your ModelB instance by going model_b_instance.model_as.all().
    Note that this is generally written with a plural for a Foreign
    Key, because a foreign key is a one to many relationship, and
    the many side of that equation is the model with the Foreign Key
    field declared on it.
    
    The further explanation linked to in the docs is helpful.
    
https://docs.djangoproject.com/en/1.10/topics/db/queries/#backwards-related-objects

    related_query_name is for use in Django querysets. It allows you
    to filter on the reverse relationship of a foreign key related
    field. To continue our example - having a field on Model A like:
    model_b = ForeignKeyField(ModelB, related_query_name='model_a')
    would enable you to use model_a as a lookup parameter in a
    queryset, like: ModelB.objects.filter(model_a=whatever). It is
    more common to use a singular form for the related_query_name.
    As the docs say, it isn't necessary to specify both (or either
    of) related_name and related_query_name. Django has sensible
    defaults. 
    
    Ref:
    
https://stackoverflow.com/questions/43132872/difference-between-related-name-and-related-query-name-attributes-in-django

So, revisiting your original report:

    "I have an XSD with
    
           <xs:element name="recipe">
               <xs:complexType>
                   <xs:sequence>
    
                       <xs:element name="title" type="xs:string"/>
    
                       <xs:element name="categories">
                           <xs:complexType>
                               <xs:sequence>
                                   <xs:element name="category" type="xs:string" 
minOccurs="1" maxOccurs="unbounded"/>
                               </xs:sequence>
                           </xs:complexType>
                       </xs:element>
                       ....
                   </xs:sequence>
               </xs:complexType>
           </xs:element>
    
    The Django models I get from that are
    
        class Recipe(models.Model):
               title = models.CharField(max_length=1000, )
               categories = models.ForeignKey(
                       "CategoriesType",
                       related_name="recipe_categories_categoriesType",
               )
               ....
    
        class CategoriesType(models.Model):
               category = models.CharField(max_length=1000, )
               ....

Django creates a one-to-many relationship from `CategoriesType` back
to `Recipe`.  I think ...

So, the question we need to ask is: given a recipe, can you find all
its categories?  Right?  The snippet above from Stackoverflow where
it says "ModelB.objects.filter(model_a=whatever)" suggests that you
can.  In that example, ModelA would correspond to the Recipe and
ModelB would be the CategoriesType.

I guess I'm arguing that the code we are currently generating really
is what we want.

I apologize for being dense and slow on this.  Although I wrote the
generateDS Django model generation code and actually did use Django
lightly in the distant past, I'm not a real Django user.

And, thanks for pushing me on this.  It really does need to be
straightened out one way or the other.

Also, even if the current code *is* correct, it is certainly less
than intuitive and should be documented somehow.  Oh, wait, it's a
relational database, so, of course it is not intuitive.

Dave

On Mon, Oct 30, 2017 at 12:25:19PM +0100, Sven Prevrhal wrote:
>    Any further thoughts here Dave?
>    Cheers,
>    Sven
>    2017-10-24 13:43 GMT+02:00 Sven Prevrhal <sprev...@gmail.com>:
> 
>      Dave- 
>      Yes I believe your Model-A Model-B thoughts are correct for a
>      one-to-many when A has many B's. In a many-to-many situation on DB level
>      one would use a mediation table, i.e. RecipeCategory with foreign keys
>      to recipe and to category. In Django, this is modeled with the
>      ManyToMany qualifier. I don't know about your code but the
>      CategoriesType could play the role of the mediating table, only that it
>      itself would not hold a char attribute but two foreign keys. I believe
>      XML/XSD would make a many-to-many relationship explicit with
>      independent, i.e. not nested elements of Table A and Table B and then
>      have a mediating element C_AB. This would be different from the XSD  I
>      had posted. Would generateDS Django readily translate this to a
>      ManyToMany qualifier? Currently, I believe the code does not implement
>      your Model A Model B thought for one-to-many relations, as the
>      foreignkey, like you said should indeed by with B.
>      Best regards
>      Sven
>      2017-10-23 23:55 GMT+02:00 Dave Kuhlman <dkuhl...@davekuhlman.org>:
> 
>        Sven,
> 
>        I recommend that you do *not* read this email.  The reason is that I
>        have been confused about this issue before, and I am (below) trying
>        to think it through and eliminate some of that confusion.
> 
>        Maybe tomorrow I'll have a less twisted reply.
> 
>        Let's see if we can get my head straight on this one.
> 
>        A recipe can have a single "categories" and that "categories"
>        element can contain multiple "category" elements.
> 
>        Do we agree so far?
> 
>        If so, the question is: How do we represent that in a Django model?
> 
>        In what is currently generated, the "Recipe" model has a ForeignKey
>        to a "CategoriesType" model.  This means that a record in the
>        "Recipe" table (relation) can point to (refer to, be joined with?)
>        multiple records in the "CategoriesType" table.
> 
>        Which is what we want, right?  Or am I twisting the fact so that
>        they fit what I want to see?
> 
>        Look at this snippet from the Django documentation (at
>        https://docs.djangoproject.com/en/1.11/topics/db/models/):
> 
>                from django.db import models
> 
>                class Musician(models.Model):
>                        first_name = models.CharField(max_length=50)
>                        last_name = models.CharField(max_length=50)
>                        instrument = models.CharField(max_length=100)
> 
>                class Album(models.Model):
>                        artist = models.ForeignKey(Musician,
>        on_delete=models.CASCADE)
>                        name = models.CharField(max_length=100)
>                        release_date = models.DateField()
>                        num_stars = models.IntegerField()
> 
>        Does the above mean that an "Album" can have multiple musicians, that
>        is
>        references to multiple records in the "Musician" table?  Or, does it
>        mean that a musician can have multiple albums?
> 
>        Here is another snippet from the same Web page:
> 
>            Many-to-one relationships¶
> 
>            To define a many-to-one relationship, use
>        django.db.models.ForeignKey. You
>            use it just like any other Field type: by including it as a
>        class attribute
>            of your model.
> 
>            ForeignKey requires a positional argument: the class to which
>        the model is
>            related.
> 
>            For example, if a Car model has a Manufacturer â** that is, a
>        Manufacturer
>            makes multiple cars but each Car only has one Manufacturer â**
>        use the
>            following definitions:
> 
>                from django.db import models
> 
>                class Manufacturer(models.Model):
>                    # ...
>                    pass
> 
>                class Car(models.Model):
>                    manufacturer = models.ForeignKey(Manufacturer,
>        on_delete=models.CASCADE)
>                    # ...
> 
>        In our case, we want a "Recipe" to have multiple instances of
>        "CategoriesType".  So, the should place the ForeignKey in the
>        "CategoriesType" model.
> 
>        So, perhaps the rule we should follow is: If you have Model-A and
>        Model-B and if you want a Model-A to have multiple instances of
>        Model-B, then put the ForeignKey in Model-B (referring to Model-A).
> 
>        What do you think?
> 
>        It worries me that I seem to recall I've been confused about this
>        before.
> 
>        More on this tomorrow.
> 
>        Dave
>        On Mon, Oct 23, 2017 at 08:33:36AM +0200, Sven Prevrhal wrote:
>        > I have an XSD with
>        >
>        >    <xs:element name="recipe">
>        >      <xs:complexType>
>        >        <xs:sequence>
>        >
>        >          <xs:element name="title" type="xs:string"/>
>        >
>        >          <xs:element name="categories">
>        >            <xs:complexType>
>        >              <xs:sequence>
>        >                <xs:element name="category" type="xs:string"
>        minOccurs="1"
>        > maxOccurs="unbounded"/>
>        >              </xs:sequence>
>        >            </xs:complexType>
>        >          </xs:element>
>        >          ....
>        >        </xs:sequence>
>        >      </xs:complexType>
>        >    </xs:element>
>        >
>        > The Django models I get from that are
>        >
>        >
>        > class Recipe(models.Model):
>        >     title = models.CharField(max_length=1000, )
>        >     categories = models.ForeignKey(
>        >         "CategoriesType",
>        >         related_name="recipe_categories_categoriesType",
>        >     )
>        >     ....
>        >
>        > and
>        >
>        > class CategoriesType(models.Model):
>        >     category = models.CharField(max_length=1000, )
>        >     ....
>        >
>        > This seems wrong to me. I would have thought Category gets a
>        ManyToManyField
>        >
>        > to Recipe. The way it comes out of generateDS it looks like a
>        > CategoriesType has many Recipes. Or perhaps my XSD is wrong?
>        >
>        > Cheers,
>        > Sven
> 
>        >
>        
> ------------------------------------------------------------------------------
>        > Check out the vibrant tech community on one of the world's most
>        > engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> 
>        > _______________________________________________
>        > generateds-users mailing list
>        > generateds-users@lists.sourceforge.net
>        > https://lists.sourceforge.net/lists/listinfo/generateds-users
> 
>        --
> 
>        Dave Kuhlman
>        http://www.davekuhlman.org

-- 

Dave Kuhlman
http://www.davekuhlman.org

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
generateds-users mailing list
generateds-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/generateds-users

Reply via email to