On 8/22/05, Brant Harris <[EMAIL PROTECTED]> wrote:
> 
> > How would this model be implemented in Django? The API provides a
> > special case where a recursive relationship back to the current entity
> > is denoted by ForeignKey('self'), but for the more general case of a
> > circular relationship I can't see a way to avoid the NameError.
> >
> > I know in SqlObject the class's name can be used instead of a
> > reference to the class, providing late binding to enable this kind of
> > model.
> 
> There is no current way of doing this.  Perhaps some of the main
> developers for Django could extrapolate further on this, but I believe
> the idea is partially to restrict such "circular" relationships as
> they are considered poor database/model design.

For what reason? The relationship I described wasn't a database design
- it was a real world (and fairly common) situation that someone might
want to model within their application. It seems pretty arbitrary to
limit that because it's 'considered poor design'.

I'll admit that having both foreign key relationships be not null
would make it impossible to insert any records, but as long as that
wasn't the case it would be a perfectly viable database design, and a
structure that I've seen many times.

When I think about it, it should be possible to implement it by having
an intermediate joining entity EmployedIn, to resolve the circularity.
Something like this:

class Employee(meta.Model):
    fields = (
        meta.CharField('name', maxlength=200),
    )
    
    admin = meta.Admin()
    
    def __repr__(self):
        return self.name
    
class Department(meta.Model):
    fields = (
        meta.CharField('name', maxlength=200),
        meta.ForeignKey(Employee, name='manager', rel_name='manager', null=True,
                        related_name='manages'),
    )
    
    admin = meta.Admin()
    
    def __repr__(self):
        return self.name
    
class EmployedIn(meta.Model):
    fields = (
        meta.ForeignKey(Department),
        meta.OneToOneField(Employee),
    )
    
    verbose_name = 'assignment'
    verbose_name_plural = 'assignments'
    
    admin = meta.Admin(
        list_display = ['employee_name', 'dept_name'],
    )
    
    def __repr__(self):
        return '%s works in %s' % (self.employee_name(), self.dept_name())
    
    def employee_name(self):
        return self.get_employee().name
    employee_name.short_description = 'employee'
    
    def dept_name(self):
        return self.get_department().name
    dept_name.short_description = 'department'

This is a bit awkward - it works alright in the database and through
the API, but the admin doesn't handle it properly. It would be better
if Django could take the SqlObject approach and allow for late-linking
between related entity classes, I think.

xtian

Reply via email to