2

I wish to edit ini files over web server, decided to use django, been using it for few days now. I can't figure out how to accomplish this. I have ini file structure looking like this:

{'GROUP', {PROPERTY : VALUE}}

Example when I read this kind of ini file:

[LOG]
    FilePath = C:/Log
[CMD]
    Level = 5

I will get my data structure filled like this:

{'LOG', {'FilePath' : 'C:/Log',}, 
{'CMD', {'Level', '5'}}}

Loop looks like this:

for group in settingsDict:
    print group                         # group
for property in settingsDict[group]:
    print property ,                      # property
    print settingsDict[group][property]     # value

I am using ini file parser.

I am having trouble understanding how to correctly develop in django: views.py is some kind of controller for django and templates are views and model would be my ini file (probably linked with db using django model), or am I getting something wrong?

I have no problem passing this dictionary to template, making a for loop in it and creating html tags like: <input type="text" name={{ property }} value={{ value }} maxlength="100" />. But how do I then post all the edited values back to control to save them in file (or db)? I Would need all 3 values, that is GROUP, PROPERTY and VALUE.

Then I discovered django also has html widgets, which you create in views.py and then pass it to template. But this is where I stop understanding things, since I am creating widget in my controller class, but even if I am.

Shall I create a list of all django widgets and pass it to template? Same question occurs, how do I get all the widget values back to controller (views.py)?

Update (11.6.2012): My code looks like this: views.py

class DynForm(forms.Form):    
    def setFields(self, kwds):
        keys = kwds.keys()
        keys.sort()
        for k in keys:
            self.fields[k] = kwds[k]

def settings(request):
    global Settings #my ini dict
    kwargs = {}
    for group in Settings:
        for property in Settings[group]:
            kwargs[property] = forms.CharField(label = property, initial = Settings[group][property])

    f = DynForm()
    f.setFields(kwargs)

    return render_to_response('/settings.html', 
    {
       'textWidget'   : f,
    })

@csrf_exempt  
def save(request):

    if request.method == 'POST': # If the form has been submitted...
        form = DynForm(request.POST) # A form bound to the POST data
        if form.is_valid(): # All validation rules pass
            # process form data
            # and return response

settings.html

<form action="/save/" method="post">
  {% csrf_token %}
  {% for field  in textWidget %}
        <div class="fieldWrapper">
            {{ field.errors }}
            {{ field.label }}: {{ field }}
        </div>
    {% endfor %}
  <p><input type="submit" value="Save" /></p>
</form>

The problem is, DynForm(request.POST) returns null so I can't get field values. My request.POST is correct, containing all fields and values. As much as I know, I am not suppose to parse request.POST data "by hands"?

Community
  • 1
  • 1
krizajb
  • 1,715
  • 3
  • 30
  • 43
  • Have you looked at [django forms](https://docs.djangoproject.com/en/1.4//topics/forms/)? They will provide an easy way to render forms in template and get the data to views.py – jhonkola Jun 08 '12 at 08:11
  • I did, but as you see I am having troubles understanding if I am doing this the right way. I can create form with as many `CharField()` as needed from my `settingsDict`, is that OK? Still didn't get it how to post all the `CharField()` edits back to `views.py` so I can edit .ini file. – krizajb Jun 08 '12 at 08:13
  • Yes, at least as a first step. If some of the values are not only generic text, it might be worth to look at other form fields also when you get things working. – jhonkola Jun 08 '12 at 08:15
  • One more question, widget attribute name is displayed in template. How do I dynamical create `CharField()` displaying text from my dictionary? Got it: `forms.CharField(label='label name')` – krizajb Jun 08 '12 at 08:35
  • Simply can't figure it out .. I have created my DynamicForm which takes kwargs argument and creates as many CharFields as needed. But can't get the form to bound on POST request. – krizajb Jun 11 '12 at 10:25
  • I think I got it .. need setData function for my Dynamic form. Needed a small break to figure it out :) Is this solution OK or should I maybe try using Multi field types? – krizajb Jun 11 '12 at 16:44

1 Answers1

0

OK, finally figured it out, taking me a lot of time (I am lacking a lot of python and django knowledge). I can't paste final solution because of copy right permissions, here is the concept:

Form
class DynamicForm(forms.Form):
    def __init__(self,*k,**kw):
        forms.Form.__init__(self,*k,**kw)
        # loop over data from **kw
        # create field 
        # set field default value

Notes about this code:

  • If form doesn't use super(SuperForm, self).__init__(*args, **kwargs), you must use forms.Form.__init__(self,*k,**kw) so you can append fields to form using self.fields attribute.
  • If you need to use default field value, use self.data[field] = defVal not initial = defVal. Form becomes unbound and you won't be able to parse data in your request.POST method. Unbound form (and with errors) will always return is_valid() False.

With this class, you have no problems parsing request.POST data. Looping over dynamic form fields looks like this:

View
for name,field in form.fields.items():
    # name - field name
    # form.data[name] - field value

Notes:

Template code loops over fields in form displaying field label and value separated with :

Template
<form action="/Tris/save/" method="post">
  {% csrf_token %}
  {% for field  in textWidget %}
        <div class="fieldWrapper">
            {{ field.errors }}
            {{ field.non_field_errors }}
            {{ field.label }}: {{ field }}
        </div>
    {% endfor %}
  <p><input type="submit" value="Save" /></p>
</form>

Most of the solution is from here: http://jacobian.org/writing/dynamic-form-generation/ and django documentation.

krizajb
  • 1,715
  • 3
  • 30
  • 43