Live data from Hacker News

Django Styleguide

github.com

91–100 of 141 posts

Re: Django Styleguide

#91
post #84

Earlier quoted context omitted.

So, the way I understand it, job/services.py and load/services.py depend on mediator/mediator.py which depends on job/models.py and load/models.py , instead of job/services.py ultimately using load/services.py , and vice versa. Thanks so much!

This is good enough to break circular dependencies between individual modules, but keep in mind that circular dependencies between the apps remain (e.g. job depends on mediator, mediator depends on job). I usually prefer to resolve those too. If job is small enough, all the orchestration of jobs should happen through mediator (same for load). If it's not plausible, then job can emit signals which mediator subscribes…

Holy bovine. This finally worked. I've been working around the clock on this for two days now. Thanks again stranger!

Re: Django Styleguide

#92
post #80
post #37

Earlier quoted context omitted.

"Also be wary of the formerly South, now built-in migrations stuff. It's built around a fragile model (perfect history representation), so has lots of foot guns." My experience has been opposite so I'd be interested in hearing your experiences if you are willing. I have been using the built in migrations since day 1 on a medium sized Django project with 350+ migrations and migration issues for our project have been e…

Diamond-dependencies are hard to work with, and so we forbade them. Specifically, you can't revert an individual migration, you just specify your desired "target" to roll back to, and therefore you can't unapply a single branch of a diamond dependency. This means if your second branch of a diamond dependency breaks the DB, but your app depends on the first branch, you're SOL and are now manually running SQL to fix yo…

Maybe you need to turn this into an article because over the last decade of working with Django, we've learnt the same lessons, sometimes the hard way. Learning to never import real models into data migrations was a big one.

I recently wanted to move a model between apps and ended up going the route of create new table, copy all rows over, delete old table. It was annoying, but the only way to make it work with regular migrations.

We ended up writing our own script[1] to squash migrations, and I'd love to know if there's a better way. We needed something that works for clean installs or existing installs that already have the current migrations installed - so it generates empty migrations which get applied on existing installs, and then they get replaced with real initial migrations on clean installs starting from a new release.

1. https://github.com/nyaruka/rapidpro/blob/main/tools/squash_m...

Re: Django Styleguide

#93

Earlier quoted context omitted.

> Always keep your models slim. As simple as possible, but no simpler. Django models are meant to deal not just with the data, but also with business logic. If `course.has_finished` is a property of the course, why would you want to have a separate function outside of the class? > Do precomputation if you need the information in a template If the precomputation is only needed in a template, you can (should, IMO) use…

> If `course.has_finished` is a property of the course, why would you want to have a separate function outside of the class? Because one should avoid passing Django models around. It leads to bad design. Have a selector or something that uses the ORM, but exposes some dataclass or pydantic model instead, and put the logic there.

You want to add an ORM to the ORM? Why?

Re: Django Styleguide

#95
post #64

Earlier quoted context omitted.

Same here. If I was starting a non-Python project tomorrow I'd consider using Django to manage the database schema - especially now that we can describe custom indexes and constraints in migrations. Our project has gone thru over 1000 migrations so far tho we squash them down to 50 or so about once a year.

Thats interesting, if I was using TypeScript to access the data, how would I keep the schemas in sync between TS and python?

Prisma works very well and has usable migrations. Not as solid as Django's.

Tiangolo of FastAPI fame is working on https://sqlmodel.tiangolo.com/ Which is pydantic models, SQL alchemy. Migrations are coming soon. This will probably be an excellent way to build APIs with db. Then you can generate a typescript client from the built in OpenAPI schema.

Re: Django Styleguide

#96
post #17

I think there are too many concepts in this, but rather than being negative, here are some tips: Always keep your models slim. Don't stuff template related stuff in there. You need to look at those models often, so compact is a win. course_has_finished(course) is not much longer than course.has_finished(), and will allow you to expand the functionality as time goes on. Do precomputation if you need the information in…

Always keep your models slim. Don't stuff template ...course_has_finished(course) is not much longer than course.has_finished() I disagree with this. When trouble shooting or expanding code it is super convenient to import a model and have all of your methods on auto complete. Especially when you need the same functionality in a view, a cron job, a celery task, and an DRF end point. If you want to keep it clean you c…

> Please. For the love of God, always use class based views for almost everything.

