Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
PT6A
Jan 5, 2006

Public school teachers are callous dictators who won't lift a finger to stop children from peeing in my plane

epalm posted:

I'd already taken a few steps in the python-social-auth direction, I continued and got it working within 30 minutes. Quite painless, although if I wanted to nitpick, the documentation is a bit daunting (there are a ton of options and tweaks) and lacks "flow", and could benefit from a minimum working example. (If there is one, I didn't see it.)

All that applies to allauth too, for what it's worth. They're probably pretty similar, so if you've started with one I don't see any reason to switch.

Adbot
ADBOT LOVES YOU

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice
Has anyone integrated these social auth things with Django Rest Framework? Does it "just work"? Any experiences with social-app-django or allauth along side DRF that would steer me one way or the other?

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Lumpy posted:

Has anyone integrated these social auth things with Django Rest Framework? Does it "just work"? Any experiences with social-app-django or allauth along side DRF that would steer me one way or the other?

There was some discussion in the thread recently about this: https://forums.somethingawful.com/showthread.php?threadid=2790475&pagenumber=102&perpage=40#post466375208

For me python-social-auth "just works" along side DRF with almost no futzing around.

Data Graham
Dec 28, 2009

📈📊🍪😋



Anybody know what the rationale is for the Django admin not creating links to related objects in the object list views?

It just lists them by their __unicode__() return strings, but it sure seems like an obvious feature would be to allow you to navigate from one object to another directly if it knows how they're related. Even most database GUIs do that to some degree.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

fletcher posted:

There was some discussion in the thread recently about this: https://forums.somethingawful.com/showthread.php?threadid=2790475&pagenumber=102&perpage=40#post466375208

For me python-social-auth "just works" along side DRF with almost no futzing around.

Awesome, thanks for the info!

porksmash
Sep 30, 2008

Data Graham posted:

Anybody know what the rationale is for the Django admin not creating links to related objects in the object list views?

The admin is pretty automagical but still can't make assumptions about everything. You may not have an admin configured for the related object. You may also choose to represent them differently like using an inline formset in a different model's admin.

You can easily add the links yourself though like so: https://stackoverflow.com/questions/28832897/link-in-django-admin-to-foreign-key-object

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

fletcher posted:

There was some discussion in the thread recently about this: https://forums.somethingawful.com/showthread.php?threadid=2790475&pagenumber=102&perpage=40#post466375208

For me python-social-auth "just works" along side DRF with almost no futzing around.

Another question: Have you (or seen good resources) on implemented authentication / account creation as part of a Single Page app using these in tandem? There seems to be a huge number of questions floating around about it which may be hiding the good answers. I have been looking at this: https://github.com/st4lk/django-rest-social-auth which sort of maybe does that? But it looks like I have to auth with providers first to get tokens from them, which then the SPA sends to Django which then exchanges said tokens behind the scenes with the provider to auth the user and then inform the SPA that they are now logged into my app.

Oh to have a couple days (or even a few hours) to sit and learn about this stuff... :suicide:

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Lumpy posted:

Another question: Have you (or seen good resources) on implemented authentication / account creation as part of a Single Page app using these in tandem?

Yes I have! :D

It's not exactly straightforward. I just have to remember which project I did it in last so I can go look at what I did. OAuth + SPA doesn't work together seamlessly...at least if you follow most of the docs and tutorials you'll find.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Thermopyle posted:

Yes I have! :D

It's not exactly straightforward...

Get me that quote!!! :v:

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Lumpy posted:

Get me that quote!!! :v:

I'm working on it right now. (As you can tell by my SA posting)

Just trying to remember how I did this in the past.

Harik
Sep 9, 2001

From the hard streets of Moscow
First dog to touch the stars


Plaster Town Cop
Anyone develop django inside visual studio? I'm trying to figure out how to run it external to VS, and still attach the debugger to it. Apparently that's possible, and it makes things like auto-reload work properly so development is faster.

Alternately, is there a better IDE that integrates well with django? VS can't follow the model magic so none of the fields show up on intellisense. I'm not an IDE guy normally (they make me want to break things), but I'm trying to use it enough to be able to help the new guys get up-to-speed.

