The Internet Trends - Niching, Layering, Hierarchy.

Isn’t it amazing how much knowledge is actually on the internet? You can google just about anything these days - often I have what I think is a semi-original thought, and can usually find someone thinking the same thing in a matter of minutes.

The fact is, we are quickly reaching the point where those quick ‘first layer’ thoughts or questions that all of us have are, or can be answered by, the internet. By first layer, I mean quick thoughts or questions that pop up in our minds on a daily basis, as opposed to questions that come when we are intensely focused on a particular area or in a particular field of expertise.

What is the impact of this? Well, what it means is that to get noticed, you need to start ‘niching’. Yep - this is talked about all the time in online marketing - targeting a specific niche to talk about, filling in the gaps of the knowledge of the internet on particular focused topics.

The second trend, which is a more predictable one due to natural heirarchy, is the layering that is being built on top of the internet. First there is the information. Then there are information aggregators - then there are aggregators of aggregators, and search of search engines. There is infrastructure being built on top of the cloud to manage it all. We built servers and browsers to handle the responses and the requests, and now we have networks and clouds of servers that can easily pass the data back and forth, and scale on and off demand flexibly.

The question is, what is the next layer that is being built? How will the browser / request / server model change? What is the next layer that will be built on top of the internet’s vast amounts of aggregated information?

How far can one think?

I have recently been paying more attention to my general thinking patterns, and am trying to deduce the optimal balance between thinking and experience when making a decision.

Experience is simply a process of gathering more information, while thinking is the process of assimilating and structuring that information but also thinking is imagining and recreating experiences. When one wants to make a decision, usually one turns to thinking and reasoning through the space. To analogize, to me its like you are a small lighted circle on a map - this is your small circle of ‘understanding’ or the whole picture you see in your mind and what you understand comfortably; and there is a fog that surrounds your little circle of understanding on all sides, covering up the surrounding territory. Thinking is the process of moving on different roads and exploring those fogged areas, so that you see the whole picture. Its important to note that it takes critical and open thinking to ‘push back’ this fog to expand your understanding and knowledge of the whole picture. This process consists basically of using logical reasoning and assumptions to think your way through the fog, and if you get stuck, you try to call on your other experiences or even ‘imagine’ how something would be to keep thinking.

However, because of how our minds work, it is often difficult to push the fog back very far - the reason is that we tend to think stereotypically and use lots of assumptions. Similarly, often it becomes difficult to properly imagine situations, let alone assess these imagined situations. Assumptions help us limit, focus, and direct our thinking, but they also prevent us from taking other roads and exploring the fog in all directions. Assumptions, then, are almost like the roads themselves - they let us think in a certain direction, much like taking a road and exploring a territory in one direction - you can’t veer from the path. However, without assumptions, we have no direction - they are very necessary. The farther and farther you move from your original starting point, what usually tends to happen is that the assumptions you make become weaker and more imagined, making it harder to move through the fog. This is why experience is so key.

Continuing with the same analogy, experience is then like a ’spotted highway’ on the map. The reason is that its much easier to understand when one experiences something first hand, its not like you are ‘fighting back’ the fog to think through it, but rather, experience just happens and understanding comes naturally - thats why its a highway, because you can understand a lot just by experiencing it, much like a highway in that you can travel great distances very quickly. However, the highway is ’spotted’ because really, experience teaches a lot of random stuff - it doesn’t necessarily carve out a large circle of understanding, but many such smaller circles of understanding scattered through the territory, that its up to you to connect.

So we mentioned that the roads in our analogy are the ‘assumptions’ we make, because they help direct our thinking. What we can do then is be self-aware of the assumptions we are making, and then challenge these assumptions. By doing this, instead of being stuck on a one-way road into the fog, we start creating side-paths that we can take and explore, which makes then our thoughts have lots of ‘branches’. Every time we drop an assumption, the possibilities open up for us to explore new options, but, of course, our path of reasoning becomes less defined; thus at some point we usually create a new assumption then (different from the old one) to create a new path for ourselves into new areas of the fog.

So what is the optimal balance between thinking and experience? This is an extremely hard question, but to answer it, I would say that more information and experience is always a better thing no matter what; that said, I don’t necessarily have a good answer, but more a quip like cliche. I would say that thinking is only necessary when a decision needs to be made, and more experience is necessary when thinking cannot provide a decision. In other words - if you can’t decide, get more experience, then decide. Simple? Not really.

