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
Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Jo posted:

I've got a Postgres database and Django 1.7. I'm adding a non-null foreign key to auth_group to my model Thingy. When makemigrations runs, I see the AddField with correct attributes. Unfortunately, it looks like Postgres is just entirely ignoring the migration for reasons I don't understand. It completes, but afterwards it seems like the changes haven't actually taken place. When I do 'sqlmigrate', I don't see the default group in the migration. Am I SOL as far as that's concerned? I can get around it by just writing the raw SQL, but I'd rather not.

Just to be sure, you are doing:

code:
python manage.py makemigrations thingie
python manage.py migrate thingie
Makemigrations doesn't actually change anything.

Adbot
ADBOT LOVES YOU

duck monster
Dec 15, 2004

Karthe posted:

I'm going to allow end users to POST CSV text to the server to enable bulk user creation. For this I'm going to have a CreateAPIView that takes in the CSV, sanitizes it, then validates each line before iterating through and creating each user. What's the best way of sanitizing the input before doing anything with it? Is this a case for some basic regex? Does Django include anything that could help, something akin to PHP's htmlspecialchars()?

I'm going to set it up so that the end user submits a file containing lines in this format:
pre:
first name, last name, email, phone number, location, station, pay rate, skills
Alma,Bailey,abailey@domain.com,7145550189,West Los Angeles,Cashier,10.50,Books
The only special characters I can think (aside from the commas) that might be necessary are @, . (period), and -. Everything else should be covered by [A-Za-z0-9].

You can abuse the form system for this. Create a form object, manually stuff it from your csv and then run the validations on it. Seems to work well when I've done it that way, anyway.

Jo
Jan 24, 2005

:allears:
Soiled Meat

Lumpy posted:

Just to be sure, you are doing:

code:
python manage.py makemigrations thingie
python manage.py migrate thingie
Makemigrations doesn't actually change anything.

Yes. I can see the created migration, too.

MonkeyMaker
May 22, 2006

What's your poison, sir?

duck monster posted:

You can abuse the form system for this. Create a form object, manually stuff it from your csv and then run the validations on it. Seems to work well when I've done it that way, anyway.

Just for the record, this isn't abuse at all. The forms library is, IMO, misnamed and should really be the validations library. The fact that it can render an HTML form is just a happy by-product.

IAmKale
Jun 7, 2007

やらないか

Fun Shoe
I tried creating an object via a Serializer but the way I did it left me confused.

I used a basic ModelSerializer:
Python code:
class LocationSerializer(serializers.ModelSerializer):
    company = serializers.StringRelatedField()

    class Meta:
        model = Location
To create a new Location:
Python code:
class Location(models.Model):
    company = models.ForeignKey(Company)
    title = models.CharField(max_length=100)
But when I try to assign a company in the initial data argument, the Serializer appears to ignore it
pre:
>>> lo = LocationSerializer(data={'title': 'Test Location', 'company': co.instance.id})
>>> lo.is_valid()
True
>>> lo.validated_data
OrderedDict([('title', 'Test Location')])
>>> lo.save()
Traceback (most recent call last):
...snip...
DETAIL:  Failing row contains (48, Test Location, null).
The only way I could get the object to save was to declare the company when I call save():
pre:
>>> lo.save(company=co.instance)
<Location: TEST COMPANY - Test Location>
Am I doing something wrong where I can't declare the company in the data payload? Or is this normal?

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Karthe posted:

I tried creating an object via a Serializer but the way I did it left me confused.

I used a basic ModelSerializer:
Python code:
class LocationSerializer(serializers.ModelSerializer):
    company = serializers.StringRelatedField()

    class Meta:
        model = Location
To create a new Location:
Python code:
class Location(models.Model):
    company = models.ForeignKey(Company)
    title = models.CharField(max_length=100)
