Categories
Python Answers

How to do an OR filter in a Python Django query?

To do an OR filter in a Python Django query, we can use Q and the | operator.

For instance, we write

from django.db.models import Q

Item.objects.filter(Q(creator=owner) | Q(moderated=False))

to call filter to search for Item items where creator is owner or moderated is False.

We call Q with the conditions we want and combine them with | to do the OR query.

Categories
Python Answers

How to pass custom form parameters to Formset with Python Django?

To pass custom form parameters to Formset with Python Django, we call formset_factory and functools.partial.

For instance, we write

from functools import partial, wraps
from django.forms.formsets import formset_factory

ServiceFormSet = formset_factory(wraps(ServiceForm)(partial(ServiceForm, affiliate=request.affiliate)), extra=3)

to wrap the ServiceForm with wraps.

And then we call partial with Service and the argument we want to pass into ServiceForm.

And then we call (wraps(ServiceForm with the result returned by partial.

And then we call formset_factory on the result returned by wraps.

Categories
Python Answers

How to programmatically saving image to Python Django ImageField?

To programmatically saving image to Python Django ImageField, we can call save with the path we want to save the file to.

For instance, we write

from django.core.files import File 
import urllib

result = urllib.urlretrieve(image_url)

self.photo.save(
    os.path.basename(self.url),
    File(open(result[0], 'rb'))
    )

self.save()

in a model class method.

We call save on the photo ImageField with the path to save to as the argument.

And we save the file that we opened from urllib.urlretrieve method by creating a File object from it.

We create the file by call open with the result[0] file with read permission.

Finally, we call self.save to save the model data.

Categories
Python Answers

How to dynamically add field to a form with Python Django?

To dynamically add field to a form with Python Django, we can add the form with a for loop.

For instance, we write

class MyForm(forms.Form):
    original_field = forms.CharField()
    extra_field_count = forms.CharField(widget=forms.HiddenInput())

    def __init__(self, *args, **kwargs):
        extra_fields = kwargs.pop('extra', 0)

        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['extra_field_count'].initial = extra_fields

        for index in range(int(extra_fields)):
            self.fields['extra_field_{index}'.format(index=index)] = \
                forms.CharField()

to create the MyForm form that has a for loop in the __init__ method that creates CharFields and add them into the self.fields dictionary dynamically.

Then in our view, we can use the form with

def myview(request):
    if request.method == 'POST':
        form = MyForm(request.POST, extra=request.POST.get('extra_field_count'))
        if form.is_valid():
            print "valid!"
    else:
        form = MyForm()
    return render(request, "template", { 'form': form })

We set the extra argument to a list we get from request.POST.get.

Then we render the template for the view with

<form>
    <div id="forms">
        {{ form.as_p }}
    </div>
    <button id="add-another">add another</button>
    <input type="submit" />
</form>
Categories
Python Answers

How to create a dynamic choice field with Python Django?

To create a dynamic choice field with Python Django, we can set the fields to a queryset value.

For instance, we write

class WaypointForm(forms.Form):
    def __init__(self, user, *args, **kwargs):
        super(waypointForm, self).__init__(*args, **kwargs)
        self.fields['waypoints'] = forms.ChoiceField(
            choices=[(o.id, str(o)) for o in Waypoint.objects.filter(user=user)]
        )

to create the WaypointForm form.

In the __init__ method, we set self.fields['waypoints'] to a ChoiceField.

And we populate the choices by setting the choices argument to a list of values that we get from the Waypoint.objects.filter(user=user) queryset.