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
minato
Jun 7, 2004

cutty cain't hang, say 7-up.
Taco Defender
Worth mentioning that if you're using virtualenv (which is very good idea) to develop Django apps, you specify the Python version with a flag when you create the env.

Adbot
ADBOT LOVES YOU

PT6A
Jan 5, 2006

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

minato posted:

Worth mentioning that if you're using virtualenv (which is very good idea) to develop Django apps, you specify the Python version with a flag when you create the env.

I'd say that goes beyond "very good idea" to "essentially malpractice to not do."

Hed
Mar 31, 2004

Fun Shoe

NtotheTC posted:

Is there a go-to e-commerce library for django that you guys use? Theres any number of them on django packages and django-oscar appears to be winning but popularity does not always trump experience

I really enjoyed cartridge when I was building those. I thought it was easy to implement, customize, and extend. Haven’t used it since 2015 but might be worth a look.

NtotheTC
Dec 31, 2007


What are you guys using for error logging these days? I liked Sentry but they seem very reticent to move off of python2.7 and django 1.6 and i cant decide if i should use it in a commercial setting because of that

Thermopyle
Jul 1, 2003

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

I've used papertrail, loggly, and my own ELK stack. All work fine.

I actually came in here to post something that I stumble across like once a year and then next time I want to find it I can't.

I give you a complete Django project:

code:
from django.http import HttpResponse
from django.conf.urls import url

DEBUG = True
ROOT_URLCONF = 'pico_django'
ALLOWED_HOSTS = '*'
DATABASES = {'default': {}}


def index(request, name):
    return HttpResponse('Hello {name}!'.format(name=(name or 'World')))

urlpatterns = [
    url(r'^(?P<name>\w+)?$', index)
]

SECRET_KEY = "not so secret"
For the next time someone is going on about how lightweight Flask is compared to Django...

epswing
Nov 4, 2003

Soiled Meat
I keep reading horror stories about those dev contractor sites. Where would be a reasonable place to look for a django dev to convert an old site from Python 2 and Django 1.11 using function-based views to Python 3 and Django 2.2 using class-based views? I'd like to jump from one LTS version to the next, and 2.2 has been pre-released (aiming to be fully released this April). It's a 24 page internal site, mostly just a LOB app with lists of records users can open, view, and edit.

I know exactly what I want, and is something I could do myself, but right now I have more money than time.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

epalm posted:

I keep reading horror stories about those dev contractor sites. Where would be a reasonable place to look for a django dev to convert an old site from Python 2 and Django 1.11 using function-based views to Python 3 and Django 2.2 using class-based views? I'd like to jump from one LTS version to the next, and 2.2 has been pre-released (aiming to be fully released this April). It's a 24 page internal site, mostly just a LOB app with lists of records users can open, view, and edit.

I know exactly what I want, and is something I could do myself, but right now I have more money than time.

It's intern season! Hire yourself an intern from a decent school and have them bang it out over the summer under your supervision.

porksmash
Sep 30, 2008

epalm posted:

I know exactly what I want, and is something I could do myself, but right now I have more money than time.

I have time and want money if you're open to a little contract, but I don't do gig sites like Upwork. Email me sa@porksmash.com if you want to discuss and I can send you some stuff I've made.

Business
Feb 6, 2007

I'm just learning and going through tutorials and I have a dumb question. When people work on a project in django, are they generally just VIMing or whatever around to the different things they need to edit each time they add something? I hope it's just a learning curve thing but I'm finding it hard to keep a 'map' of every file that needs to be edited each time I add a new page or template or whatever. Relatedly, is there a good way to keep track of your db models other than just keeping them in a text file?
I feel like I get how the pieces fit together over the course of a tutorial or whatever and debugging hasn't been bad but I'm having a hell of a time keeping up with all the moving parts even in a small project

Thermopyle
Jul 1, 2003

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

Business posted:

I'm just learning and going through tutorials and I have a dumb question. When people work on a project in django, are they generally just VIMing or whatever around to the different things they need to edit each time they add something? I hope it's just a learning curve thing but I'm finding it hard to keep a 'map' of every file that needs to be edited each time I add a new page or template or whatever. Relatedly, is there a good way to keep track of your db models other than just keeping them in a text file?
I feel like I get how the pieces fit together over the course of a tutorial or whatever and debugging hasn't been bad but I'm having a hell of a time keeping up with all the moving parts even in a small project

Where things go make sense if you understand how Django and web frameworks in general work.

The web server (nginx or apache) hands a web request to Django.

Django looks in urls.py to see which view function or class to hand the request to.