More interesting question: I've got a set of APIs designed to be consumed by both a webpage and a mobile app. I don't want to do the double-tap on every action to get a fresh CSRF token - but I obviously don't want someone's session cookies used by foreign code. Is there a way to do some kind of long-lived CSRF token? I don't think I need to go full AWS with signed requests, but something that's safe from third-party javascript making requests to my endpoints.

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.
On CSRF tokens, my clients almost always seem to not get fresh csrf tokens when they navigate direct to 'site.com/admin', it's sort of been low priority but it's still pretty annoying, anyone experience and know how to ensure the page load provides a clean and usable csrf token?

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Harik posted:

Anyone develop django inside visual studio? I'm trying to figure out how to run it external to VS, and still attach the debugger to it. Apparently that's possible, and it makes things like auto-reload work properly so development is faster.

Alternately, is there a better IDE that integrates well with django? VS can't follow the model magic so none of the fields show up on intellisense. I'm not an IDE guy normally (they make me want to break things), but I'm trying to use it enough to be able to help the new guys get up-to-speed.

PyCharm (JetBrains) is a fantastic IDE for Python & Django. Definitely check it out.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice
EDIT: Turns out I'm a dummy! This library wants a "code", which is not the 'accessToken' you get back. On to try something else!

(left here for posterity...)

-----


Question about me trying to implement Social / SSO logins, and apparently I am doing something dumb as I'm running into an error that is stumping me. (To be fair, that's not hard to do...) I can log in / create users using "vanilla" social-auth-app-django and everything works, so that seems to be in order.

Trying to get authentication working via DRF is where the problems start. I am doing Facebook first, and I use the FB javascript SDK and do FB.long() and get back an accessToken. When I attempt to use the API endpoints provided from rest-social-auth passing in said token I get this error on the server side:



code:
 Authentication process canceled; 
 {'error': 
    {'code': 100, 'type': 'OAuthException', 'fbtrace_id': 'Ec2RsuzzbGD', 'message': 'Invalid verification code format.'}
}
The code I'm sending validates here: https://developers.facebook.com/tools/debug/accesstoken/ so I know that part is good. My request is being sent to:

http://localhost:8888/api/login/social/jwt/facebook/

with a body of:

code:
{ "code": "EAAT7bZB0BZ...2UZD" }
(truncated for length, but again, the code validates on FB's tool)

Any thoughts?

Lumpy fucked around with this message at 17:00 on Jul 21, 2017

porksmash
Sep 30, 2008

fletcher posted:

PyCharm (JetBrains) is a fantastic IDE for Python & Django. Definitely check it out.

The super handy Django (and other web framework) features are Professional edition only, though. Certainly won't stop you from running and debugging it, but I find it worth the money and I'm just a hobbyist.

Fluue
Jan 2, 2008
Got a weird session issue going on with Django 1.11 (been happening since 1.10, though).

I store some user experience data in the session (generic example: what kind of colors to use on a page). Occasionally these values are not populated in the request.session attribute even though the user still has a session_id cookie and I'm not doing anything to clear their session or refresh the session during these requests. This completely breaks the user experience and I've been puzzled why it happens (and without any sort of rhyme or reason).

The session storage is setup using cached_db and the cache is a semi-remote memcached that lives on one of the servers (we also only use a single remote DB instance, so it doesn't seem to be an issue of database sharding). The server setup includes 4 servers (all configured the same via ansible) that live under an Amazon ELB. The django cache settings point to {ip_of_the_server_running_memcached}:{port} on every server.

Could having a single memcache instance living on one server that all over servers in an ELB "pool" point to affect data retrieval? Would it be better to use a service like Elasticache? Again it's a sporadic issue, but I haven't been able to pin down any exact patterns as to why or when this happens.

Fluue fucked around with this message at 21:37 on Jul 21, 2017

IAmKale
Jun 7, 2007

やらないか

Fun Shoe
Does the set-cookie header set by HttpResponse.set_cookie() not set the cookie appropriately if you're making requests via the Javascript console? I've just started in to coding a hand-crafted artisanal analytics framework (basically a small Google Analytics-esque JavaScript library that sends events to a DRF server). So far I have something that works across multiple domains, and I'm able to send requests from, say foo.com to my server running on local.bar.com (which is a CNAME to 127.0.0.1).

For simplicity's sake, I'm testing things out by sending requests from foo.com via the Developer Console. The request comes in, I set a cookie on the response, and I see the set-cookie header on the response:


So far, things appear to be working fine on the backend.

However, when I try to view Cookies under the Applications tab, I don't see that cookie anywhere. Is it because I'm trying to set it from the console? Do I need to launch the event from within the foo.com page itself before it'll appear and get set on subsequent requests?

Edit: It turns out I needed to set CORS_ALLOW_CREDENTIALS = True in settings.py and also set up my request on the front end to send credentials, then the cookie started to be set and sent as expected.

IAmKale fucked around with this message at 16:03 on Jul 25, 2017

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice
So let us say I have three distinct types of users. How do I handle that when each type of user has vastly different profile data?

When there's one user profile type, I'm used to doing this:

Python code:
from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # my fields here
One thought is to have a base Profile class and have three different profiles inherit from that.

Python code:
from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # any common fields

class UserTypeAProfile(Profile):
    # user type A fields

class UserTypeBProfile(Profile):
    # user type B fields

# ditto Type C User
Another thought is to have three specific profile types, and link them to a generic Profile:

Python code:
from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    user_type = # set the user type to one of my three

class UserTypeAProfile(models.Model):
   profile = models.OneToOneField(Profile, on_delete=models.CASCADE)
   # user type A fields

class UserTypeBProfile(models.Model):
   profile = models.OneToOneField(Profile, on_delete=models.CASCADE)
   # user type B fields

# ditto Type C User
Comedy option: just have one Profile and put all the fields on it for all three user types.

Has anyone done this? Any suggestions?

IAmKale
Jun 7, 2007

やらないか

Fun Shoe
The second method definitely seems like the more sane way to approach this. It'll keep your Profile models nice and clean by reducing duplication of the OneToOneKey field. Will there be any common fields that might end up being defined in Profile class? If so, perhaps consider renaming Profile to BaseProfile to give a better indication that your custom Profile models will get a basic set of fields by subclassing.

Edit: As soon as I hit submit I realized that the second approach will potentially create one of each profile type per user. If the profiles really are that different, then I'd say make three different fields, each with their own OneToOne field so they act as standalone profile types:

code:
from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)

class TypeAProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)

class TypeBProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
Then again that might lead to the same thing...huh, this seemed easier at first glance.

IAmKale fucked around with this message at 17:38 on Jul 31, 2017

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

IAmKale posted:

...huh, this seemed easier at first glance.

I think you have summed up software development in the most concise way I have ever seen.

Harik
Sep 9, 2001

From the hard streets of Moscow
First dog to touch the stars


Plaster Town Cop
PyCharm didn't win me over, yet. Doesn't help that web integration is pro-only and for small shops VS Community is legal (up to 5 people in a company) and free. I was just finding it a real pain to convert the project structure to what it wanted without starting from scratch. Next weekend I'll give it another go.

Actual question:

I've gotten pretty far with getting a basic CI/manual deploy from git going, but I'm stuck on making a nice christmastree out of the tests.

Standard Django unit tests. Gitlab self-hosted with the built-in CI.

I get an overall pass/fail on the pipeline test stage, but what I'd like to do is get a red/green on each test name at some stable URL. Would that be something to generate as part of the pipeline and extract as an artifact? This should be a solved problem - they don't really expect you to list every unittest in the gitlab-ci.yml file, right? I think the django runner just does some initial setup and hands it over to the standard python unittest, so anything that works there should work here.

The nice part about all this is as soon as I get it working for one project I can cookie-cutter it over to all the others and now everything is done right. Not bad for a team of one. I don't count the newhires, the have no idea about any of this stuff yet - I still need to edit all their commits at this point.

Lumpy posted:

So let us say I have three distinct types of users. How do I handle that when each type of user has vastly different profile data?

When there's one user profile type, I'm used to doing this:

Python code:
from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # my fields here
One thought is to have a base Profile class and have three different profiles inherit from that.

Python code:
from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # any common fields

class UserTypeAProfile(Profile):
    # user type A fields

class UserTypeBProfile(Profile):
    # user type B fields

# ditto Type C User
Another thought is to have three specific profile types, and link them to a generic Profile:

Python code:
from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    user_type = # set the user type to one of my three

class UserTypeAProfile(models.Model):
   profile = models.OneToOneField(Profile, on_delete=models.CASCADE)
   # user type A fields

class UserTypeBProfile(models.Model):
   profile = models.OneToOneField(Profile, on_delete=models.CASCADE)
   # user type B fields