But when I try to assign a company in the initial data argument, the Serializer appears to ignore it
pre:
>>> lo = LocationSerializer(data={'title': 'Test Location', 'company': co.instance.id})
>>> lo.is_valid()
True
>>> lo.validated_data
OrderedDict([('title', 'Test Location')])
>>> lo.save()
Traceback (most recent call last):
...snip...
DETAIL:  Failing row contains (48, Test Location, null).
The only way I could get the object to save was to declare the company when I call save():
pre:
>>> lo.save(company=co.instance)
<Location: TEST COMPANY - Test Location>
Am I doing something wrong where I can't declare the company in the data payload? Or is this normal?


According to the docs, normal.

Asymmetrikon
Oct 30, 2009

I believe you're a big dork!
I've been writing an API using Django Rest Framework, and I've hit a wall with permissions.

I have three models, Account, UserProfile, and Campaign. UserProfile is one-to-one with the default Django User, and has a foreign key to the Account to which it belongs. Campaign also has a foreign key to its Account. In the API, each of these has a HyperlinkedModelSerializer and a viewset pointing at it.

I'd like to make it so that a user can only post a Campaign if the Campaign's 'account' field points to the same Account as the requesting user's UserProfile's account. As far as I can tell, though, to get the Account that the post request's url maps to, I have to override the .create() method on the Campaign Serializer. I can't find out how to get the requesting user at that point, though.

Am I missing something trivial? It seems like there has to be a way to do this.

Edit: Nevermind, it turns out you can get it through self.context['request'].user.

Asymmetrikon fucked around with this message at 03:37 on Sep 20, 2015

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

Asymmetrikon posted:

I've been writing an API using Django Rest Framework, and I've hit a wall with permissions.

I have three models, Account, UserProfile, and Campaign. UserProfile is one-to-one with the default Django User, and has a foreign key to the Account to which it belongs. Campaign also has a foreign key to its Account. In the API, each of these has a HyperlinkedModelSerializer and a viewset pointing at it.

I'd like to make it so that a user can only post a Campaign if the Campaign's 'account' field points to the same Account as the requesting user's UserProfile's account. As far as I can tell, though, to get the Account that the post request's url maps to, I have to override the .create() method on the Campaign Serializer. I can't find out how to get the requesting user at that point, though.

Am I missing something trivial? It seems like there has to be a way to do this.

Edit: Nevermind, it turns out you can get it through self.context['request'].user.

I've been using Django for a couple years now and every now and then I try to ease myself into the convenience of modelforms, modelserializers, class based views etc. but every time I do, I find when I want to do something interesting or outside the box, I hit a wall and go into an override frenzy where I should have just used basic forms or serializers and function based views where I have total control.

I guess my point it, these viewsets and fancy serializers are great for simple use cases, but aren't worth the trouble later, IMO.

Guess what? self.context request is only available if you use their view sets by the way. An example hack is where I had to nest 3 serializers into each other just to update a couple related tables in one PUT request and then realized I had no user obj into the serializer any more. I had to then pass Request around like a football just to get a logged in user into an Update() override.

Data Graham
Dec 28, 2009

📈📊🍪😋



Ahz posted:

I've been using Django for a couple years now and every now and then I try to ease myself into the convenience of modelforms, modelserializers, class based views etc. but every time I do, I find when I want to do something interesting or outside the box, I hit a wall and go into an override frenzy where I should have just used basic forms or serializers and function based views where I have total control.

Phew, I thought I was the only one.

The last couple of Django jobs, I've inherited systems that had been thoroughly and carefully built by-the-book, with serializers, viewsets, on-model methods, the whole nine yards. But I always end up spending ten times as much time unraveling them and figuring out where to make simple logic tweaks as I would have if I'd just done it the way I did three jobs ago when none of us knew what we were doing and we just made a pile of monolithic function-based view.py's. It might have been ugly and repetitive and low in code reuse, but drat if we weren't cranking out new features daily. And drat if the guy they hired to pick up after I left wasn't up and running in a matter of days.