The view takes the template you specify and adds the data the template requires.

The view returns the rendered template, and Django passes it back to the web server.

Once you understand that it's never really a question of where you should add or edit stuff.

NtotheTC
Dec 31, 2007


I use an IDE for Django, maybe an Emacs or VIM expert could keep up but honestly I'd be lost without it. The gold standard is pycharm which has a free (community) version and a paid (professional) version. The community version unfortunately doesn't come with all the cool Django integration stuff but still allows you to see the project structure and bounce around the code so is going to be lightyears ahead of VIM.

I haven't used it personally so I can't vouch for it but possibly VScode as a free alternative? It's not going to come close to the paid version of pycharm but for hobby coding might be the easier choice.

The Fool
Oct 16, 2003


VS Code works fine and is what I use, it's even possible to setup pylint with Django within it.

Dominoes
Sep 20, 2007

Business posted:

I'm just learning and going through tutorials and I have a dumb question. When people work on a project in django, are they generally just VIMing or whatever around to the different things they need to edit each time they add something? I hope it's just a learning curve thing but I'm finding it hard to keep a 'map' of every file that needs to be edited each time I add a new page or template or whatever. Relatedly, is there a good way to keep track of your db models other than just keeping them in a text file?
I feel like I get how the pieces fit together over the course of a tutorial or whatever and debugging hasn't been bad but I'm having a hell of a time keeping up with all the moving parts even in a small project
Tabs in Pycharm

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice
VIM with bufferTabs. :colbert:

BaronVonVaderham
Jul 31, 2011

All hail the queen!
I can't seem to find this answer anywhere for some reason, and it seems like a really simple question:

In Django REST Framework, when using many=True in your serializer to support creation of multiple objects per request....is there a limit to the number of objects in a single request? Also is there a default rate limit for requests to an endpoint?

I don't know why none of this appears to be in their docs, their bit about multiple objects is just "build a serializer, user many=true" and that's about it.

Thermopyle
Jul 1, 2003

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

BaronVonVaderham posted:

I can't seem to find this answer anywhere for some reason, and it seems like a really simple question:

In Django REST Framework, when using many=True in your serializer to support creation of multiple objects per request....is there a limit to the number of objects in a single request? Also is there a default rate limit for requests to an endpoint?

I don't know why none of this appears to be in their docs, their bit about multiple objects is just "build a serializer, user many=true" and that's about it.

many=True actually uses ListSerializer.

ListSerializer just calls `create` for each item in the list, so the only limits you're going to run into is how long you want a request to take or how long before your web server shuts down the request.

BaronVonVaderham
Jul 31, 2011

All hail the queen!

Thermopyle posted:

many=True actually uses ListSerializer.

ListSerializer just calls `create` for each item in the list, so the only limits you're going to run into is how long you want a request to take or how long before your web server shuts down the request.

Thanks. We're doing some wonky extension of the serializer I guess (not my endpoint, I was asked to build this, then went digging and found it already exists), but cool, I'll just have to do some testing to see where that break point happens and then round that down or something to be safe. The guy on our CRM team asking about this, who requested the endpoint, seems to want to abuse this thing, so I probably need to really underestimate those limits.

epswing
Nov 4, 2003

Soiled Meat
Doesn’t look like I can use check as a field name, if it’s a foreign key. I get a SystemCheckError. However, the docs list only two restrictions on field names: A field name cannot be a Python reserved word, and cannot contain more than one underscore in a row.

https://stackoverflow.com/questions/54681167/django-model-field-name-check-raises-systemcheckerror

Are the docs wrong, or am I doing something wrong?

epswing fucked around with this message at 22:49 on Feb 14, 2019

CarForumPoster
Jun 26, 2013

⚡POWER⚡
I wanna start baby’s first Django project this week, basically displaying a subset of a pandas dataframe in a bootstrap table based on url strings.

I picked out a bootstrap theme I like.

I watched sentdex’s Django tutorials and it seems pretty doable. Copy paste some static stuff, add some jinja things, seems easy enough.

What are packages like this for? Would it make getting started easier?
https://pypi.org/project/django-bootstrap4/

My current website is with weebly and I’m thinking about redoing it. It’d be nice if my nontechnical cofounder can make minor edits with a WYSIWYG editor. Should I got for djangoCMS?

Is this useful: https://github.com/divio/djangocms-bootstrap4

Thermopyle
Jul 1, 2003

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

CarForumPoster posted:

I watched sentdex’s Django tutorials and it seems pretty doable. Copy paste some static stuff, add some jinja things, seems easy enough.