Tags: , , , , , , ,

Modeling a Path to Successful

I recently read this blog entry http://lethain.com/entry/2009/jul/31/success-and-dancing-shoes/ and starting thinking on what success was REALLY about. The article had much truth to it, saying that one must position oneself amongst the right people, and of course must be willing to work hard, and there should be a sprinkle of luck. I started thinking how to model a path of success.

But honestly, I have a completely different model of the factors of success.

A key ingredient in the model of success is ‘the goal’.

What do I mean by ‘the goal?’

I mean that at some point, there needs to be an idea that can be realized as something concrete that provides real value to people (or businesses). There has to be a direction that is being moved in to create this value. If you want to be successful, you need to be associated (and possibly contributing to) the right goal.

A goal can be a new toy you are going to produce, a new internet startup based around a novel idea, or anything that essentially a group of people can use as a direction to move towards creating something of concrete value. Most of my examples will be business oriented, but this doesn’t have to be the case. All that matters is that there must be value produced.

First, you should ask yourself, is there anyone considered successful who has not been associated with a goal? I can’t think of any.

Now, once you accept that a goal has to exist, the question of ‘how do I become successful’ instead turns into something else. It becomes a matter of being associated with the right goals/directions/ideas, as well as potential goals/directions/ideas.

Everyone is part of many goals today - in fact, you should probably ask yourself ‘What goals am I pursuing?’ - one of them, if you are employed, is your employers goal of doing whatever it is the company is trying to accomplish.

The people who you surround yourself with are essentially your ‘pool’ of potential goals you can pursue. Maybe one of them is entrepreneurial, and has a goal of starting a company. Then you also have a potential to be in that company and pursue that goal.

However, the main thing you should realize is that you have your own goals! You can have an idea of something of value, and share that goal with others and pursue that goal. The important questions to ask oneself are “how can I do this better?”, or if a problem presents itself, realizing that solving that problem for yourself is also probably a problem for others, and it is a small step from solving a problem to creating a new goal of solving this problem on a larger basis.

Thus, success is about the intersection of a two things:
1. How well your defined goal provides concrete value to others
2. How well you and the people you surround yourself with can pursue that goal

The first is about measuring the usefulness of the goal - will people like this new toy? Will people use this internet service? This can be a very hard estimation, but you can improve and hone it over time with feedback.

The second is about how well you can solve the subproblems that creep up and get in the way of the greater goal. With a solid team of smarter, experienced, and well-tempered individuals, you will be able to handle these sub problems better. Some sub problems may be ‘how can I change the product to match the needs of what people are telling me they need/want?’, or ‘how can I tackle this technical challenge’ or ‘how can I get the next round of funding for our company?’

One must attach oneself to a goal, or create the goal and attach people to it. Success is merely the approach and carrying out of this goal.

Tags: , , , ,

Create a Django Dynamic Form with JQuery - Dynamic Field Addition and Removal