Never mind how in some of these more recent jobs I've found myself confronting viewset-generated API endpoints that spit out hundreds of times more data than is necessary, with programmatically generated queries that take many seconds to complete and then many more seconds just to transport and serialize before it even starts spewing to the browser. All conscientious and by-the-book, mind you. But it's not just that it was unoptimized, it's that the system never seemed to give the original devs any indication that they should optimize it.

Thermopyle
Jul 1, 2003

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

I haven't done much Django except a little maintenance since 1.6 was the newest version. Getting ready to dive into some new projects and was just wondering if anyone has been keeping up with the 2 Scoops of Django books and if they do a good job of covering the best practices that have changed since 1.6? I've always liked the books but it's been a couple years since I picked up a copy...

Also if anyone has anything to say about changes since 1.6, I'll listen.

The March Hare
Oct 15, 2006

Je rêve d'un
Wayne's World 3
Buglord

Thermopyle posted:

I haven't done much Django except a little maintenance since 1.6 was the newest version. Getting ready to dive into some new projects and was just wondering if anyone has been keeping up with the 2 Scoops of Django books and if they do a good job of covering the best practices that have changed since 1.6? I've always liked the books but it's been a couple years since I picked up a copy...

Also if anyone has anything to say about changes since 1.6, I'll listen.

Migrations are the biggest change since 1.6 I think, so get familiar w/ them (it's great).

Hed
Mar 31, 2004

Fun Shoe

Thermopyle posted:

I haven't done much Django except a little maintenance since 1.6 was the newest version. Getting ready to dive into some new projects and was just wondering if anyone has been keeping up with the 2 Scoops of Django books and if they do a good job of covering the best practices that have changed since 1.6? I've always liked the books but it's been a couple years since I picked up a copy...

Also if anyone has anything to say about changes since 1.6, I'll listen.

Y'know I got the 1.8 book because why not but I really haven't referred to it all that much. I think the stuff I've used is mainly their thoughts on caching frameworks and the new Postgres-specific features. There is some good stuff on deploying to SaaS/IaaS places but I think you have that down.

Jo
Jan 24, 2005

:allears:
Soiled Meat

Thermopyle posted:

I haven't done much Django except a little maintenance since 1.6 was the newest version. Getting ready to dive into some new projects and was just wondering if anyone has been keeping up with the 2 Scoops of Django books and if they do a good job of covering the best practices that have changed since 1.6? I've always liked the books but it's been a couple years since I picked up a copy...

Also if anyone has anything to say about changes since 1.6, I'll listen.

South is rotting in hell and we revel in its tears. Warn on invalid prefetch_related kicks rear end.

Thermopyle
Jul 1, 2003

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

PyCharm 5.0 does more introspection into models:

epswing
Nov 4, 2003

Soiled Meat
models.py
Python code:
class Player(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField(max_length=50)

class Tournament(models.Model):
    name = models.CharField(max_length=50)

class TournamentPlayer(models.Model):
    tournament = models.ForeignKey(Tournament)
    player = models.ForeignKey(Player)
    paid = models.BooleanField()
admin.py
Python code:
class TournamentPlayerInline(admin.TabularInline):
    model = TournamentPlayer
    fields = ('player', 'paid') # want to display player email too!
    
@admin.register(Tournament)
class TournamentAdmin(admin.ModelAdmin):
    inlines = [TournamentPlayerInline]
I have an Inline question. When I pull up a Tournament in the Admin Site, I can see which players are going, and if they paid. I would also like to display extra information contained in Player, for example email address. In TournamentPlayerInline I thought I might be able to get away with
Python code:
fields = ('player', 'player__email', 'paid')
but no dice. How can I access Player properties from TournamentPlayerInline?

IAmKale
Jun 7, 2007

やらないか

Fun Shoe
Someone correct me if I'm wrong but I think you can do something like this in your TournamentPlayer serializer:

Python code:
class TournamentPlayerSerializer(serializers.ModelSerializer):
    player = PlayerSerializer(many=False, required=False)
Then instead of a key your "player" field will contain all of the info you'd normally get back from your PlayerSerializer.

This might also be useful in figuring out a solution: http://www.django-rest-framework.org/api-guide/relations/#nested-relationships

IAmKale fucked around with this message at 22:42 on Oct 5, 2015

epswing
Nov 4, 2003

Soiled Meat

Karthe posted:

TournamentPlayerSerializer

I'm not sure I understand. Where would TournamentPlayerSerializer go, exactly?

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

epalm posted:

I'm not sure I understand. Where would TournamentPlayerSerializer go, exactly?

I think he thinks you are using Django Rest Framework.

IAmKale
Jun 7, 2007

やらないか

Fun Shoe

epalm posted:

I'm not sure I understand. Where would TournamentPlayerSerializer go, exactly?

Lumpy posted:

I think he thinks you are using Django Rest Framework.
Sorry, that's exactly what happened. I forgot that this is a general Django thread, not specifically for Rest Framework :downs:

Eleeleth
Jun 21, 2009

Damn, that is one suave eel.

epalm posted:

models.py
Python code:
class Player(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField(max_length=50)

class Tournament(models.Model):
    name = models.CharField(max_length=50)

class TournamentPlayer(models.Model):
    tournament = models.ForeignKey(Tournament)
    player = models.ForeignKey(Player)
    paid = models.BooleanField()
admin.py
Python code:
class TournamentPlayerInline(admin.TabularInline):
    model = TournamentPlayer
    fields = ('player', 'paid') # want to display player email too!
    
@admin.register(Tournament)
class TournamentAdmin(admin.ModelAdmin):
    inlines = [TournamentPlayerInline]
I have an Inline question. When I pull up a Tournament in the Admin Site, I can see which players are going, and if they paid. I would also like to display extra information contained in Player, for example email address. In TournamentPlayerInline I thought I might be able to get away with
Python code:
fields = ('player', 'player__email', 'paid')
but no dice. How can I access Player properties from TournamentPlayerInline?

All you need to do here is add a method to your TournamentPlayer Model that returns the player email, then reference that field in your inlines, like so:

models.py
Python code:
class Player(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField(max_length=50)

class Tournament(models.Model):
    name = models.CharField(max_length=50)

class TournamentPlayer(models.Model):
    tournament = models.ForeignKey(Tournament)
    player = models.ForeignKey(Player)
    paid = models.BooleanField()
   
    def player_email(self):
        return self.player.email
admin.py
Python code:
class TournamentPlayerInline(admin.TabularInline):
    model = TournamentPlayer
    fields = ('player', 'paid', 'player_email')
    
@admin.register(Tournament)
class TournamentAdmin(admin.ModelAdmin):
    inlines = [TournamentPlayerInline]

epswing
Nov 4, 2003

Soiled Meat

Eleeleth posted:

All you need to do here is add a method to your TournamentPlayer Model that returns the player email, then reference that field in your inlines, like so:

Tried that!

I get FieldError: Unknown field(s) (player_email) specified for TournamentPlayer

Django 1.8.4

Ongoing SO post here: http://stackoverflow.com/questions/32972838

epswing fucked around with this message at 17:22 on Oct 6, 2015

Eleeleth
Jun 21, 2009

Damn, that is one suave eel.

epalm posted:

Tried that!

I get FieldError: Unknown field(s) (player_email) specified for TournamentPlayer

Django 1.8.4

Ongoing SO post here: http://stackoverflow.com/questions/32972838

I see my mistake. It'll work as I specified, with one edit: player_email needs to be specified in both fields and readonly_fields. I'll elaborate in an SO answer.

epswing
Nov 4, 2003

Soiled Meat

Eleeleth posted:

I see my mistake. It'll work as I specified, with one edit: player_email needs to be specified in both fields and readonly_fields. I'll elaborate in an SO answer.

Woo, thanks!

Edit: I must say, Django's Admin Site is a beautiful piece of usable software.

epswing fucked around with this message at 06:42 on Oct 7, 2015

IAmKale
Jun 7, 2007

やらないか

Fun Shoe
Where in Rest Framework should a check go to see if a user is trying to create a number of objects in excess of their allocated quota? For example, if a user is licensed to create 5 records but tries to make a 6th, I want to deny the request and tell them that they can't make any more.

Should this kind of check go into a Serializer, or a View? I'm currently leaning towards implementing it in the object Serializer's create() method.

Eleeleth
Jun 21, 2009

Damn, that is one suave eel.
Wouldn't that be best implemented as a custom permission?

IAmKale
Jun 7, 2007

やらないか

Fun Shoe

Eleeleth posted:

Wouldn't that be best implemented as a custom permission?
It certainly would, and it certainly did. Thank you for that.

Jo
Jan 24, 2005

:allears:
Soiled Meat
I'm having trouble coming up with a query because of the ORM's lack of "not equals". We have an existing dataset used by other applications internally, so I didn't define the data model, but each row has an id and a 'next' which points to another ID or itself.

Here's my sample data:

ID NEXT
1 2
2 2
3 4


In this case, I would like to return {2, 3} since 1 is outdated and replaced by 2. 3 is also outdated by 4, but 4 isn't in our current query set.

If it supported not equals, I imagine I'd do queryset.exclude(Q(next__in=queryset) & Q(next__notequal=F('id')). It seems really hacky to do in=queryset) & (Q(next__lt=F('id') | Q(next__gt=F('id'))). Can anyone think of a less gross way?

Data Graham
Dec 28, 2009

📈📊🍪😋



Can't you do ~Q(next=F('id') ?

Jo
Jan 24, 2005

:allears:
Soiled Meat

Data Graham posted:

Can't you do ~Q(next=F('id') ?

:doh:

Probably.

Dominoes
Sep 20, 2007

I'm setting up a simple database of books, and am looking for advice on database design.

I'm leaning towards having a separate entry with a unique ISBN, with a field that links each entry to other entries that are of the same work. How would I set up this relationship? It's somewhat like a ManyToMany, but with items of the same table.

An alternative setup would be to have one entry for each work, with different ISBNs for each edition or w/e causes works to be fragmented. Or two tables, one with Works and a second for ISBNs, and a ManyToOne relationship of ISBNs to Works. How would y'all set this up, and if I went with my first option, how do you actually code a ManyToMany with the same table?

Mata
Dec 23, 2003

Dominoes posted:

How would y'all set this up, and if I went with my first option, how do you actually code a ManyToMany with the same table?

If each work has one or more ISBNs, I would suggest dividing them up between two tables, to minimize data redundancy. If you want to go with the first option, you still need a second table to model the relationships within the first table. I did a similar thing where I want users to have relationships with other users (e.g. you can block users or add them as friends) for which I created a "Relationship" table where each row describes the relationship between two users:

code:
class ClientUser(models.Model): 
   relationships = models.ManyToManyField('self', symmetrical=False, through='Relationship')

class Relationship(models.Model):
    from_clientuser = models.ForeignKey(ClientUser, related_name='from_clientuser')
    to_clientuser = models.ForeignKey(ClientUser, related_name='to_clientuser')
    status = models.IntegerField(choices=RELATIONSHIP_STATUSES)

Dominoes
Sep 20, 2007

Mata posted:

If each work has one or more ISBNs, I would suggest dividing them up between two tables, to minimize data redundancy. If you want to go with the first option, you still need a second table to model the relationships within the first table. I did a similar thing where I want users to have relationships with other users (e.g. you can block users or add them as friends) for which I created a "Relationship" table where each row describes the relationship between two users:

code:
class ClientUser(models.Model): 
   relationships = models.ManyToManyField('self', symmetrical=False, through='Relationship')

class Relationship(models.Model):
    from_clientuser = models.ForeignKey(ClientUser, related_name='from_clientuser')
    to_clientuser = models.ForeignKey(ClientUser, related_name='to_clientuser')
    status = models.IntegerField(choices=RELATIONSHIP_STATUSES)
That looks like a good way to solve this.

Here's what the two-table approach I described looks like:
Python code:
class Work(models.Model):
    title = models.CharField(max_length=255)
    author = models.CharField(max_length=255)


class ISBN(models.Model):
    isbn10 = models.TextField(unique=True)
    isbn13 = models.TextField(unique=True)
    publication_date = models.DateField()
    work = models.ForeignKey(Work)

Dominoes fucked around with this message at 15:47 on Oct 9, 2015

porksmash
Sep 30, 2008
Is there a way to use django-autocomplete-light with integer fields with choices specified? In the example below I'd like to be able to type 'first' and get a list of objects that have the_choices=1.

code:
CHOICE_FIRST = 1
CHOICE_SECOND = 2
CHOICE_THIRD = 3

CHOICES = (
    (CHOICE_FIRST, 'First'),
    (CHOICE_SECOND , 'Second'),
    (CHOICE_THIRD , 'Third'),
)

the_choices = models.IntegerField(choices=CHOICES)

Dominoes
Sep 20, 2007

Checkout enumfields

I'm looking for advice on querying a Django Postgres database based on string similarity. One approach would be to query all objects in the database, then use the builtin difflib library on the results, but that would be slower than a natural query. Is there any way to do this using a query?

Dominoes fucked around with this message at 13:30 on Oct 22, 2015

IAmKale
Jun 7, 2007

やらないか

Fun Shoe
Will I run into any issues attempting to set a string to a ForeignKey field if the referenced foreign model is deleted?

Something like this:
Python code:
class Foo(models.Model):
    confirmed_location = models.ForeignKey(Location, on_delete=models.SET(get_location_title))

    def get_location_title():
        return self.confirmed_location.title
I want to allow for Locations to be deleted, but I also want to leave enough info in its related Foo objects for someone to go back later and understand that, "oh, they belonged to this old location".

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Dominoes posted:

Checkout enumfields

I'm looking for advice on querying a Django Postgres database based on string similarity. One approach would be to query all objects in the database, then use the builtin difflib library on the results, but that would be slower than a natural query. Is there any way to do this using a query?

Probably have to use some raw sql to get to the more advanced functions, I would imagine: http://www.postgresql.org/docs/9.5/static/fuzzystrmatch.html

good jovi
Dec 11, 2000

'm pro-dickgirl, and I VOTE!

Karthe posted:

Will I run into any issues attempting to set a string to a ForeignKey field if the referenced foreign model is deleted?

Something like this:
Python code:
class Foo(models.Model):
    confirmed_location = models.ForeignKey(Location, on_delete=models.SET(get_location_title))

    def get_location_title():
        return self.confirmed_location.title
I want to allow for Locations to be deleted, but I also want to leave enough info in its related Foo objects for someone to go back later and understand that, "oh, they belonged to this old location".

Yes, you will have issues. In any database I've ever used, foreign keys are just integer fields with some extra constraints, so you won't be able to shove a string in there. Just add another field to store notes in.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

good jovi posted:

Yes, you will have issues. In any database I've ever used, foreign keys are just integer fields with some extra constraints, so you won't be able to shove a string in there. Just add another field to store notes in.

Another option might be to do a 'soft delete' with some sort of active/inactive field on the record

good jovi
Dec 11, 2000

'm pro-dickgirl, and I VOTE!

fletcher posted:

Another option might be to do a 'soft delete' with some sort of active/inactive field on the record

Probably a better idea.

Adbot
ADBOT LOVES YOU

Dominoes
Sep 20, 2007

fletcher posted:

Probably have to use some raw sql to get to the more advanced functions, I would imagine: http://www.postgresql.org/docs/9.5/static/fuzzystrmatch.html
Thank you.

For model fields, what's the difference between help_text and label?

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