I wouldn't use jinja. Not because jinja is bad, but because Django already has its own template language that is as good or better.

CarForumPoster posted:

What are packages like this for? Would it make getting started easier?
https://pypi.org/project/django-bootstrap4/

I think it basically just adds some template tags that insert all the bootstrap boilerplate for you.

Whether its useful kinda depends on how familiar you are with Bootstrap. I find that if you're not familiar with BS, the extra level of abstraction that packages like this add can cause more confusion than they prevent.

On the other hand if you're familiar with BS, they can save you some typing I guess.

CarForumPoster posted:

Should I got for djangoCMS?

It really just depends on how complicated your CMS needs are.

I think maybe I'd try building what you need with django itself first.

epswing
Nov 4, 2003

Soiled Meat
I have a Car which has a custom reserve_car permission which is checked by a DRF view when a user tries to reserve a Car.

Here's a test which checks the permission works. The test passes and everything works fine.

Python code:
from rest_framework.test import APITestCase
from django.contrib.auth import get_user_model
User = get_user_model()

class CarTests(APITestCase):

    def test_reserve_car_permission(self):

        # set up a test user
        user = User.objects.create_user('user', 'user@example.com', 'secret')
        self.client.force_authenticate(user=user)

        # give user permission to add_car, but not reserve_car
        user.add_perm('myapp.add_car')
        user = User.objects.get(pk=user.id)
        self.client.force_authenticate(user=user) # re-authenticate
        self.assertTrue(user.has_perm('myapp.add_car'))
        self.assertFalse(user.has_perm('myapp.reserve_car'))

        # create a blank car
        data = {'name': 'Some Car'}
        response = self.client.post(car_list_url(), data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED, msg=json_error_response(response))
        car_id = response.data['id']

        # try to reserve the car, should fail because user doesn't have reserve_car permission
        response = self.client.post(carreserve_detail_url(car_id))
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN, msg='User should not have permission')
        self.assertEqual(response.data['detail'], 'You do not have permission to perform this action.')

        # add the reserve_car permission to the user
        user.add_perm('myapp.reserve_car')
        user = User.objects.get(pk=user.id)
        self.client.force_authenticate(user=user) # re-authenticate
        self.assertTrue(user.has_perm('myapp.add_car'))
        self.assertTrue(user.has_perm('myapp.reserve_car'))

        # try again to reserve the car, should pass now
        response = self.client.post(carreserve_detail_url(car_id))
        self.assertEqual(response.status_code, status.HTTP_200_OK, msg=json_error_response(response))
Apparently the client must re-authenticate when permissions are added (once when myapp.add_car is added, and later when myapp.reserve_car is added). If I remove the 2nd and 3rd self.client.force_authenticate(user=user) lines, the test fails as if the user hasn't been give any permissions.

Does this mean if a user of my api is given a new permission (or has a permission taken away), it won't take affect until they request a new api token? Is the server caching user permissions? Or just the test framework is caching user permissions?

epswing fucked around with this message at 14:50 on May 30, 2019

Data Graham
Dec 28, 2009

📈📊🍪😋



I'm having problems with session cookies disappearing after an HttpResponseRedirect.

I'm overriding the built-in password recovery views, which do this when you click on the emailed token link (django.contrib.auth.views.PasswordResetConfirmView):

code:
INTERNAL_RESET_URL_TOKEN = 'set-password'
INTERNAL_RESET_SESSION_TOKEN = '_password_reset_token'

...

        self.validlink = False
        self.user = self.get_user(kwargs['uidb64'])

        if self.user is not None:
            token = kwargs['token']
            if token == INTERNAL_RESET_URL_TOKEN:
                session_token = self.request.session.get(INTERNAL_RESET_SESSION_TOKEN)
                if self.token_generator.check_token(self.user, session_token):
                    # If the token is valid, display the password reset form.
                    self.validlink = True
                    return super().dispatch(*args, **kwargs)
            else:
                if self.token_generator.check_token(self.user, token):
                    # Store the token in the session and redirect to the
                    # password reset form at a URL without the token. That
                    # avoids the possibility of leaking the token in the
                    # HTTP Referer header.
                    self.request.session[INTERNAL_RESET_SESSION_TOKEN] = token
                    redirect_url = self.request.path.replace(token, INTERNAL_RESET_URL_TOKEN)
                    return HttpResponseRedirect(redirect_url)

        # Display the "Password reset unsuccessful" page.
        return self.render_to_response(self.get_context_data())