So I found a nice piece of Jquery - Jquery-Dynamic-Form ( http://code.google.com/p/jquery-dynamic-form/ ), and thought it would be just the thing to spice up the static forms on my latest venture (a django website, of course). So I downloaded the jquery file and tested it out, and I thought, to myself that it would be no problem to integrate - well, it took longer than I thought, but I finally got it to work nicely.

Here’s how I was able to integrate dynamic addition of form fields on my django form using jquery- dynamic-form:


0. First, fix the JQUERY. This particular jquery library used a ‘php’ style naming scheme for its variables - namely, something like:

<input type="text" name="myfield[]" id="0">
<input type="text" name="myfield[]" id="1">
<input type ="text" name="myfield[]" id="2" >

As you can see, it used the php array as the name - instead, i make a quick fix to the jquery to make it instead just do this naming scheme:

<input type="text" name="myfield0" id="0">
<input type="text" name="myfield1" id="1">
<input type ="text" name="myfield2" id="2" >

To do that was rather easy, simply change a couple lines in the jquery; to look like this:

/* Normalize field name attributes */
            if (!nameAttr) {
				jQuery(this).attr("name", "field" + fieldId);
			}

			if (!/\[\]$/.exec(nameAttr)) {
				jQuery(this).attr("name", nameAttr + fieldId);
			}

As you can see, we only changed 2 lines of code, so that it appends the ‘fieldId’ to the end of the name attribute.


1. Set-up the form template properly with jquery-dynamic-form (easy) - lets you clone whatever field you want, in my case, just a + and - buttons to click on to add / remove text fields on the fly (this template needs a dynamic element to it, but we’ll get to that in step 3)
The JQuery Stuff:

<script type="text/javascript" src="/media/js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="/media/js/jquery-ui-1.7.2.highlight.min.js"></script>
<script type="text/javascript" src="/media/js/jquery-dynamic-form.js"></script>
<script type="text/javascript">
    $(document).ready (function() {
        $("#duplicate").dynamicForm("#plus", "#minus", {limit:6, createColor:"yellow", removeColor:"red"});

    });
</script>

The template form stuff:

<form method="post" action=".">
 <fieldset>
        <h3>My dynamic text fields</h3>

		<div id="fields">
		    <div class="field">
		        {{ dynamic_html }}
		        <p><span><div id="plus">Add Another <a href="">[+]</a></div>
		        <div id="minus">Remove <a href="">[-]</a></div></span></p>
                    </div>
               </div>
    <p><input type="submit" value="Build it!" /><br/></p>
 </fieldset>
</form>

As you can see, we dynamically create the guts of this template with a variable called {{ dynamic_html }} - I’ll show you what happens with this in a second.

But in general, its just some code that we generate that shows our bound form fields, but it works just like you think it would - clicking the plus adds a field, clicking the minus removes it, intuitive! Here is a quick preview:

A Preview of the Form

A Preview of the Form

2. When the form is submitted, the VIEW dynamically creates a form to match the submitted amount of fields. I used what i call the ‘type’ method to dynamically create the form- we’ll show you this in step three. When the form gets submitted, here is the view that handles it:

Here is the view code:

def myview(request, template_name='myapp/mytemplate.html'):

    if request.method == 'POST':
        #create the dynamic form class here on the fly
        form_class = make_dynamic_form(post=request.POST)

        form = form_class(data=request.POST)

        #this is the template that we insert into our general template
        dynamic_fields_template = make_dynamic_fields_template(form.data)

        if form.is_valid():
            #hooray! A Valid form - process the form fields as necessary!
           return HttpResponseRedirect('/')
    else:
        initial_vals = {'empty_textbox':'',}

        form_class = make_dynamic_form(post=initial_vals)
        form = form_class()
        dynamic_fields_template = make_dynamic_fields_template({'blog_url':''})

    dynamic_html = dynamic_fields_template.render(Context({'form':form}))
    return render_to_response(template_name,
                                {'form':form, 'dynamic_html':dynamic_html},
                                context_instance=RequestContext(request))

#Input: dictionary of fields into this method
#Output: Html (with our field variables not yet bound to context)
def make_dynamic_fields_template(fields):
    template_html = ""
    for f in fields:
        template_html += """
        <p id="duplicate">
        My Form Label {{ form.%s }}
        {{form.%s.errors}}
        </p>
        """ % (f, f)

    return Template(template_html)

Here you can see that we dynamically create our form on the fly from the POST information using a custom method that we show in the next step. If the form is valid, perfect, and you can process it like any other form. If it was the first time we accessed the page (and didn’t POST), then you can see that we simply create a form with one field on the fly, render the template for this one field, and then pass this dynamic_template inside the other template; this variable gets rendered it like a regular variable using {{ dynamic_html }} inside the template.

Why do we have to render the template on the fly? Well, if the template (with a bunch of new, say, text fields you added dynamically) doesn’t validate - well, then you need to return that form you just used (with its corresponding errors) - but you still want it to be a dynamic form, but the original template you used doesn’t know how many fields you added or removed dynamically (using jquery), or what their names are! Thus, we need to dynamically generate a template again from our new form, which we do by created the html and passing it into our template as a variable (and rendering it there)

2.5 To create the form on the fly, we use this method:
http://www.b-list.org/weblog/2008/nov/09/dynamic-forms/ to create the form on the fly. You can see we override the ‘clean’ method; We validate all the dynamic fields, and if there are errors, assign the errors back to the individual fields (otherwise, errors would go in non_field_errors) - this is done using this technique: http://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other

And here is how the form is created on the fly:

def make_dynamic_form(myfields={}):
    fields = {}

    #create the fields dynamically!
    for p in myfields.keys():
        fields[p] = forms.CharField(max_length=200, required=False, widget=forms.TextInput(attrs={'class':'text' }))
    #this creates our new form with the given fields
    newform = type('MyDynamicForm', (forms.BaseForm,), { 'base_fields': fields })

    #now lets define our clean method
    def clean(self):
        cleaned_data = self.cleaned_data

        #iterate through each value
        for val in cleaned_data.keys():
            if not val:
                continue;

             if (self.cleaned_data[val] is None) or (self.cleaned_data[val] == ''):
                    continue;

            # clean the individual value below

             ...run your own cleaning tests here....
             ...say it doesn't validate.....

             #we defined assign_error function to assign the error to the correct field
             self.assign_error(val,u'This is an error we want to attach to that specific dynamic field!')
             #this error goes in non_field_errors - we call this method anyway
             raise forms.ValidationError(u'Error!')

    #attaches an error to a specific field instead of non_field_errors
    def assign_error(self,val,msg):
        if not self._errors.has_key(val):
            self._errors[val]= ErrorList([msg])
            del self.cleaned_data[val]

    #create the methods for the form
    newform.clean = clean
    newform.assign_error = assign_error

    return newform

What we do here is create a fields dictionary, pass this dictionary into the ‘type’ function along with some other stuff, and we create our form. Now, we define the methods we want, and set these as attributes for the form, and finally return the new form. In this case, we defined the clean method, and also a helper method to assign the errors to their respective fields - otherwise, django would put all our errors in non_field_errors, because thats what happens when you raise form validation errors inside of the ‘clean’ method.

Thanks! Any questions / comments are welcome!

Tags: , , , , , , , ,

Expand a VMWare Partition Vista / Ubuntu

So I run Vmware on Vista with a virtual install of Ubuntu on an 8GB partition - well, the 8GB filled up, so I needed to expand the ext3 partition.

The three steps to take are:

1. Expand the VMWare partition using the vmware tool (comes with vmware workstation and others)
Here is a link that describes how to do this: http://4sysops.com/archives/expanding-a-virtual-vmware-disk/ . It is fairly easy to do.

The code looks something like this:

'vmware-vdiskmanager -x 10GB myDisk.vmdk'

2. Now, download a live cd that you can boot from, knoppix is the one I used http://knopper.net/knoppix-mirrors/index-en.html — just download an iso file of it. You’ll want to boot vmware from this iso, so what you do is in the Vmware Workstation sidebar, put this iso in the CD Drive (click on the CD drive and load this iso, easy!). Now you need to tell Ubuntu to boot from CD, so go to VM –> Power –> Power on to Bios. Now, this will start up the Vmware bios, now go to the boot menu and press the ‘+’ sign to move the CD Drive up to the top (so it boots first before the hard drive, so that ubuntu will start from this live cd iso that we downloaded).

3. Now Knoppix should be loading, (you may have to hit like ‘return’ to get it to start loading) - once its fully loaded, open up a terminal. type ‘gparted’ in the terminal to run gparted. Now it should show all your partitions and such. Unmount all the drives you need to do stuff with using:

su root

umount /dev/nameofdrive, i.e........ umount /dev/sda1

If the swap partition becomes an issue root, i.e. you need to delete it, you need to turn it off first, so just do:

swapoff -a

Now, make sure there are no partitions between the free space and the original partition you want to expand. Simply select the partition you want to expand and select how much you want to expand it! Then click ‘apply’ in gparted to actually do it, and it should take a while before saying completed.

If the swap partition is between the free space and the other partition, you will need to delete the swap partition and create a new one at the end of the free space.

Once you have hit ‘apply’ in gparted, and it tells you everything was successful, shut it down, and then go back to vm–>power –> power on to bios and reset your boot so that it doesn’t run from CD first anymore. Then restart and it should load up your regular installation (in my case vmware), but this time with more space for you to use!

Note: You should probably check that things are working, and you may have to make a few edits. First, you should type (as root, or on ubuntu use sudo as shown):

sudo fdisk -l
</pre>

This will list all the partitions you have, make sure its set up properly. Now, if you deleted a swap file, you should check to see if the new swap you created is being used:

free -m
</pre>

This should show how much swap is being used. If your swap is not on, well turn it on using 'swapon'. Use the command 'blkid' to check the names of your partitions, then edit the /etc/fstab file and make sure that the names of the partitions are all the same as the ones you saw when you used the blkid command. If they aren't, change the /etc/fstab file to the correct ones.

Tags: , , , , , , ,

C++ Eclipse Install CDT and MinGW GCC Plugin

I just succesfully installed c++ on eclipse using the CDT C++ plugin and MinGW compiler for windows Vista. There are a lot of plugins to get working. There were a few things that I had to set up, no doubt, so here are some notes for those of you trying to do the same thing:

0. Obviously you need to have downloaded eclipse first http://www.eclipse.org

1. Download the  Eclipse CDT Plugin http://www.eclipse.org/cdt/

2.  Now because I am on windows I need to install a c++ compiler (the CDT plugin doesn’t come with one!), so the recommended one is MinGW. Here is a link that says exactly how to install it, and exactly what you will need to install. http://www.mingw.org/wiki/Getting_Started. Note that there is an automatic installer.

At this point, DO NOT FORGET TO SET YOUR PATH VARIABLE! This is very easy on windows; http://www.java.com/en/download/help/path.xml this says how to do it.

If you happen to get the error:”Your connection appears to have dropped out. Reconnect your dial up or check your IE proxy settings.” then this means that sourceforge is having trouble downloading the file. What you should do is first make sure the installer is not on your desktop, retry it a few times, and then set your source forge default mirror settings - this can be done by signing up for a sourceforge account and then going to your account  https://sourceforge.net/account/ and clicking the Default Download Mirror under the main preferences page.

3. Now follow this guide to setting up the code environment - it is a little outdated but you should be able to follow it pretty easily:

http://www.codeproject.com/KB/tips/CPP_Dev_eclipse_CDT.aspx

4. Finally, you will need to set the path of the ‘includes’ library, so to do this, go to Project -> properties -> C/C++ general -> Paths and Symbols, then click on the ‘Includes Tab (first one), and under languages go to GNU C++, then click on the ‘Add…’ button the right, and then select the folder C:\MinGW\include, and press enter.

Done!

Tags: , , , , , , , , ,

Quick Reflections on building ZetaPage

The first thing I am obligated - by pure appreciativeness and nothing else - to thank every one of the Shotput Partners. They have created an absolutely amazing program that has helped us immeasureably to get our startup off the ground and into existence.

Alas, the hour is late, and because this warrants much more, here I will outline some brief thoughts to preceed the upcoming lengthy post.

0. There is no substitute for energy.

Everyday I’m faced with hundreds of decisions, from tiny ones like “what is the proper way to word a sentence on the about page”, to how the database models should change to allow better normalization and ensure easier scalability. Every day, you need to be making those decisions and moving forward. Whatever it is, you need to just do it and move forward - sure you may make some typos or screw up the models and have to refactor a lot of code later - but you can’t stop. Of course, I have always been a huge fan of reasoning through things, and doing things in the best way possible; no doubt you can still do this, but the caveat is that you should do things as best as possible (within the given time period).

1. Meeting once a week and speaking with people

In the Shotput program, once a week we would meet with really awesome entrepreneurs, technology lawyers, professors, marketing experts, and a whole host of really cool and smart people. Similarly, working with the other groups to provide feedback and just being surrounded with other entrepreneurs somehow adds a certain vibe and energy that really makes you feel awesome - it is palpable and apparrent, that each of us knew we were buidling something new and novel.

2. Who you gonna call? (Hopefully Ghostbusters isn’t the answer)

Sometimes you have hard decisions to make, such as changing the focus or direction of the company; sure you need to make a decision and go with it, but, like I said earlier, I’m definitely a fan of doing things the best way possible (and not having to redo things) - thus getting expert outside advice is the best thing possible. That is where key advisors come in.

3. Solving hard problems on a daily basis

Like I said earlier, you will be faced with hundreds of questions a day. Solving problems on a daily basis turns into knowing when it is worth it to sit down and think about something, and when it is completely fine to use a straight-out-of-the-box approach.

4. Adaptation on a daily basis

Now, when making decisions you need to be inundated with the latest <insert statement here>; by this, I mean that each day you need to be in two frames of mind; the first frame of mind is the one you ended yesterday on; essentially, this is the plan going ahead. The second frame of mind is the changeling mind, what it does is test the waters of each decision and assumption you make - it doesn’t prevent you from making decisions, but it makes you aware of all the avenues you could be taking in case you get tripped up or decide you need to go in a different direction. Its like you’re navigating through a neighborhood, following the main road but being aware of all the side streets - you do it because the house you are looking for could be on any street.

An Important Question When Moving into Unknown Programming Territory

So you’re about to undertake a project that you have little experience with (whether it be the language) or little knowledge about at all. The first question to ask oneself is “What level do I need to be working at?”

Now, let’s say I want to write a web application, and I choose to use python-django. We start with a problem, say, ‘how do I create a user-login interface (i.e. a standard across websites - e-mail activation, etc). First, you should consider what levels are available to you. In this case, the levels (from top down) are as follows:

Django-App (Pre-Built)

Django-App (customized with Python)

Combingin Pre-Built Python Libraries That Each Do A Significant Piece (i.e. loggin in to website, storing a session)

Develop Using much smaller Python Modules that Each Do A Smaller Piece (handle an http request, parse html)

… (more levels)

Using C/C++ To Build Python modules and work with those

(lower than this is absurd for common web stuff usually!)

Often, developers can strangle themselves because they start working at too low of a level, instead of searching for higher-level solutions that will either work out of the box, or work with a small bit of customization (my preferred way). While more control is great - time is almost always a factor (plus if you use django, then you probably subscribe to the DRY principle (Don’t Repeat Yourself), and do this anyway!)

So before you start your next project, do your research (usually in the form of multiple google searches) and make sure you are operating at the correct level.

Tags: , , , ,

Extend the Django-registration Form - Adding the Extra Fields you Want

Django-registration is cool, but often you want to add some more fields to the Registration Form. At first, it doesn’t quite jump out at you how to do this. This blog post is all about how to add some extra fields into django-registration while having to write the least code. We’ll go through all the steps just because its nice to have completness. Let’s see what we can do.

I used easy_install django-registration, and it installed this egg file to my site-packages: django_registration-0.7-py2.5.egg

Steps:
1. Create your own app, ours is called ‘mynewapp’ (which is a very poor name, by the way), and add it to your settings.py file in the regular way by registering it under INSTALLED_APPS

2. In your app, create a model in your models.py file using this method: http://www.djangobook.com/en/1.0/chapter12/#cn222 and make sure to set the AUTH_PROFILE_MODULE in your settings.py file.

This model is the ‘extended’ fields that you want to see in the form, such as user ‘location’, ‘address’, or ‘favorite stripper’ to name a few example.

It should look something like this and should be in models.py:

from django.db import models
from django.contrib.auth.models import User
class ZProfile(models.Model):
user = models.ForeignKey(User, unique=True)
favorite_band = models.CharField(max_length=200, blank=True)

In our case, we created a class model called ZProfile. Then, we added this in our settings.py file:

AUTH_PROFILE_MODULE = "mynewapp.ZProfile"

Note: you MUST put ‘appname.ClassName’ NOT like ‘projectname.appname.modulename’ or anything like that. Our class is ZProfile (inside a module named something like zforms.py or something), our app is mynewapp.

3. Now create a new registration form for yourself. You can create a new python file, and name it like newform.py.In it, define new RegistrationFormZ that extends RegistrationForm; this should have the new fields you want to add, and also it should override the save() method of RegistrationForm (its superclass).
Something like this:

from django import forms
from registration.forms import RegistrationForm
from django.utils.translation import ugettext_lazy as _
from registrationz.models import ZProfile
from registration.models import RegistrationProfile
attrs_dict = { 'class': 'required' }
class RegistrationFormZ(RegistrationForm):
band = forms.CharField(widget=forms.TextInput(attrs=attrs_dict))
def save(self, profile_callback=None):
new_user = RegistrationProfile.objects.create_inactive_user(username=self.cleaned_data['username'],
password=self.cleaned_data['password1'],
email=self.cleaned_data['email'])
new_profile = ZProfile(user=new_user, favorite_band=self.cleaned_data['band'])
new_profile.save()
return new_user

So what we see is that when a new user account is created, so too do we create our profile account. Nice! But we’re not done yet.

We have to tell django-registration to use our new form, RegistrationFormZ, instead of the default RegistrationForm. Django-registration is well designed in that it lets just simply pass this in as a keyword argument to the ‘register’ view, specifying which registration form we want to use. This is done using url patterns. So, let’s create a urls.py file WITHIN OUR APP (i.e. within the app we created earlier) that looks something like ‘registration.urls’ (django-registration default). We only have to change the url pattern that maps to the register view, with this line:

url(r'^register/$',
register,
{'form_class' : RegistrationFormZ},
name='registration_register'),

Here is the whole of the urls.py inside my app, with this change:

from django.conf.urls.defaults import *
from django.views.generic.simple import direct_to_template
from django.contrib.auth import views as auth_views

from registration.views import activate
from registration.views import register
from mynewapp.registrationz.formsz import RegistrationFormZ

urlpatterns = patterns('',
# Activation keys get matched by w+ instead of the more specific
# [a-fA-F0-9]{40} because a bad activation key should still get to the view;
# that way it can return a sensible "invalid key" message instead of a
# confusing 404.
url(r'^activate/(?Pw+)/$',
activate,
name='registration_activate'),
url(r'^login/$',
auth_views.login,
{'template_name': 'registration/login.html'},
name='auth_login'),
url(r'^logout/$',
auth_views.logout,
{'template_name': 'registration/logout.html'},
name='auth_logout'),
url(r'^password/change/$',
auth_views.password_change,
name='auth_password_change'),
url(r'^password/change/done/$',
auth_views.password_change_done,
name='auth_password_change_done'),
url(r'^password/reset/$',
auth_views.password_reset,
name='auth_password_reset'),
url(r'^password/reset/confirm/(?P[0-9A-Za-z]+)-(?P.+)/$',
auth_views.password_reset_confirm,
name='auth_password_reset_confirm'),
url(r'^password/reset/complete/$',
auth_views.password_reset_complete,
name='auth_password_reset_complete'),
url(r'^password/reset/done/$',
auth_views.password_reset_done,
name='auth_password_reset_done'),
url(r'^register/$',
register,
{'form_class' : RegistrationFormZeta},
name='registration_register'),
url(r'^register/complete/$',
direct_to_template,
{'template': 'registration/registration_complete.html'},
name='registration_complete'),
)

Now, you need to make sure to include this urls.py file in your PROJECT urls.py.

So go to your project’s global urls.py, and add these lines:

(r'^accounts/', include('myproject.mynewapp.urls')),
(r'^$', direct_to_template, { 'template': 'index.html' }, 'index'),

The first line simply includes the URL file that we created in our app; the second line uses direct_to_template notation, which means don’t do any djangoey stuff (i.e. dont’ redirect to a view) instead just show a plain static template. The second line is only necessary if you used those template files I provided a link to earlier (on the other blog), and you want to show your index.html when people go to your site.

Now, run python manage.py syncdb, and it should update the correct models. Now when you create a user account, it will created a profile for him/her that is accessible by calling the get_profile() method (because we created a ForeignKey relationship between our user and the profile account, remember?). This profile will have all the fields you defined, in our case, it just has one field, favorite_band (which I really don’t even have, sadly).

One thing, is that while the ‘management’ script to clean up expired users accounts works for RegistrationProfiles or whatever, you will probably have to modify this if you to say you also want to delete the user’s accompanying ZProfile as well when it is checking for expired accounts.

Hope this was helpful! Feel free to leave me a comment or question and I will try to reply.

Tags: , , , , , , , ,

Getting a Production Server Up and Running: Django, Ubuntu, Nginx, Apache, Subversion, Memcache, UFW(firewall)

This post is for those of you self-starters that have never set up a whole server for a serious project, and want to learn how. Here is the links that I found that helped me most in the process. Its about installing apache, django, ubuntu, mod-wsgi, nginx, and subversion.

The first step is to go through this guide:

The Django and Ubuntu Intrepid Almanac @ Irrational Exuberance

This assumes you have ubuntu installed - it shows how to get and install apache, nginx, and django.

Here is another similar one:

Installing Django on Ubuntu Intrepid: Django, Nginx, Apache, mod_wsgi, cmemcache | meppum.com

Now, you will need to set up subversion, these are the best links I found for that:

https://help.ubuntu.com/community/Subversion

http://www2.russbrooks.com:8000/2009/2/1/install-subversion-on-ubuntu-linux

http://articles.slicehost.com/2007/9/5/using-ssh-with-svnserve

http://svnbook.red-bean.com/en/1.1/ch04s02.html

If you have questions, feel free to ask them in the comments section.

Tags: , , , , , , ,