This. 100%. Leverage as much pre-built stuff you can, especially with something as important as your HTTP layer. Whenever I run out of CRUD verbs for a model and I need to add a custom endpoint, I'll implement it in a separate APIView sublcass. Convention over configuration; write boring code.

Re: Django Styleguide

#97
post #5

> We use Celery for the following general cases: > > Communicating with 3rd party services (sending emails, notifications, etc.) > Offloading heavier computational tasks outside the HTTP cycle. > Periodic tasks (using Celery beat) Sigh. No mention of the trade-offs. There's simpler ways to do all these things. Celery is a big complex beast and it always pains me to see it as the default suggestion for simple tasks.

A lot of people use Django with uWSGI, which also comes with queues, cron, workers, cache and lots more. I've been stuck with Celery on previous projects for reasons. But I've been dying to try out uWSGI's built in features for this. Hearing great things about it.

https://uwsgi-docs.readthedocs.io/en/latest/Spooler.html

https://uwsgi-docs.readthedocs.io/en/latest/Cron.html

https://uwsgi-docs.readthedocs.io/en/latest/Mules.html

https://uwsgi-docs.readthedocs.io/en/latest/Caching.html

Re: Django Styleguide

#98
post #39

Ah, the typical "where to put business logic in Django". M in ActiveRecord MVC web frameworks is deeply misunderstood. M is not "data model" (it would be called DVC if that was the case). M is your domain model. It's the model of your business, model of the real world. It's the core of your application. Another thing that I never understood, why are functions called services? Is it a subconscious desire to go back to…

Business logic goes in the controller. That's why it's called a controller because it controls stuff like access to your data.

I try to use controllers just to connect incoming events or API calls to the business layer.

The control part is more like Traffic Controller . Just directing traffic.

Re: Django Styleguide

#99
post #84

Earlier quoted context omitted.

This is good enough to break circular dependencies between individual modules, but keep in mind that circular dependencies between the apps remain (e.g. job depends on mediator, mediator depends on job). I usually prefer to resolve those too. If job is small enough, all the orchestration of jobs should happen through mediator (same for load). If it's not plausible, then job can emit signals which mediator subscribes…

> ...all the orchestration of jobs should happen through mediator (same for load) So, in a smaller app, when a request comes into job/views.py or load/views.py then we immediately start working with JobLoadMediator to handle business logic between the two? I was just going to focus on specific tasks between job and load. I'll probably look into signals; I haven't used those in several years and as I recall, it felt h…

> when a request comes into job/views.py or load/views.py then we immediately start working with JobLoadMediator to handle business logic between the two?

In my world, mediator.views and job.views would likely have different audiences.

mediator.views is for business domain (e.g. your API). Though name would not be mediator, it would be something domain-specific.

job.views could be for more low-level internal tooling (e.g. analytics/monitoring). Or it could be empty, if job is just dumb data object that has a lifecycle but doesn't require public API.

> When a Job is deleted, it needs to delete associated Loads. And the states of the Loads will affect the state of the Job

If you want to keep them apart, signals is the right (though not the easiest) answer. job owns (depends on) loads, and subscribes to loads signals. load doesn't know anything about job (ignore the fact that job is referenced in load.models as foreign key, that's just limitations of SQL DDL).

The easiest is a subtle dependency: load can access job through foreign key, job can access loads through related_name. Circular dependency is still there, but it is resolved at runtime. This will start to cause pain when application grows, but is fine at small scale.

Though again, I'd probably merge those apps: if you can't reason about load without job, and can't reason about job without load, there's very little benefit in keeping them separate. It might make you feel more organized, but the if the code is lying about your mental model, this is false organization.

Re: Django Styleguide

#100

I've been working on a project with flask + sqlalchemy. I have those sql queries returning a bit of rows (up to 20k) and that are quite slow. SQLalchemy does not seem to support caching the results and I've started to use flask-caching[1] with redis using the @cache.memoize() decorator. Just wondering if I am taking the right path or if there is better alternative. [1] https://flask-caching.readthedocs.io

> flask-caching[1] with redis using the @cache.memoize() decorator.

> Just wondering if I am taking the right path or if there is better alternative.

Yes, this can be a fine solution to slow queries and is used very often in many kinds of web applications.

However... 20k rows is not a very big number for a modern dB. If the db query is really the slow part then you should investigate why - ensure the relevant sql queries are written properly, and that the relevant tables are indexed properly for the queries that you are running on them.

Post reply on HN