So what happens is, you come in with a URL like reset/MjU0MDJ/56t-6f0eeb72ba42f34ce946/, where 'uidb64' is 'MjU0MDJ' and 'token' is '56t-6f0eeb72ba42f34ce946'. It looks up the userid via base64 decoding in get_user(), and then does the above logic. 'token' is not 'set-password', so it does the 'else' block, where it sets the token in your session, and then redirects you to the url reset/MjU0MDJ/set-password/. This goes through the same logic again, but this time finds the token in the session and does the 'if' block above, resulting in the password reset form.

However, in my setup, after it sets the token in the session cookie and issues the redirect, the resulting /set-password/ page has NO session cookies. No cookies at all, in fact. So they get the "yo you followed a bogus link" page.

If I copy the same URL into a new browser window, it DOES have the session cookie, and it renders the reset form properly. So it's setting the session value properly. But the cookie is being lost during the 302 redirect somehow.

I've tried fiddling with SESSION_COOKIE_DOMAIN and SESSION_COOKIE_SECURE (this is a production server with a valid SSL cert, and all the URLs are using [url]https://[/url] with the same hostname), to no avail.

I'm not finding anything addressing this in the usual places. Django 2.1.7, Python 3.6.

Anyone dealt with this? I feel like it must be familiar ground for some of us.


E: I should note that this worked perfectly fine in Django 1.11 and earlier. I just recently upgraded to Dj2 and Py3, and this apparently stopped working right then.

Data Graham fucked around with this message at 02:40 on Jun 1, 2019

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Data Graham posted:

I'm having problems with session cookies disappearing after an HttpResponseRedirect.

I'm overriding the built-in password recovery views, which do this when you click on the emailed token link (django.contrib.auth.views.PasswordResetConfirmView):

[code]
If I copy the same URL into a new browser window, it DOES have the session cookie, and it renders the reset form properly. So it's setting the session value properly. But the cookie is being lost during the 302 redirect somehow.

What's the cookie path? Unless a path is specified, a cookie is only going to match the document where you set the cookie.

Data Graham
Dec 28, 2009

📈📊🍪😋



The path is / (default).

Anyway what the fuuuuuuck. Further blind poking has revealed that this behavior ONLY happens when I'm following the email link by clicking on it IN iCloud mail IN Safari.

In other words if I paste the un-redirected URL (with the live token) straight into the browser, the cookie gets set fine and persists through the redirect, and I get the reset form.

The problem doesn't happen if I make a raw HTML page with the link in it on my local box and open it locally in Safari, nor if I put that page on a webserver and open it remotely in Safari. It doesn't happen if I click an activated link in any non-web application (like Notes). It doesn't happen in iCloud mail in Chrome.

Apparently iCloud Mail is doing some kind of goofy javascript witchery on its activated links ...? Ugh.

KICK BAMA KICK
Mar 2, 2009

Is there a pattern for defining a ModelAdmin to handle the shared fields for Models that share an abstract base and then also the stuff specific to the child Models? My first guess is define a ModelAdmin that handles the common stuff and subclass it for each child model with the specific stuff and register the child ModelAdmins to the child Models but idk how far you can take that -- at first glance it probably works for say setting some shared readonly_fields but I'm not sure about more complicated layout and stuff?

Hed
Mar 31, 2004

Fun Shoe
Has anyone been deploying on AWS lambda? Seems cool but I’m a little unclear if best practice is still to mess with Cookiecutter templates then install Zappa or just go with the default

punished milkman
Dec 5, 2018

would have won
I've got a noob question. I see people online often recommending using React + Django or Vue + Django for a development stack... are these people pretty much exclusively referring to using DRF to create an API that your front end talks to? Or is there some other approach I'm not aware of?

NtotheTC
Dec 31, 2007


There are halfway-house integration libraries out there that convert django widgets into react components automagically but they're almost always more trouble than they're worth in the long run. My personal approach is API and a separate frontend

Thermopyle
Jul 1, 2003

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

punished milkman posted:

are these people pretty much exclusively referring to using DRF to create an API that your front end talks to?

Yeah.

epswing
Nov 4, 2003

Soiled Meat
Here's a pretty standard setup for a nested writeable serializer, which allows the client to GET a user, and PUT it back with a different set of groups:

Python code:
class GroupDetailSerializer(serializers.ModelSerializer):
    class Meta:
        model = Group
        fields = ('id', 'name',)
        
class UserDetailSerializer(serializers.ModelSerializer):
    groups = GroupDetailSerializer(many=True)
    class Meta:
        model = User
        fields = ('id', 'username', 'groups')
    
    @transaction.atomic
    def update(self, instance, validated_data):
        # snip.. remove all group assignments here
        groups = validated_data.pop('groups')
        super().update(instance, validated_data)
        # snip.. establish new group assignments here
        return instance
