It's easy to make Django react to "Accept-Language" headers, I love how the LocaleMiddleware supports it out of the box [1]. I implemented automatic language detection to show either German or English content and was surprised how many users hated it. We're located in Germany but a lot of people have their browser set to English for some reason, yet they still expect to see pages in German. Of course I had provided an explicit language switch but many users did not like the site guessing their language.
I agree 100%. Even if you don't need it, these lines don't hurt you, but most of the time, the additional model is put to good use. I usually add metadata, such as additional timestamps, flags, tags, custom user settings, consent or preferences.
I'd love to hear your criticism of django, issues you encountered and problems you have solved :)
> My real criticism of Django is that, at long last, I think it's starting to look dated.
Actually, that is something I found really great about django. I found that django is reliable over a long period of time. The js/node/react/express/angular apps I had developed in the past (~2012+) can't be built these days without redoing major components. I never had these problems with django.
As for the responsiveness of the results, I found that a good understanding of django's performance helps. Using a good caching strategy (on models, views + nginx) yields results have almost instant reactions, even though there is the whole HTTP to HTML roundtrip. While they do have the noticable page-reload semantics, I found that these are way easier to build and sometimes yield very enjoyable experiences for my users. After all, I'm not building a YouTube so PictureInPicture and SPA-semantics aren't that important to my users.
> Modern web apps are maintaining models in the client and staying current though a combination of ajax queries and websockets.
Julia Elman explains how to do this with Django + DRF and Backbone.js in the book "Lightweight Django" (O'Reilly). Is this a viable compromise?
I've implemented Django+DRF+React in several projects. The thrust of my arguement is that, were Django started today and not 17 years ago, it would account for these concepts more than templates do.
Django contrib exists to be a home for first party solutions to specific problems [1]. It need not be an entire frontend framework that follows trends like react, but something to make syncing state easier sits squarely in that namespace.
One advantage of REST is that it's easier to use from a programmatic client perspective; this might become useful if you want to offer an API to third-parties.
My biggest objection to that naming scheme would be the numbering. If you have multiple people working on an app, it is likely that you at some point get multiples of a number as people add models simultaneously. What happens if there are multiples using a single number?
I much prefer the timestamp based system that is used by Rails, it make the risk of that kind of conflict a lot lower.
The migration engine will order the dependencies at runtime, and it will bail (and suggest creating a "merge" migration) if you have diverging trees of migrations. I find it pretty robust in practice.
> My biggest objection to that naming scheme would be the numbering. If you have multiple people working on an app, it is likely that you at some point get multiples of a number as people add models simultaneously. What happens if there are multiples using a single number?
We have this happen at work, when merging branches; this is what `./manage.py makemigrations --merge` exists for.
The only thing that annoys me to this day is that they have the numbers first. I get the logic why: it means they're ordered in the directory properly.
That said, it's very annoying in that they're not tab-completable... any time I have to edit one, I have to stop and hunt in the entire list for what I'm looking for.
I wouldn't call those harmful. Most are non-issues, while others are "unfortunate" at best.
1. I found that the ORM works quite well and it's easy to optimize later. Using `prefetch_related` or `select_related` in the ORM still feels weird (they're just joins), but I wouldn't call them harmful.
2. I found it unfortunate that the info on how to change the User model is hidden so deep in the Documentation. I don't like to RTFM, but with Django it sure is worth it; same goes for 1.
3. I occasionally do it, but most of the time, I don't and never had an issue.
4. It do rely on that and found django's naming scheme to be a non-issue. I guess this might be more important if you need to change your database out of band (out of django band, that is)
5. This point is unsubstantiated. Apps aren't mere packages but also define a scope for the admin tool (which I use a lot and think is an integral part of Django) so that it will group models and allow individual access (i.e. apps also provide scope for your permissions). I use tons of apps but I wouldn't call it a harmful default.
6. Yeah, dynamic languages might produce naming collisions. Still beats imports like `org.example.publib.boulder.yourmoms.maidenname.models.impl.Account`
I consider them harmful for beginners who need to start working on non trivial production code.
Multiple apps are definitely good for the admin but what I was advocating isn't 100% avoidance of apps but to avoid creating apps for every tiny feature.
Personally, I like my databases to be designed for longevity and avoid couple code to my data. Code can die at any point in time but data is an asset that needs to live for as long as the company is in operation.
> beginners who need to start working on non trivial production code.
If you're a beginner dropped into a non-trivial production codebase your best bet is to follow existing conventions until you gain enough experience to be able to evaluate such advice and consider it against your projects' and business' requirements.
Does your employer pay for your technical skillset and your labor, or do they pay you for sacrificing your mental health? I don't think self-care is unprofessional, and deciding to leave is perfectly fine.
Professionalism means being able to produce convergent results given varying resources, but when the spec is unclear, your employer doesn't provide appropriate resources for you to perform or if your mental health is in danger, I think it's perfectly valid to back off. "Professional" does not mean "sorcerer". A professional photographer can't take a good picture in complete darkness, and even a good architect can't create a distributed system when the environment won't support it. It argue it's professional to know your own limits and reject a job offer.
It's difficult to make the decision to leave, especially when you have been jobhunting for a while and I can't say anything substantial on how anyone should make such a decision, but the other day I found a meme saying (something along those lines):
In a job, you should either earn or learn; either is good, both is ideal, if it's neither: leave. If the job pays ok money, but costs your sanity, I'd argue you should leave.
This is judging a fish on it's ability to fly. In other words, it is judging an object oriented program on its ability to resemble top-to-bottom sequential execution style programming, while ignoring that the language is commited to a different paradigm.
OO-Programs have these weird factory functions called constructors that do exactly that. To me, it makes sense that such functions should share their living space with the class that they are creating. Where else would you like to put these functions? "Utils"?
As for classes, namespaces and objects: as others have pointed out, this is an implementation detail. In Python, for example, classes are objects. Besides, classes and objects are functions (and the other way around) so it doesn't matter all that much in practice.
What buggs me more is code like this:
class SayHello {
public static void toPerson(String name) {
System.out.println("Hello " + name);
}
}
Sure, comparing it to an empty Python file which just says "print" this looks like an aweful lot of code. However if the paradim is poorly understood, it will seem to be working against you:
class Name {
public Name (string name) {
this.name = name;
}
public static void greet() {
System.out.println("Hello " + this.name);
}
}
The programming is different in that you create a declarative network of objects that then ... act. At this level, there is hardly any difference, except that the name has been introduced as a proper concept. Many people will argue that such value objects are expensive or inefficient (which they are) but if that cost hits you hard, you should be asking yourself why you picked a high level language to begin with.
Yes, in such a paradigm a place is needed where the entry point lives, but I found it fundamentally useful. Whatever you call the class it:
- Can read and encapsulate access to env variables
- It can accept commandline arguments (as main(argv[]) indicates)
- It's the place to setup and configure your (object)- dependency tree (what IoC/Dependency Injection-Containers are doing)
- Or it can be the ultimate exception handler for messages deeper in your program, e.g. where you would start your main message pump / game loop, etc.
I don't use a debugger. When I have a problem that I need to narrow down I state my hypotyhesis of what is going on in some kind of unit test and narrow it down that way.
I am currently working on a Python/Django project of around 45k lines of code, 28k of which are tests. For me, this approach works quite well. It is not that I am against debugging or that I don't value debugging as a tool, but I just never feel the need to use one.
The tests also have a nice side-effect: because I do TDD a lot, I mostly end up with a lot of small understandable units, so I am effectively preventing code with properties that need me to follow each statement one by one.
I hardly ever feel the need to interrupt the running process to inspect the current variables. In many cases, this would be futile anyway, because I started writing a lot of generators.
[1] https://docs.djangoproject.com/en/5.1/topics/i18n/translatio...