On Fri, Jun 8, 2012 at 7:50 PM, Anssi Kääriäinen <anssi.kaariai...@thl.fi> wrote: > On 8 kesä, 13:43, Russell Keith-Magee <russ...@keith-magee.com> wrote: >> That's certainly an interesting use case. However, I can think of at >> least 2 ways it could be mitigated. >> >> One way would be to treat this as part of the contract of a pluggble >> app. We've always said that an app should do one thing, and one thing >> only; providing a *single* swappable model candidate, and any >> associated support (e.g., forms, admin declarations) would seem to fit >> that definition fairly well. In this context, a "library" of reusable >> User models is really just a collection of apps, one of which will be >> installed in your project. The CMS with a range of User model options >> would provide them as a series of apps, one (and only one) of which >> needs to be installed. > > We might want to have two user models already in the auth.models. The > current User, and then an "ImprovedUser", which is like the default > user, but has the worst limitations lifted (email field can be 255 > chars long, username restrictions lifted, ...). It seems the current > implementation would not allow for this, because only one model could > define itself as swappable, and the other would get installed even if > it wasn't needed. For our use case this would work as we control > global_settings.py, and we can use the hidden swappable attribute for > both models, but I guess the ImprovedModel/BackwardsCompatibilityModel > pattern isn't such a rare case. To make the swappable option nicer to > use for 3rd party apps a better solution than different app for each > swappable model would be welcome.
I'm not sure I see why. This looks to me like *exactly* what apps are designed to achieve. By way of implementation, it might make sense to introduce this as a 'sub app' - i.e., contrib.auth.improveduser would be an installable app in itself; this would avoid the need to dirty up the contrib namespace. However, for me that's a relatively minor implementation detail. I don't understand the objection to using app installation as the basis for declaring what features you want a particular project to have. Can you elaborate on why you think this isn't a reasonable solution to the problem? >> > The model_label_for_default_model can't be defined anywhere in the >> > current implementation. The Model._meta.swapped uses: >> > return self.swappable and getattr(settings, self.swappable, None) >> > not in (None, model_label) >> >> Sure - but model_label_of_default_model doesn't *need* to be defined >> anywhere - it's the model that has swappable=XXX defined on it. > > I was driving for the use case where you define multiple different > models for the same "slot" using the swappable option. If there can be > only one model with swappable set for each slot, then there is no > problem here. To me, that seems like solving an entirely different problem. It *might* be a problem that could be solved with app-refactor -- the configuration of an app could potentially specify all sorts of configuration points, such as "Model X has a foreign key to placeholder A; what model will A be?". That's an orthogonal problem to replacing all references to User with a custom model across an entire project. >> Again - for me this is one of those things where it's all about the >> interface. >> >> In this example, your end problem isn't "I need to issue a query with >> Q(creator__last_name__ilike=q)|Q(creator__first_name__ilike=q)" -- >> it's "I need to search for document creator by name", and *that* is >> what your interface should be defining. If your interface spec said >> you had to provide a "find_document_by_author()" method, and one >> particular implementation happens to use that query, then you've just >> solved the problem. The specific document attributes *should* be >> irrelevant -- and if they aren't, you haven't defined your document >> interface well enough. >> >> It's impossible to claim that every model will be usable in every >> circumstance. At some point, you have to lock down an interface >> specification, which will define what it is possible to do in a >> 'generic' sense with your swappable model. This isn't some new concept >> we're inventing here - interfaces have been a major part of more than >> one language for decades. Luckily, with Python, we get the benefits of >> interfaces without needing to be strict about it -- we can rely on >> duck typing, rather than rigorous and inflexible compile-time checks. > > The problem is that we have no ability to define ORM interface for the > model. The ORM doesn't allow for this. It would be nice, but you can't > have everything. I am not claiming this is a blocker issue at all, I > was just wondering if there were any plans to define an ORM interface > for the model. I'm not sure I understand what you're saying here. We can specify that the model class itself needs to provide certain methods (e.g., User.get_full_name()), and we can specify that the Manager must provide certain methods (e.g., User.objects.create_superuser()). If we really needed to, we could also specify that the queryset implementation for the model had to provide certain methods, or that the model class had to provide certain class methods. If you're saying that we have no way to require that certain queries work or are parameterized, then I agree -- but I also think that this is a good thing. If you're building an app that is going to utilise pluggable models, then it's up to you to abstract away the implementation behind an interface that provides whatever utility you require. If you're not in a position to define an interface like that, then I'd argue that you don't really have a model that is a candidate for being swapped out. For the purposes of this work, the only model we actually care about is User (since swappability as a general feature isn't on the table here), and we can definitely define an interface for User. Yours, Russ Magee %-) -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.