# ditto Type C User
Comedy option: just have one Profile and put all the fields on it for all three user types.

Has anyone done this? Any suggestions?
The second option sounds saner, because if you go with the first you're bound to get an A&C user at some point and then what do you do with two copies of Profile that may not actually match up?

I'd hang them directly off User as well, since all the lookups start from the User model. It saves an indirection User.get().Profile.OptionA.fields, and since the bulk of the profile data is going to be in one of the Options, it makes sense to make it a first-class relation.

I think using contrib.auth.User directly is deprecated for 2.0, they're trying to un-arcweld it from the core so that changing from usernames to email addresses doesn't require a complete database wipe. django.settings.USER_MODEL and get_user_model() are what they're recommending now, and it may make sense to make a custom User model, even if it's just User(contrib.auth.User): pass

I think I blew 6 hours attempting to un-gently caress migrations alone before I gave up and wiped them all and restarted at the point we added the custom model. At least the data wasn't too bad to manually import.

I don't remember the difference between a OneToOne and a unique foreign key - if you make a FK unique it warns you to switch to OtO but I don't think it requires every User to have a ProfileA, just that every ProfileA have a unique user. I know the last time I dealt with a non-optional relation the easiest way was to hang a signal on new_user and create the sub-profile at that point.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Harik posted:

PyCharm didn't win me over, yet. Doesn't help that web integration is pro-only and for small shops VS Community is legal (up to 5 people in a company) and free. I was just finding it a real pain to convert the project structure to what it wanted without starting from scratch. Next weekend I'll give it another go.

I don't know anything about the free version, but the only project structure PyCharm wants is the type of project structure you're supposed to have for Django projects anyway.

epswing
Nov 4, 2003

Soiled Meat
It appears that when I'm buidling a form dynamically, if I have an f = forms.CharField() and I set f.required = True, the requiredness of the field works as expected. But if I set f.max_length = 1, the lengthyness seems to be ignored (isn't caught by form.is_valid()). However if I create an f = forms.CharField(max_length=1), then max_length applies and works. Why can't I set max_length after creating the CharField?

This is on Django 1.11.

Ahz
Jun 17, 2001
PUT MY CART BACK? I'M BETTER THAN THAT AND YOU! WHERE IS MY BUTLER?!

epalm posted:

It appears that when I'm buidling a form dynamically, if I have an f = forms.CharField() and I set f.required = True, the requiredness of the field works as expected. But if I set f.max_length = 1, the lengthyness seems to be ignored (isn't caught by form.is_valid()). However if I create an f = forms.CharField(max_length=1), then max_length applies and works. Why can't I set max_length after creating the CharField?

This is on Django 1.11.

Pretty sure max_length isn't really a property of the class and just used as a kwarg on init. I have found dynamic form definition is often more work than it's worth if you can find an alternate method of achieving what you want.

porksmash
Sep 30, 2008
It looks like setting max_length does nothing without also adding the MaxLengthValidator to the field's validation list (which the constructor does for you if you supply the max_length kwarg) https://docs.djangoproject.com/en/1.11/_modules/django/forms/fields/#CharField

epswing
Nov 4, 2003

Soiled Meat

porksmash posted:

It looks like setting max_length does nothing without also adding the MaxLengthValidator to the field's validation list (which the constructor does for you if you supply the max_length kwarg) https://docs.djangoproject.com/en/1.11/_modules/django/forms/fields/#CharField

Ahz posted:

Pretty sure max_length isn't really a property of the class and just used as a kwarg on init. I have found dynamic form definition is often more work than it's worth if you can find an alternate method of achieving what you want.

Ah yeah, should've just looked at the source. I was confused because required and max_length appeared to behave differently. Thanks!

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Anyone bought Two Scoops for 1.11 yet?

Enough new info for the price of upgrading from the 1.8 version?

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Thermopyle posted:

Anyone bought Two Scoops for 1.11 yet?

Enough new info for the price of upgrading from the 1.8 version?

