DISQUS

Perplexed Labs: Adventures in Django and Python – Part III

  • attila · 4 months ago
    There is a ternary operator in python:
    value_when_true if condition else value_when_false
    3 if a==2 else 101
    introduced in v2.5.

    Using the and-or hack you will run into problems, it's not recommended
    [] and 'true' or false
    is false for example.
  • matticakes · 4 months ago
    Thanks for pointing that out, I'll update the post.
  • Jake Boxer · 4 months ago
    Great post Matt. While I do appreciate the advantages of the forms module over having to do it all manually, I agree that I have to fight with it a lot. Hopefully it'll be one of the areas that gets improved as Django evolves.

    I just wanted to let you know, Python (2.5 and up I believe) does in fact have a ternary operator; it's just a slightly different syntax. In your example, I could go:

    label = "true" if booleanVariable else "false"

    Unfortunately, it's fairly recent, so if you use it and then end up on an old version (< 2.5 I believe), you'll be in trouble.
  • matticakes · 4 months ago
    Thanks Jake. As usually is the case it's fantastic for a large number of scenarios but, as you dig deeper and need to finely tune things, you begin to identify potential areas for improvement.
  • megaman821 · 4 months ago
    If don't plan on using the result of your filter statement, instead of:
    if account.useraccount_set.filter(user__exact=request.user) != []:
    you could try:
    if account.useraccount_set.filter(user__exact=request.user).count()
    or if you do need the result:
    try:
    user_account = account.useraccount_set.get(user=request.user)
    ...
    except UserAccount.DoesNotExist:
    ....
  • matticakes · 4 months ago
    Interesting, thanks.

    I suppose using the 2nd method you proposed, count(), would be ideal for performance/memory reasons because you're not transferring the result-set from the database.
  • jokull · 4 months ago
    Check out the `attrs` kwarg in form fields. Something like:

    title = forms.CharField(attrs={'class': 'myclass'})
  • matticakes · 4 months ago
    I looked up the 'attrs' documentation, which is sparse. I don't think it's the responsibility of the view or the Form definition to define template related attributes like style, size, etc. I think these attributes should elegantly be modified within the template.
  • andybak · 4 months ago
    Shouldn't those attributes be defined in CSS? Then it's not quite so unappealing to simply use 'attrs' in your form definition to modify or append to the class name (even this might not be needed - you can use the id assigned to each form element or just use CSS attribute selectors).

    Anyway the point is you say styling doesn't belong in Python and I would argue it doesn't belong in the template either.
  • matticakes · 4 months ago
    You have to define those attributes somewhere. It makes more sense (to me) to do that within the template than in your form definition or in your view.

    Even if you ultimately style the attributes using CSS you have to specify that class somewhere. I'd like to able to easily do that from within the template.
  • John · 4 months ago
    I've oft wondered what the best way to set attrs in the template would be, somewhere in the back of my mind this filter base solution has been floating around. 5 minutes and a real quick test shows it has promise.

    @register.filter
    def with_attrs(value, arg):
    args = arg.split(' ')
    attrs = {}
    for v in args:
    v1 = v.split('=')
    attrs[v1[0]] = v1[1]

    return value.as_widget(attrs=attrs)

    {{ form.name|with_attrs:"maxlength=10" }}
  • matticakes · 4 months ago
    John, this is exactly in line with what I'd like to be able to accomplish. I like where you're going with this.

    Perhaps splitting on something other than a space?
  • John · 4 months ago
    Yea, like i said this had been floating around for a while.. Space was just the first thing that jumped out at me. Of course that does not work for style stuff.

    might be better to write it so it can be chained:

    {{ form.name|with_attrs:"size=10"|with_attrs:"style=width: 720px" }}
  • John · 4 months ago
    A quick look at BoundField and it does not appear the chaining of attrs would work. Maybe a comma: (how do you make this thing keep formatting?)

    @register.filter
    def with_attrs(value, arg):
    attrs = {}
    for x in arg.split(','):
    v = x.strip().split('=')
    attrs[v[0]] = v[1]

    return value.as_widget(attrs=attrs)
  • matticakes · 4 months ago
    DISQUS supports some html, apparently not PRE :(
  • Jonathan Buchanan · 4 months ago
    In addition to letting you easily generate HTML4 from your forms (slash, begone!), the "field" template tag provided by http://github.com/simonw/django-html/ lets you specify attributes for rendered form fields:

    {% field form.somefield class="special" %}
  • Andrew Shultz · 3 months ago
    You could do something crazy like subclass the form and give it special processing that will munge some of the fields in ways you approve of. We did that back on 0.96 to use the automatic model form fields but have some of them hidden (there was no "uneditable" then) or to be able to set the entire form to be uneditable.

    In the process I hacked up the automatic form generation a fair bit - unfortunately not all the required pieces were exposed by newforms at the time, which was very irritating since I don't expect to have python modules have functions I'm not allowed to get to somehow. I expect many of the specifics have changed but the basic idea might still work, though not cleanly.