When I GET a user, it looks like this:

pre:
{
    "id": 1,
    "username": "user"
    "groups": [
        {
            "id": 1,
            "name": "G1"
        },
        {
            "id": 2,
            "name": "G2"
        }
    ],
}
And I can PUT this user containing a different set of dictionaries of groups, and things will update correctly (by blowing away existing group assignments, and establishing new ones that were provided). That all works.

But what I'd like to do, because the group model is small/simple with a unique name field, is be able to GET a user like this:
pre:
{
    "id": 1,
    "username": "user"
    "groups": ["G1", "G2"],
}
and PUT a user with modified groups like this:
pre:
{
    "id": 1,
    "username": "user"
    "groups": ["G1", "G3", "G4"],
}
Group names are unique, and in the user serializer's update function, I'd just look up groups by name instead of pk. What I don't understand is how to configure GroupDetailSerializer. Should that be a ListSerializer? In other words how can I GET/PUT a list of strings rather than a list of dictionaries?

epswing fucked around with this message at 03:22 on Jul 6, 2019

epswing
Nov 4, 2003

Soiled Meat
Not sure if this is the right answer, but what I did was add a group_names property to User:
Python code:
class User(AbstractUser):

    @property
    def group_names(self):
        return [group.name for group in self.groups.all()]
And reference it in the serializer:
Python code:
class UserDetailSerializer(serializers.ModelSerializer):
    groups = StringListField(source='group_names')
    class Meta:
        model = User
        fields = ('id', 'username', 'groups')
Where StringListField is a ListField with a CharField child:
Python code:
class StringListField(serializers.ListField):
    child = serializers.CharField()
So on the way out (GET) the client gets an array of str group names ["G1", "G2"], and on the way in (PUT) you just validated_data.pop('group_names') and there's your ["G1", "G3", "G4"] input.

Seems to work, didn't need ListSerializer in the end.

CarForumPoster
Jun 26, 2013

⚡POWER⚡
I think it was in this thread that someone had an issue with their site loading already "pre scrolled down" or in the middle of the page. I'm having the same issue, does this ring a bell to anyone?

Hed
Mar 31, 2004

Fun Shoe
What are people's opinions on using UUIDs everywhere as the primary key?

I'm starting a new Django project and while the framework has made it easy for a long time, I've seen mixed ideas on the Internet: that using UUIDs is both terrible and fine. For now I'm giving models that are going to be on my REST interface (which is most of them) an additional field that is based on the ShortUUID from Django extensions. Still, carting both around and dorking around with Django-REST-Framework to use both PKs and UUIDs seems a little silly.

Data Graham
Dec 28, 2009

📈📊🍪😋



I just changed the one-and-only model in my latest project whose pk's are user-facing to UUIDs.

That is the main reason I would do it — it avoids exposing integer IDs as an attack facet (so some wiseguy doesn't just go "hey my ID is 1142, I wonder if I can make this same API call to 1141 and see if I get someone else's stuff").

I wouldn't use a UUID in addition to a pk though. Just make your UUIDField (or ShortUUIDField) your pk and be done with it.

NtotheTC
Dec 31, 2007


I always liked this article about readable URLs too: https://wellfire.co/learn/fast-and-beautiful-urls-with-django/

only applies if you care what the user sees in the url bar though

porksmash
Sep 30, 2008
I use UUID primary keys often and like it, especially if it's user facing so they can't guess neighboring rows. It makes no sense to me to have a regular integer PK AND a UUID in a different indexed column, especially if the UUID will be the primary lookup column.

From my research postgresql suffers no performance impacts other than the fact that a uuid requires more storage than an int/bigint. I have not noticed any issues including tables with 10mil+ rows. Dunno anything about other DB engines though.

Data Graham
Dec 28, 2009

📈📊🍪😋



Aside though, thanks for the tip on ShortUUIDField (and django-extensions). I like having a uuid that isn't so obviously one.

I was just on the verge of writing my own to do basically the same thing but :yayclod:

Data Graham fucked around with this message at 22:17 on Aug 10, 2019

epswing
Nov 4, 2003

Soiled Meat
I use https://hashids.org to mitigate the “modify the url to find other records” problem.

NtotheTC
Dec 31, 2007


I mean, you guys use permissions all the time anyway right so URL modding isn't an issue? :v:

Adbot
ADBOT LOVES YOU

Data Graham
Dec 28, 2009

📈📊🍪😋



There’s other kinds of opsec than making sure user=request.user but yeah :haw:

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