So, I realized my version (which I haven't opened in years) is for 1.5, so I went ahead and bought the latest version. I can heartily recommend Two Scoops of Django 1.11. It's got a ton of best-practices info. I like having it because Django has so many features that I'll go a long time without using parts of Django and its nice to have a reference for the "best" way to do different things.

There's a table of contents at that link to see what it covers...

Dominoes
Sep 20, 2007

Is there a template system that works for django that lets you wright full-up python in the Templates? I never liked how restricted Django templates are: simple things work, but anything else (calling functions, methods etc) requires setting up intermediate data structures or custom template tags in the Python code. React's JSX provides an alternative where you write full-up JS with HTML tags; it has none of the template system's limitations. For pages that don't require interaction, it'd be nice to have something as powerful as JSX but in Python; is this possible?

Dominoes fucked around with this message at 20:55 on Aug 12, 2017

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Dominoes posted:

Is there a template system that works for django that lets you wright full-up python in the Templates? I never liked how restricted Django templates are: simple things work, but anything else (calling functions, methods etc) requires setting up awkward data structures in the Python code. React's JSX spoiled me to the point where I don't want to touch Django Templates again. For pages that don't require interaction, it'd be nice to have something as powerful as JSX but in Python; is this possible?

FYI, that's antithetical to how templates should work according to the Django philosophy. Templates should be as dumb as possible.

Think of it like this: you're wanting logic and data structures and whatever in your template. You might say you want a programming language in your template.

The kicker is that you already have a programming language at your disposal, it's called python! Use python to construct your data and feed it to your templates.

This isn't exactly just a Django philsophy, just google around stuff about "logic in templates".

That being said Jinja2 does allow you to put more logic in your templates.

Also, I don't view JSX as a template language, but that's a wide-ranging debate discussed ad nauseum all over the internet.

Dominoes
Sep 20, 2007

Thanks. It feels awkward for me; I made many attempts to get used to this style, but never succeeded. I don't like bouncing back and forth between python code and templates when setting up how my page should look. Ie I may have something written in my template, but want to change something later that requires a function call; have to rewrite the whole thing in Python, then find a way to wrap it in a template-friendly dict etc. Or guess where I put the logic when looking at older code. I also don't like creating throw-away data structures for templates; ie I may have a consistent data structure or way of passing around info that's consistent throughout my program, that is incompatible with rigid templates.

I suspect this is similar to the front-end philosophy difference between React's JSX and Angular's templates; ie some people can't stand how JSX mixes program logic with UI.

Dominoes fucked around with this message at 22:48 on Aug 12, 2017

Data Graham
Dec 28, 2009

📈📊🍪😋



Something that I've only fairly recently come to make friends with is the notion of putting your derived data into @property methods in your models.

I used to chafe under the strictness of Django's templating logic, but once I realized the benefits of pushing as much logic as possible as far back toward the model as possible, a lot of what I had been trying to do at the template level simply stopped being necessary. Now those properties are reusable too.

grenada
Apr 20, 2013
Relax.

Thermopyle posted:

Anyone bought Two Scoops for 1.11 yet?

Enough new info for the price of upgrading from the 1.8 version?

Thanks for the tip. I'm working my way through the Mozilla Developer Network django tutuorial, and really love it so far.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

laxbro posted:

Thanks for the tip. I'm working my way through the Mozilla Developer Network django tutuorial, and really love it so far.

To be clear, Two Scoops isn't a Django tutorial, it's a collection of best practices.

In other words, it shouldn't be the first Django resource you read, but maybe the third or something like that.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Dominoes posted:

Thanks. It feels awkward for me; I made many attempts to get used to this style, but never succeeded. I don't like bouncing back and forth between python code and templates when setting up how my page should look. Ie I may have something written in my template, but want to change something later that requires a function call; have to rewrite the whole thing in Python, then find a way to wrap it in a template-friendly dict etc. Or guess where I put the logic when looking at older code. I also don't like creating throw-away data structures for templates; ie I may have a consistent data structure or way of passing around info that's consistent throughout my program, that is incompatible with rigid templates.

I suspect this is similar to the front-end philosophy difference between React's JSX and Angular's templates; ie some people can't stand how JSX mixes program logic with UI.

It sounds to me like you need to learn to embrace fat models, thin views, insubstantial templates.

Your models and model managers should be peppered with properties and methods for getting the data you want out of them. Your views should be doing the minimal amount possible.

To quote Two Scoops:

quote:

When deciding where to put a piece of code, we like to follow the “Fat Models, Utility Modules,
Thin Views, Stupid Templates” approach.
We recommend that you err on the side of putting more logic into anything but views and templates.
The results are pleasing. The code becomes clearer, more self-documenting, less duplicated, and a lot
more reusable. As for template tags and filters, they should contain the least amount of logic possible
to function.
We cover this further in:
Fat Models Section 6.7: Understanding Fat Models
Utility Modules Section 29.2: Optimize Apps With Utility Modules
Thin Views Section 8.5: Try to Keep Business Logic Out of Views
Stupid Templates I Section 13.9: Follow a Minimalist Approach
Stupid Templates II Chapter 14: Template Tags and Filters

Of course, you don't want your models to become unwieldy grab bags of code. So, you have to be on the lookout for ways to generalize ideas between models and pull that code out into helpers.

At some point it often becomes useful to think about your project from a domain-driven design viewpoint. Typically what this means for me is I have a services.py and/or a queries.py where I keep small and focused functions for doing things and asking things.

Split code into these modules by thinking in commands.

Given a Foo, when a user does Bar, then start thermonuclear war.

There's two types of queries you're probably concerned about. Presentational queries and business logic queries. Often, custom tags and filters work for presentational queries.

Python code:
@register.filter
def user_in_esperanto(user):
    return translate_api.translate(user.name)
For accessing or creating data for templates, you can also use proxy models.

For complex queries you have to create and access a lot, you can use query models which are basically a form of denormalization wherein you create/update them every time you create/update your "real" models. I usually use signals to update these query models, but I'm always feel a little icky about it because of the un-explicit, spooky action at a distance. You can also update them from your services.py functions.

These are all idea taken from domain driven design, so do some reading on that for some great ideas on how to organize your projects.

(i got turned on to this pattern in django from a great stackoverflow answer years ago but I can't seem to find it right now)

Thermopyle fucked around with this message at 18:48 on Aug 13, 2017

Dominoes
Sep 20, 2007

Thermopyle posted:

Split code into these modules by thinking in commands.

There's two types of queries you're probably concerned about. Presentational queries and business logic queries. Often, custom tags and filters work for presentational queries.

Python code:
@register.filter
def user_in_esperanto(user):
    return translate_api.translate(user.name)

Data Graham posted:

Something that I've only fairly recently come to make friends with is the notion of putting your derived data into @property methods in your models.
These cut to the core of what doesn't feel natural to me: The work done to make your data accessible to the view is performed in a preparatory way (special methods/properties in your models, specialized @register.filters, pre-computed data structures). To me, it makes more sense to keep the Python code (what you refer to as business logic?) generic, and write the view-specific code during the view itself; antithetical to the two-scoops snipped Therm quoted.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Dominoes posted:

These cut to the core of what doesn't feel natural to me: The work done to make your data accessible to the view is performed in a preparatory way (special methods/properties in your models, specialized @register.filters, pre-computed data structures). To me, it makes more sense to keep the Python code (what you refer to as business logic?) generic, and write the view-specific code during the view itself; antithetical to the two-scoops snipped Therm quoted.

I don't have time to type a lot right now, but one aspect of the purpose of putting it on the model or other utility modules is that you can't keep your code more generic by having it in your view.

I mean, if, as part of your view, you have code that does x, y, and z, how are you going to use that code elsewhere? What if you want a view later that wants x, y, and z along with other stuff?

Dominoes
Sep 20, 2007

Thermopyle posted:

I mean, if, as part of your view, you have code that does x, y, and z, how are you going to use that code elsewhere? What if you want a view later that wants x, y, and z along with other stuff?
I'm referring to code that's made specifically to accommodate Django's rigid templates; ie code that you don't need anywhere else. (register.filters, pre-computed data structures, modifications to the models etc)

huhu
Feb 24, 2006

Thermopyle posted:

So, I realized my version (which I haven't opened in years) is for 1.5, so I went ahead and bought the latest version. I can heartily recommend Two Scoops of Django 1.11. It's got a ton of best-practices info. I like having it because Django has so many features that I'll go a long time without using parts of Django and its nice to have a reference for the "best" way to do different things.

There's a table of contents at that link to see what it covers...

Would you recommend this book for me - I built one site in Django, got a contract for 4 months doing Flask, and now I have a full time job in Django starting in about a week and a half.

Adbot
ADBOT LOVES YOU

Hed
Mar 31, 2004

Fun Shoe
Yes I have bought every edition and like he says it's great reference for the corners of the framework you don't use every day.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply