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
Metonymy
Aug 31, 2005
This is a pretty simple question, but I haven't found a good treatment of it in the Django docs:

Let's say I have a Items model, and a UserItems model.

code:
class Items(models.Model):
    title = models.CharField(max_length=500)

class UserItem(models.Model):
    item = models.ForeignKey(Item)
    user = models.ForeignKey(User)
    userflaggedtheitem = models.BooleanField()
Essentially, if a user flags an item, the UserItem record is created.

So the relationship represented in the DB as a one-to-many, but is effectively a one-to-one (or none) for any given user.

I'm looking for a way to pull back Items with the associated UserItem inner join'ed, so I can check if the user has flagged the item. I know I can pull an individual Item and go: item.useritem_set.all() to pull all associated records, but how do I go about getting a model that has the inner join of the two? Iterating through item.useritem_set.all() during templating seems like a hideous solution, even if item.useritem_set has been filtered to only match the current user.

Metonymy fucked around with this message at 22:33 on Jul 13, 2009

Adbot
ADBOT LOVES YOU

TOO SCSI FOR MY CAT
Oct 12, 2008

this is what happens when you take UI design away from engineers and give it to a bunch of hipster art student "designers"

Metonymy posted:

So the relationship represented in the DB as a one-to-many, but is effectively a one-to-one (or none) for any given user.

This isn't a one-to-one relationship, it's a many-to-many -- a user may flag many items, and an item may be flagged by many users. Consider using a ManyToManyField.

Metonymy
Aug 31, 2005

Janin posted:

This isn't a one-to-one relationship, it's a many-to-many -- a user may flag many items, and an item may be flagged by many users. Consider using a ManyToManyField.

I've switched to a ManyToMany field and checked the Django docs, but I'm still not sure how you go about pulling a recordset that mimics an INNER JOIN.

The vibe I'm getting from the docs is that I would have to filter and iterate across an Item's __useritem_set.all() even though it has been narrowed to a single UserItem.

That seems really hackish. Is there a better way to do this in Django? An INNER JOIN does not seem like an outlandish use case.

bitprophet
Jul 22, 2004
Taco Defender
What exactly are you trying to accomplish? I don't see what the point of the BooleanField is, it implies you'll be autogenerating one of these for every possible item/user combination, then flagging only the ones where a "flagged" relationship actually exists.

Whereas a simple many-to-many (as Janin suggests) between User and Item represents that relationship in a pretty common and obvious manner. You can then simply do item_obj.user_set.(filter|count|all|etc) from the Item side, or user_obj.item_set.(ditto) for that side of things.

Finally, if the example you gave is seriously limited and you have a lot of OTHER metadata riding on this User<-->Item relationship (i.e. on your current UserItem class) you will still want to use a ManyToManyField, but use the "through" kwarg and point it at UserItem. This will give you both the overarching join magic in the background (as in my previous paragraph) as well as the ability to access the UserItem objects to get at your "edge" data.

I definitely think that if your model has more to it than what you've shown, giving us the real model classes might help some :)

Edit: docs for through/having extra data on m2m join classes is here

Metonymy
Aug 31, 2005

bitprophet posted:

What exactly are you trying to accomplish? I don't see what the point of the BooleanField is, it implies you'll be autogenerating one of these for every possible item/user combination, then flagging only the ones where a "flagged" relationship actually exists.

...

I definitely think that if your model has more to it than what you've shown, giving us the real model classes might help some :)

Edit: docs for through/having extra data on m2m join classes is here

I think my problem is that I'm not used to being abstracted away from the actual database structure. If it seems like I am talking out of my rear end, I probably am - I've only been working with Django for a week. But here's what's up:

Lets say I'm writing a Twitter reader, and I've got two models: Tweet, and UserTweet. The UserTweet model exists only to tell me whether a given user has read a given tweet, but might get extended with more metadata. So:
code:
class Tweet(models.Model):
    tweet = models.CharField(max_length=160)
    link = models.CharField(max_length=200)
    
class UserTweet(models.Model):
    tweet = models.ForeignKey(Tweet)
    user = models.ForeignKey(User)
    hasRead = models.BooleanField() # whether the user has read the article or not
    # more metadata about when the user read the item, etc.
I don't think a many-to-many is appropriate, because a given UserTweet is associated with only one Tweet (in contrast to the Django doc's Publication/Article example, where a Publication contains multiple Articles, and an Article may appear in multiple Publications). So I might just represent that with a simple ForeignKey relationship, right? But if I do that, is there really no way to achieve an INNER JOIN or LEFT OUTER JOIN style query for a given user, so that I can pull the unique Tweet.UserTweet (for the current user) to see whether the user has read that article? I only ask because I'm running into this templating issue where I want to do something like:

code:
   {% for tweet in tweets %}
   <div class="tweet {{ READ CLASS OR UNREAD CLASS DEPENDING ON THE UserTweet }}">
   {{ tweet.link}}
   </div>
   {% endfor %}
So filtering Tweet.usertweet_set on the server-side to account for the current user and then going Tweet.usertweet_set.all()[0] (and assuming it has filtered properly) in the template seems klugey as heck. How do you typically deal with one-to-many relationships that become one-to-one relationships when filtered in Django? It seems like this would be a common use case for any kind of relationship between individual users and data items...

bitprophet
Jul 22, 2004
Taco Defender
Did you read the link I posted? You're still not quite getting it.

You want a many-to-many relationship between Tweet and User. That is effectively what you are trying to create with your UserTweet that has FKs to Tweet and User. Django's many-to-many mechanisms will give you these joins you're asking for, because that's what they were designed for.

And you can use the "through" option to have that relationship make use of your explicitly defined UserTweet class so you can store and access specific data, instead of using a hidden/implicit join table (which is what M2Ms do when "through" is not used -- they make a 3-column table with id, fk to model 1 and fk to model 2.)

In other words, you have two actual objects, nodes on a relationship graph, User and Tweet -- and the edge between them is UserTweet.

So you'll start out with a bunch of Users and Tweets and no UserTweet objects because no relationships/edges exist yet. Then, when a User sees a Tweet, you create a link between that User and that Tweet, generating a UserTweet object, and you can then set the timestamp on it.

Finally, note that you do not need the boolean "hasRead" column because the simple existence or lack thereof of a UserTweet linking a specific user to a specific tweet, is what tells you whether that User has read that Tweet. So a given Tweet's .user_set.all() gives you all users that have read that Tweet, and a User's .tweet_set.all() gives you all tweets that user has read.

Please read the docs I linked you to, especially the examples towards the end of the section (i.e. just above the One-to-One header) and it should make this all crystal clear.

Final note: given all this, you probably want to rename UserTweet to 'Reading' or 'ReadTweet' or something that makes it more obvious that this particular Tweet<-->User relationship has to do with when the user read the tweet -- as you'll almost definitely be wanting to make additional such relationships for e.g. a user posting a tweet and so on.

bitprophet fucked around with this message at 14:32 on Jul 14, 2009

TOO SCSI FOR MY CAT
Oct 12, 2008

this is what happens when you take UI design away from engineers and give it to a bunch of hipster art student "designers"

Metonymy posted:

I don't think a many-to-many is appropriate, because a given UserTweet is associated with only one Tweet (in contrast to the Django doc's Publication/Article example, where a Publication contains multiple Articles, and an Article may appear in multiple Publications).

Forget about UserTweet; what you're looking for is a many-to-many relationship between User and Tweet. To check whether a user has read a tweet, check if that User exists in the Tweet's user list.

Once you've established the many-to-many relationship, additional metadata may be added to the intermediate table.

Metonymy
Aug 31, 2005

bitprophet posted:

Did you read the link I posted? You're still not quite getting it.

That's what I was afraid of :)

I'll go back and read the docs again. I think my problem is I'm still thinking in terms of a normalized table structure, rather than an object model, and it's forcing my models into awkward, un-Django-like shapes. Thanks for the help, Janin/Bitprophet!

dancavallaro
Sep 10, 2006
My title sucks
Is there a way I can define a custom __unicode__ method or something for one of my ModelFields? I'm new to Django, so forgive me if I'm not explaining this correctly. I'm making a blog-type-thing similar to the tutorial in the OP, except my posts can have multiple categories, so I'm using a ManyToManyField instead of a ForeignKey. Everything is working great, I even figured out how to make a custom display for the ManyToManyField in my list_display in my admin.py. But when I pass my all_posts object that has all my blog posts into my template, and I try to display post.Category, obviously it just displays stuff like <django.db.models.fields.related.ManyRelatedManager object at 0x864a82c>. How can I define a custom display method for this field?

jupo
Jun 12, 2007

Time flies like an arrow, fruit flies like a banana.

dancavallaro posted:

Is there a way I can define a custom __unicode__ method or something for one of my ModelFields?

Funnily enough you quoted the correct name for it right there - just define a __unicode__ method on your model. This may not be your problem however, considering:

dancavallaro posted:

and I try to display post.Category, obviously it just displays stuff like <django.db.models.fields.related.ManyRelatedManager object at 0x864a82c>. How can I define a custom display method for this field?

There's some weird stuff going on here. For starters using a ManyToManyField implies a Post can belong to multiple categories. If this is the case wouldn't the name of the relationship be post.categories and not post.Category? Are you using a ManyToManyField instead of a ForeignKey field?

dancavallaro
Sep 10, 2006
My title sucks

jupo posted:

There's some weird stuff going on here. For starters using a ManyToManyField implies a Post can belong to multiple categories. If this is the case wouldn't the name of the relationship be post.categories and not post.Category? Are you using a ManyToManyField instead of a ForeignKey field?

Yeah, I want a Post to be able to belong to multiple categories, because the categories are like tags. And yes, the name of the relationship should be post.Categories instead of post.Category, I was reusing code from the tutorial in the OP and hosed up. Yes, I am using a ManyToManyField. If I was using a ForeignKey field, this wouldn't be a problem, because ForeignKey fields display properly automatically. But ManyToManyFields just display that <django.db.models.fields.related.ManyRelatedManager object at 0x864a82c> stuff.

jupo
Jun 12, 2007

Time flies like an arrow, fruit flies like a banana.

dancavallaro posted:

Yeah, I want a Post to be able to belong to multiple categories, because the categories are like tags. And yes, the name of the relationship should be post.Categories instead of post.Category, I was reusing code from the tutorial in the OP and hosed up. Yes, I am using a ManyToManyField. If I was using a ForeignKey field, this wouldn't be a problem, because ForeignKey fields display properly automatically. But ManyToManyFields just display that <django.db.models.fields.related.ManyRelatedManager object at 0x864a82c> stuff.

Ok so Managers return querysets - you'll want to iterate through post.Category.all() or post.categories.all() if you end up changing the name.

dancavallaro
Sep 10, 2006
My title sucks
Yeah, I realized I can do this in my template:

code:
{% for category in post.Category.all %}
   {{category.Name}}
{% endfor %}
Still haven't changed the naming scheme. Quick question thought: should fields be uppercase or lowercase? Because judging by the OP and the official Django tutorial, I would have thought it should be Post.Categories, but you guys seem to be saying Post.categories. What's the standard on this?

bitprophet
Jul 22, 2004
Taco Defender
Please don't capitalize your attribute names, it makes the baby Guido (or Adrian if you prefer) cry :( (in other words, every single other Python coder will think you're insane) and as mentioned it should be a plural name, so post.categories would probably be the most sensible/readable.

Basically, just keep in mind that Python is case sensitive, and try not to be so cavalier (cavallaro? :xd:) with your capitalization. Generally, the only time you should ever see capital letters is in the name of a class itself -- never instances of a class, or class/instance attributes. Or function names.

So, when referring to the Post class, use "Post", and a hypothetical Post instance could be "post", and then a Post instance's categories attribute would be "post.categories".

Python's style guide

dancavallaro
Sep 10, 2006
My title sucks

bitprophet posted:

Please don't capitalize your attribute names, it makes the baby Guido (or Adrian if you prefer) cry :( (in other words, every single other Python coder will think you're insane) and as mentioned it should be a plural name, so post.categories would probably be the most sensible/readable.

Basically, just keep in mind that Python is case sensitive, and try not to be so cavalier (cavallaro? :xd:) with your capitalization. Generally, the only time you should ever see capital letters is in the name of a class itself -- never instances of a class, or class/instance attributes. Or function names.

So, when referring to the Post class, use "Post", and a hypothetical Post instance could be "post", and then a Post instance's categories attribute would be "post.categories".

Python's style guide

Hmm. That's what I would have thought, I guess, but the OP threw me off:

code:
class BlogPost(models.Model):
	Title		= models.CharField(maxlength=255)
	Category	= models.ForeignKey(Category)
	Slug		= models.SlugField(prepopulate_from=('Title',))
	Author		= models.ForeignKey(User)
	PostText	= models.TextField()
	PublishDate	= models.DateTimeField(auto_now_add=True)
drat OP!!! :argh:

Just kidding, the OP was really helpful. I'm loving Django so far.

edit: For content, I'm building a little webapp that I can use as an alternative to emailing myself little code snippets and URLs and stuff like that. I find myself doing that all the time, especially when I'm at work and want to save something for later. So I'm making a little memo-pad type thing, that lets me tag entries with multiples tags, so I can look at my "Bookmarks" tag to see a list of URLs I wanted to remember, the "Code" tag to see a list of all my code snippets, the "To Do" tag to see a list of things I wanted to remind myself to do, etc. Not totally necessary, and something like this may exist, and it's basically just a super stripped down blog, but it's fun to do and really loving easy with Django. My web design leaves a bit to be desired though...

dancavallaro fucked around with this message at 03:13 on Jul 15, 2009

king_kilr
May 25, 2007

dancavallaro posted:

edit: For content, I'm building a little webapp that I can use as an alternative to emailing myself little code snippets and URLs and stuff like that. I find myself doing that all the time, especially when I'm at work and want to save something for later. So I'm making a little memo-pad type thing, that lets me tag entries with multiples tags, so I can look at my "Bookmarks" tag to see a list of URLs I wanted to remember, the "Code" tag to see a list of all my code snippets, the "To Do" tag to see a list of things I wanted to remind myself to do, etc. Not totally necessary, and something like this may exist, and it's basically just a super stripped down blog, but it's fun to do and really loving easy with Django. My web design leaves a bit to be desired though...

My webdesign skills suck too, however: http://www.designinfluences.com/fluid960gs/ looks like it could be a great resource for getting simple yet decent designs going.

Metonymy
Aug 31, 2005

bitprophet posted:

In other words, you have two actual objects, nodes on a relationship graph, User and Tweet -- and the edge between them is UserTweet.

Thank you for taking the time to explain this. It finally all clicked when I stopped thinking of the UserTweet as an entity. Everything you said was clear, I was just mentally stuck in a very database-centric model.

So now I'm on board. There can be a many-to-many field on Tweets, relating Tweets to Users, "through" a UserTweetData model. I get that, and it seems like a good way to model the data.

But I also ran into this documentation, which looks a lot like my original model:
M2M w/ Intermediary

Does this apply to the Tweet/User/UserTweet case? What do I buy by switching to the ManyToMany field, rather than the M2M Intermediary model in the documentation above? Based on my experiences so far, I've been able to do things like tweet.usertweet_set.all() with the intermediary model (rather than a M2M field) to get that joined data that we're talking about.

The last thing I'm hung up on is the idea that there's no way to cleanly "normalize" the model for things like JSON serialization or templating. As an example:
Lets say I want to display 1000 Tweets, and give users' unread Tweets a class that makes them bold. Simple. For each tweet, I need the core information, plus some pieces of user metadata.

Regardless of what many-to-many model I use, on the back end, I'm going to have to pull those 1000 Tweets, then filter each Tweet's usertweet_set.all() to limit it to the current user ID, right? Note that filtering the Tweet on usertweet__id is the wrong behavior -- I'm not trying to exclude Tweets that haven't been read, I'm just trying to pull pertinent metadata.

I'm slightly horrified by this idea that I have to filter each individual Tweets' usertweet set -- it seems like it would scale very poorly. I know querysets are lazy-evaluated, but there must be a cleaner solution, right?

bitprophet
Jul 22, 2004
Taco Defender

Metonymy posted:

But I also ran into this documentation, which looks a lot like my original model:
M2M w/ Intermediary

Does this apply to the Tweet/User/UserTweet case? What do I buy by switching to the ManyToMany field, rather than the M2M Intermediary model in the documentation above?

I believe that part of the docs was simply never updated to highlight the relatively new "through" functionality. The intermediate model in that link gives you only the ability to query from one endpoint or the other, to the joining model, and NOT to the other endpoint. So in your situation, you'd be able to ask a User about its UserTweetData objects, but not the actual Tweet objects -- which is almost always the primary goal.

Simply by adding the ManyToManyField with the "through" option to such a setup, you then get the ability to query endpoint-to-endpoint, as well as querying the intermediate model. (The third possible setup, having a ManyToManyField with no intermediary model, then doesn't allow you to store extra info about the relationship itself -- it's solely a "this tweet is linked to this user" and not "this tweet was read by this user on this date".)

quote:

Regardless of what many-to-many model I use, on the back end, I'm going to have to pull those 1000 Tweets, then filter each Tweet's usertweet_set.all() to limit it to the current user ID, right? Note that filtering the Tweet on usertweet__id is the wrong behavior -- I'm not trying to exclude Tweets that haven't been read, I'm just trying to pull pertinent metadata.

I'm slightly horrified by this idea that I have to filter each individual Tweets' usertweet set -- it seems like it would scale very poorly. I know querysets are lazy-evaluated, but there must be a cleaner solution, right?

Someone else more familiar with the underpinnings (paging king_kilr) can answer this more authoritatively than I can, because my actual SQL-fu is not that strong. All I can really say is that the ORM tries to address your concerns as best it can -- look into QuerySet.select_related(), for example -- but you will run into the occasional "oh god what do you mean I have to do this inefficient query?" because there's simply going to be spots where an ORM and raw SQL don't overlap well. This might be one of them, I'm not entirely sure.

Keep in mind that you can always execute raw SQL in said edge cases, if necessary, though you'd have to figure out how to get the resultant data into a useful format. You can also tailor the SQL generated by QuerySets to a large degree with the 'extra' option which may also make life easier -- you can tell it to tack on extra JOINs, for example.

bitprophet fucked around with this message at 14:33 on Jul 15, 2009

Metonymy
Aug 31, 2005

bitprophet posted:

Simply by adding the ManyToManyField with the "through" option to such a setup, you then get the ability to query endpoint-to-endpoint, as well as querying the intermediate model.

Aha! That's slick. You can get there without the Many-to-Many field with something like tweet.usertweet_set.all()[0].user, but that's not particularly elegant.

bitprophet posted:

Keep in mind that you can always execute raw SQL in said edge cases, if necessary, though you'd have to figure out how to get the resultant data into a useful format. You can also tailor the SQL generated by QuerySets to a large degree with the 'extra' option which may also make life easier -- you can tell it to tack on extra JOINs, for example.

Cool. I looked into the extra option and it falls a little short, but I guess this is just part of working with a framework: it's going to make 99% of what you need to do very easy, and you're going to have to go outside the box for the other 1%.

Thank you for all of your explanations - I appreciate it.

Metonymy fucked around with this message at 18:03 on Jul 15, 2009

Kronok
Sep 19, 2002
I'm having some problems finding out how to display a cookie in a template that was created by javascript. I already have the cookie set, I just need to display it somewhere in my template.

Pretty much I want the Django equivalent of PHP's echo $_COOKIE["mycookie"];

The documentation is too confusing in this area for me to understand how to do this properly.

king_kilr
May 25, 2007
Given that you have request available in the template it's just {{ request.COOKIES.mycookie }}

Kronok
Sep 19, 2002
Figuring out how to get the request available is part of my problem.

http://dpaste.com/67703/

As soon as I uncomment that stuff, it breaks and doesn't really help. I'm a bit new to this so I'm sure I'm doing something stupid.

edit: Got it. I wasn't cookied properly, so it couldn't load it, but my code is correct. Thanks for the help!

Kronok fucked around with this message at 03:47 on Jul 16, 2009

nbv4
Aug 21, 2002

by Duchess Gummybuns
Does anyone know what the deal is with Django 1.1? It was originally supposed to be released back in April. I can't seem to find any current information on the status of it. Right now I'm using trunk, but would like to wait until 1.1 goes final before I launch, but I have no idea when that'll be. It's really hard to find a blog or something maintained by a fairly high ranking django person that has been updated since like February.

Janitor Prime
Jan 22, 2004

PC LOAD LETTER

What da fuck does that mean

Fun Shoe
I looked into that recently and saw that there were still 4 major bugs that needed to be fixed.

king_kilr
May 25, 2007

MEAT TREAT posted:

I looked into that recently and saw that there were still 4 major bugs that needed to be fixed.

There are now no major outstanding bugs, expect the release candidate *very* shortly. About a week after that, assuming no major bugs are found the final release will come out.

nbv4
Aug 21, 2002

by Duchess Gummybuns
release candidate is out :woop:

ATLbeer
Sep 26, 2004
Über nerd
n/m

chips
Dec 25, 2004
Mein Führer! I can walk!
I'm having issues with using WSGI in Apache 2 and my admin area. Basically it's not updating in apache, even though it's updating when I run the developent server with manage.py. I presume this is some issue with mod_wsgi not recognising code changes, but it's still not working even if I restart apache, and changing some code sometimes produces changes. I had only just added admin.py to my application, so maybe mod_wsgi still isn't recognising it?

TOO SCSI FOR MY CAT
Oct 12, 2008

this is what happens when you take UI design away from engineers and give it to a bunch of hipster art student "designers"

chips posted:

I'm having issues with using WSGI in Apache 2 and my admin area. Basically it's not updating in apache, even though it's updating when I run the developent server with manage.py. I presume this is some issue with mod_wsgi not recognising code changes, but it's still not working even if I restart apache, and changing some code sometimes produces changes. I had only just added admin.py to my application, so maybe mod_wsgi still isn't recognising it?

touch the .wsgi file.

chips
Dec 25, 2004
Mein Führer! I can walk!

Janin posted:

touch the .wsgi file.

Still isn't showing new admin models.

code:
user@ubuntu810server:~/mysite/apache$ cat /etc/apache2/httpd.conf
WSGIScriptAlias / /home/user/mysite/apache/django.wsgi
code:
user@ubuntu810server:~/mysite/apache$ ls -l
total 4
-rwxr-xr-x 1 user user 235 2009-07-25 02:30 django.wsgi
Could this be misconfigured paths? Though I'm not seeing how that'd stop it finding a source file in the same location as every other.

m0nk3yz
Mar 13, 2002

Behold the power of cheese!

chips posted:

Still isn't showing new admin models.

code:
user@ubuntu810server:~/mysite/apache$ cat /etc/apache2/httpd.conf
WSGIScriptAlias / /home/user/mysite/apache/django.wsgi
code:
user@ubuntu810server:~/mysite/apache$ ls -l
total 4
-rwxr-xr-x 1 user user 235 2009-07-25 02:30 django.wsgi
Could this be misconfigured paths? Though I'm not seeing how that'd stop it finding a source file in the same location as every other.

Are you running in daemon mode, or embedded mode?

chips
Dec 25, 2004
Mein Führer! I can walk!
Worked out that it's because admin.py didn't have the appropriate file permissions, so presumably manage.py was ok because it was running as me but apache couldn't see it.

Metonymy
Aug 31, 2005
Does anyone have any experience serializing raw SQL resultsets? It feels kind of like a hack to iterate over the rows and transform them directly to strings, but I am not sure if the serializers support straight-up sql results -- it seems like they might need some metadata to do their thing.

code:
sql = "SOME ARBITRARY RAW SQL"
cursor.execute(sql, [request.user.id, today-timeshift, today])
data = serializers.serialize("json", cursor.fetchall())
Edit: straight-up cursor returns rows as tuples and dictfetchall is apparently deprecated... hmm..

Edit 2:

So this looks like steps in the right direction:

code:
queryset = [ViewClassForMySQLResults(*row for row in cursor.fetchall())]

s = simplejson.dumps([ufi.__dict__ for ufi in queryset])
But simplejson (natch) can't serialize datetimes, so this breaks too. Is simplejson/__dict__ even the right approach? This has to be a relatively common problem in AJAX development - run a SQL query, serialize the results, and fire them back over the wire.

Metonymy fucked around with this message at 01:29 on Sep 20, 2016

jupo
Jun 12, 2007

Time flies like an arrow, fruit flies like a banana.
Django serializers (I assume from your first snippet this is what you were using) handle dates in regular models - I'd try and go down that path.

Metonymy
Aug 31, 2005

jupo posted:

Django serializers (I assume from your first snippet this is what you were using) handle dates in regular models - I'd try and go down that path.

Yeah, my problem has been with custom SQL queries that don't fit in the regular models. The Django serializers choke on any non-Django models, and simplejson chokes on dates. It seems like such a basic thing:

1. Run SQL query.
2. Serialize results as JSON.
3. Fire them back on the wire.

Is there a clean way to do that?

Edit:

Found
code:
from django.core.serializers.json import DateTimeAwareJSONEncoder
dta = DateTimeAwareJSonEncoder()
dta.encode([gumps.__dict__ for gumps in qs])
As long as I don't have any more "weird" types, I guess this shouldn't choke.....

Is this really the best way to serialize an arbitrary object to JSON in Django/Python?

Metonymy fucked around with this message at 04:00 on Jul 27, 2009

jupo
Jun 12, 2007

Time flies like an arrow, fruit flies like a banana.
Maybe you could cast the dates to varchar in your SQL

Metonymy
Aug 31, 2005
ORM design pattern question:

I'm going to execute some raw SQL to populate a 'View' class (does not extend models.Model since I don't want Django to make a DB representation of any of its fields) for one of my Django models. There are some search parameters that come in on a request, the raw SQL query gets executed, turned into a list of ViewClass, then serialized as json and returned.

What's the cleanest way to organize this?

It seems like I want a Manager class for my ViewClass - I pass the query parameters to the manager, and it returns a list of the ViewClass objects, which the view then serializes as JSON.

This feels a little bit like reinventing the wheel, though, since I don't think I am going to end up subclassing anything.

Does anyone have any experience writing raw SQL queries in Django? Any advice on best practices or design patterns?

king_kilr
May 25, 2007

Metonymy posted:

ORM design pattern question:

I'm going to execute some raw SQL to populate a 'View' class (does not extend models.Model since I don't want Django to make a DB representation of any of its fields) for one of my Django models. There are some search parameters that come in on a request, the raw SQL query gets executed, turned into a list of ViewClass, then serialized as json and returned.

What's the cleanest way to organize this?

It seems like I want a Manager class for my ViewClass - I pass the query parameters to the manager, and it returns a list of the ViewClass objects, which the view then serializes as JSON.

This feels a little bit like reinventing the wheel, though, since I don't think I am going to end up subclassing anything.

Does anyone have any experience writing raw SQL queries in Django? Any advice on best practices or design patterns?

If you're using Django 1.1 (the RC or the dev version, or murphy willing the final release in a few days), you could use an unmanaged model so that you'd have a full Django model, but Django wouldn't try to create any tables for it. http://docs.djangoproject.com/en/dev/ref/models/options/#django.db.models.Options.managed

Metonymy
Aug 31, 2005

king_kilr posted:

If you're using Django 1.1 (the RC or the dev version, or murphy willing the final release in a few days), you could use an unmanaged model so that you'd have a full Django model, but Django wouldn't try to create any tables for it. http://docs.djangoproject.com/en/dev/ref/models/options/#django.db.models.Options.managed

That looks sweet. Thank you.

SOLUTION FOUND, SEE BOTTOM OF POST

Does anyone have experience dealing with multi-column primary keys?

I've got a table that stores metadata that users can associate with an item. When I fire off a POST to update the metadata, there may or may not exist an entry for a given user and a given item. Since Django uses primary keys (which cannot be composite) to determine whether to update or insert, every time I fire off that POST, it's going to create a new entry for the user and the item.

code:
umd = UserMetaData(myItem=MyItem.objects.get(id=myitemid), user=request.user)
umd.templeton = "lets get rad"
umd.save()

# creates new object every time
Obviously I can do a UserMetaData.get() to see if the object with the user and itemid already exists, and then catch the exception if it doesn't and create a new one, but that seems a little limp; I don't like the idea of the exception governing my expected control flow. Is there a better way to do this kind of thing, or do I just need to get over my reluctance to use an exception as a proxy "if".

Edit:
http://www.djangoproject.com/documentation/models/get_or_create/

Metonymy fucked around with this message at 22:43 on Jul 28, 2009

Adbot
ADBOT LOVES YOU

jupo
Jun 12, 2007

Time flies like an arrow, fruit flies like a banana.
I think you're looking for:

code:
my_item, created = MyItem.objects.get_or_create(id=myitemid)
You can see here get_or_create returns a two element tuple - the object and a bool indicating whether the record was created.

http://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create-kwargs

Your aversion to using an exception around get is unnatural however as it's quite a common practice, so much so that your model contains its own DoesNotExist exception specifically for this case, eg:

code:
try:
  my_item = MyItem.objects.get(id=myitemid)
except MyItem.DoesNotExist:
  pass

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