diff --git a/src/memberdb/account.py b/src/memberdb/account.py
new file mode 100644
index 0000000000000000000000000000000000000000..64d12a162b0d93237016195ac626a481698171da
--- /dev/null
+++ b/src/memberdb/account.py
@@ -0,0 +1,84 @@
+from django.http import HttpResponse, HttpResponseRedirect
+from django.shortcuts import render
+from django.urls import reverse
+from django.utils import timezone
+from django import forms
+
+from .models import Member
+from .forms import MyModelForm
+from .views import MyUpdateView
+from memberdb.account_backend import validate_username
+
+class AccountForm(MyModelForm):
+
+	# form fields
+	user= forms.SlugField(
+		validators=[validate_username]
+		)
+	forward_email  = forms.EmailField(
+		label='Forwarding address(optional)', 
+		required=False,
+		help_text="Your club email will be forwarded to this address. Leave blank if email forwarding is not required"
+	)
+
+	password = forms.CharField(
+		min_length=10, 
+		max_length=127, 
+		widget=forms.PasswordInput, 
+		strip=False,
+		help_text="Password must be between 10 and 127 characters long") 
+
+	confirm_password = forms.CharField(
+		min_length=10, 
+		max_length=127, 
+		widget=forms.PasswordInput,
+		strip=False,
+	)
+
+
+	class Meta:
+		model = Member
+		fields = ['first_name']
+		error_messages = {
+			'username': {
+				'unique': 'This username is already taken, please pick another one.',
+				'invalid': 'Please pick a username with only lowercase letters and numbers'
+			}
+		}
+	def clean(self):
+		try:
+			user.clean()
+			if (self['password'].value() != self['confirm_password'].value()):
+				self.add_error('confirm_password', 'Passwords must match.')
+			if (self['forward_email'].value().split('@')[1] in ["ucc.asn.au", "ucc.gu.uwa.edu.au"]):
+				self.add_error('forward_email', 'Forwarding address cannot be the same as your account address.')
+		except:
+			pass
+		super().clean();
+
+	def save(self):
+		return
+		
+	
+
+class AccountView(MyUpdateView):
+	template_name = 'admin/memberdb/account_create.html'
+	form_class = AccountForm
+	model = Member
+	pk_url_kwarg = 'object_id'
+	admin = None
+
+	def get_context_data(self, **kwargs):
+		m = self.get_object()
+		context = super().get_context_data(**kwargs)
+		context.update(self.admin.admin_site.each_context(self.request))
+		context.update({
+			'opts': self.admin.model._meta,
+			'member': m,
+		})
+		return context
+
+	def form_valid(self, form):
+		m, ms = form.save()
+		messages.success(self.request, 'Your membership renewal has been submitted.')
+		return HttpResponseRedirect(reverse("admin:memberdb_membership_summary"))
diff --git a/src/account/actions.py b/src/memberdb/account_backend.py
similarity index 81%
rename from src/account/actions.py
rename to src/memberdb/account_backend.py
index c4a73826b0d8082f291b3ba98180bdb808026320..4883b204b82536be9d86af0133fbddcdc46e0246 100644
--- a/src/account/actions.py
+++ b/src/memberdb/account_backend.py
@@ -2,7 +2,8 @@
 import logging
 
 from django.conf import settings
-from django.core.exceptions import ImproperlyConfigured
+from django.core.exceptions import ImproperlyConfigured, ValidationError
+from django.utils.translation import gettext_lazy as _
 
 import ldap
 import re
@@ -15,9 +16,9 @@ log = logging.getLogger('ldap')
 # load config
 
 ldap_uri = getattr(settings, 'AUTH_LDAP_SERVER_URI')
-ldap_search_dn = getattr(settings, 'REPLACE_ME')
-ldap_bind_dn = getattr()
-ldap_bind_secret = getattr()
+ldap_search_dn = getattr(settings, 'AUTH_LDAP_USER_DN_TEMPLATE')
+#ldap_bind_dn = getattr()
+#ldap_bind_secret = getattr()
 
 
 #initalise ldap instace
@@ -40,6 +41,9 @@ def get_user_attrs(username, attrs):
 			return None
 		return result[0]; 
 
+	except:
+		return None
+
 def get_account_lock_status(username):
 	ld = get_ldap_instance()
 	try:
@@ -49,6 +53,17 @@ def get_account_lock_status(username):
 		ld.unbind()
 	return bool(result[1]['userAccountControl'] & 0x002)
 
+def validate_username(value):
+	# usernames can't begin with a numeric
+	if re.match(r"^\d.*", value):
+		log.info("test")
+		raise ValidationError(
+			_('Username cannot begin with a number'),
+			params={'value': value}
+		)
+	else:
+		return value
+
 # locks the specified User Account by performing the following actions:
 # 1. set UAC ACCOUNTDISABLE flag (0x002) via ldap
 # 2. set user shell to `/etc/locked20xx` via ldap
@@ -104,7 +119,7 @@ def unlock_account(username):
 # Account creation steps:
 # 
 def create_account(member):
-	username = 
+	username = "changeme";
 	log.info("I: creating new account for %s (%s %s)")
 	
 	# prepend student numbers with 'sn'
diff --git a/src/memberdb/admin.py b/src/memberdb/admin.py
index 25d3698ee1fceae61b8ddd7b38dcb43d23460184..413fe0edfec2a2977d6261b3d204f20ed01d942b 100644
--- a/src/memberdb/admin.py
+++ b/src/memberdb/admin.py
@@ -10,122 +10,138 @@ from gms import admin
 from memberdb.models import Member, IncAssocMember, Membership
 from memberdb.actions import download_as_csv
 from memberdb.approve import MembershipApprovalForm, MembershipApprovalAdminView
-
+from memberdb.account import AccountForm, AccountView
 
 def get_model_url(pk, model_name):
-    return reverse('admin:memberdb_%s_change' % model_name, args=[pk])
+	return reverse('admin:memberdb_%s_change' % model_name, args=[pk])
 
 """
 helper mixin to make the admin page display only "View" rather than "Change" or "Add"
 """
 class ReadOnlyModelAdmin(admin.ModelAdmin):
-    def has_add_permission(self, request):
-        return False
-        
-    def has_delete_permission(self, request, obj=None):
-        return True
+	def has_add_permission(self, request):
+		return False
+		
+	def has_delete_permission(self, request, obj=None):
+		return True
 
-    def has_change_permission(self, request, obj=None):
-        return False
+	def has_change_permission(self, request, obj=None):
+		return False
 
 """
 Define the administrative interface for viewing member details required under the Incorporations Act
 """
 class IAMemberAdmin(ReadOnlyModelAdmin):
-    readonly_fields = ['__str__', 'updated', 'created']
-    fields = ['first_name', 'last_name', 'email_address', 'updated', 'created']
-    search_fields = ['first_name', 'last_name', 'email_address']
-    list_display = readonly_fields
-    actions = [download_as_csv]
-
-    # add a "go to member" URL into the template context data
-    def change_view(self, request, object_id, form_url='', extra_context={}):
-        extra_context['member_edit_url'] = get_model_url(object_id, 'member')
-        return super().change_view(request, object_id, form_url, extra_context=extra_context)
-        
+	readonly_fields = ['__str__', 'updated', 'created']
+	fields = ['first_name', 'last_name', 'email_address', 'updated', 'created']
+	search_fields = ['first_name', 'last_name', 'email_address']
+	list_display = readonly_fields
+	actions = [download_as_csv]
+
+	# add a "go to member" URL into the template context data
+	def change_view(self, request, object_id, form_url='', extra_context={}):
+		extra_context['member_edit_url'] = get_model_url(object_id, 'member')
+		return super().change_view(request, object_id, form_url, extra_context=extra_context)
+		
 class MembershipInline(admin.TabularInline):
-    model = Membership
-    readonly_fields = ['member', 'date_submitted']
-    radio_fields = {'payment_method': admin.VERTICAL, 'membership_type': admin.VERTICAL}
-    extra = 0
-    fk_name = 'member'
+	model = Membership
+	readonly_fields = ['member', 'date_submitted']
+	radio_fields = {'payment_method': admin.VERTICAL, 'membership_type': admin.VERTICAL}
+	extra = 0
+	fk_name = 'member'
 
 class MemberAdmin(admin.ModelAdmin):
-    list_display = ['first_name', 'last_name', 'display_name', 'username']
-    list_filter = ['is_guild', 'is_student']
-    readonly_fields = ['member_updated', 'updated', 'created']
-    search_fields = list_display
-    actions = [download_as_csv]
-    inlines = [MembershipInline]
-
-    # add a "go to member" URL into the template context data
-    def change_view(self, request, object_id, form_url='', extra_context={}):
-        extra_context['incassocmember_url'] = get_model_url(object_id, 'incassocmember')
-        return super().change_view(request, object_id, form_url, extra_context=extra_context)
+	list_display = ['first_name', 'last_name', 'display_name', 'username']
+	list_filter = ['is_guild', 'is_student']
+	readonly_fields = ['member_updated', 'updated', 'created']
+	search_fields = list_display
+	actions = [download_as_csv]
+	inlines = [MembershipInline]
+	
+	# add custom URLs to this model in the admin site
+	def get_urls(self):
+		urls = super().get_urls()
+		custom_urls = [
+			path('<object_id>/create/', self.admin_site.admin_view(self.process_account), name='create-account'),
+		]
+		return custom_urls + urls
+
+
+
+	# add a "go to member" URL into the template context data
+	def change_view(self, request, object_id, form_url='', extra_context={}):
+		extra_context['incassocmember_url'] = get_model_url(object_id, 'incassocmember')
+		return super().change_view(request, object_id, form_url, extra_context=extra_context)
+
+	def process_account(self, request, *args, **kwargs):
+		return AccountView.as_view(admin=self)(request, *args, **kwargs)
+
+
 
 """
 Define the admin page for viewing normal Member records (all details included) and approving them
 """
 class MembershipAdmin(admin.ModelAdmin):
-    list_display = ['membership_info', 'member_actions', 'membership_type', 'payment_method', 'approved', 'date_submitted', ]
-    list_display_links = None
-    list_filter = ['approved']
-    readonly_fields = ['date_submitted']
-    radio_fields = {'payment_method': admin.VERTICAL, 'membership_type': admin.VERTICAL}
-
-    # make the admin page queryset preload the parent records (Member) 
-    def get_queryset(self, request):
-        qs = super().get_queryset(request)
-        return qs.select_related('member')
-
-    # add custom URLs to this model in the admin site
-    def get_urls(self):
-        urls = super().get_urls()
-        custom_urls = [
-            path('<object_id>/approve/', self.admin_site.admin_view(self.process_approve), name='membership-approve'),
-        ]
-        return custom_urls + urls
-
-    # display a short summary of relevant member / membership info for pending memberships
-    def membership_info(self, ms):
-        context = {
-            'ms': ms,
-            'member': ms.member,
-            'member_url': get_model_url(ms.member.pk, 'member'),
-        }
-        html = render_to_string('admin/memberdb/membership_summary.html', context)
-        return mark_safe(html)
-    
-    membership_info.short_description = 'Membership info'
-    membership_info.allow_tags = True
-
-    # called per record, returns HTML to display under the "Actions" column
-    def member_actions(self, ms):
-        context = {
-            'ms': ms,
-            'member': ms.member,
-            'member_url': get_model_url(ms.member.pk, 'member'),
-            'member_approve': reverse('admin:membership-approve', args=[ms.pk])
-        }
-        html = render_to_string('admin/memberdb/membership_actions.html', context)
-        return mark_safe(html)
-
-    member_actions.short_description = 'Actions'
-    member_actions.allow_tags = True
-
-    def process_approve(self, request, *args, **kwargs):
-        return MembershipApprovalAdminView.as_view(admin=self)(request, *args, **kwargs)
-
-"""
+	list_display = ['membership_info', 'membership_type', 'payment_method', 'approved', 'date_submitted', 'member_actions', ]
+	list_display_links = None
+	list_filter = ['approved']
+	readonly_fields = ['date_submitted']
+	radio_fields = {'payment_method': admin.VERTICAL, 'membership_type': admin.VERTICAL}
+
+	# make the admin page queryset preload the parent records (Member) 
+	def get_queryset(self, request):
+		qs = super().get_queryset(request)
+		return qs.select_related('member')
+
+	# add custom URLs to this model in the admin site
+	def get_urls(self):
+		urls = super().get_urls()
+		custom_urls = [
+			path('<object_id>/approve/', self.admin_site.admin_view(self.process_approve), name='membership-approve'),
+		]
+		return custom_urls + urls
+
+	# display a short summary of relevant member / membership info for pending memberships
+	def membership_info(self, ms):
+		context = {
+			'ms': ms,
+			'member': ms.member,
+			'member_url': get_model_url(ms.member.pk, 'member'),
+		}
+		html = render_to_string('admin/memberdb/membership_summary.html', context)
+		return mark_safe(html)
+	
+	membership_info.short_description = 'Membership info'
+	membership_info.allow_tags = True
+
+	# called per record, returns HTML to display under the "Actions" column
+	def member_actions(self, ms):
+		context = {
+			'ms': ms,
+			'member': ms.member,
+			'member_url': get_model_url(ms.member.pk, 'member'),
+			'member_approve': reverse('admin:membership-approve', args=[ms.pk]),
+			'create_account': reverse('admin:create-account', args=[ms.member.pk])
+		}
+		html = render_to_string('admin/memberdb/membership_actions.html', context)
+		return mark_safe(html)
+
+	member_actions.short_description = 'Actions'
+	member_actions.allow_tags = True
+
+	def process_approve(self, request, *args, **kwargs):
+		return MembershipApprovalAdminView.as_view(admin=self)(request, *args, **kwargs)
+
+	"""
 Register multiple ModelAdmins per model. See https://stackoverflow.com/questions/2223375/multiple-modeladmins-views-for-same-model-in-django-admin/2228821
 """
 class ProxyMembership(Membership):
-    class Meta:
-        proxy = True
+	class Meta:
+		proxy = True
 
 class PendingMembershipAdmin(MembershipAdmin):
-    def get_queryset(self, request):
-        return self.model.objects.filter(approved__exact=False)
+	def get_queryset(self, request):
+		return self.model.objects.filter(approved__exact=False)
 
 # Register the other models with either default admin site pages or with optional customisations
 admin.site.register(Member, MemberAdmin)
diff --git a/src/static/account_form.js b/src/static/account_form.js
new file mode 100644
index 0000000000000000000000000000000000000000..149bd13edff15de187cb6e733f812902b7e41920
--- /dev/null
+++ b/src/static/account_form.js
@@ -0,0 +1 @@
+var conditional_fields = $("div");
\ No newline at end of file
diff --git a/src/static/admin_custom.css b/src/static/admin_custom.css
index 629d6c09b024c7598d1fecd17bd3941a52af0a9b..00ce3db898ca8871eb330fc763d319be52f92bc7 100644
--- a/src/static/admin_custom.css
+++ b/src/static/admin_custom.css
@@ -34,6 +34,7 @@
     overflow: auto;
 }
 
+
 .button {
     display: inline-block;
 }
diff --git a/src/templates/admin/memberdb/account_create.html b/src/templates/admin/memberdb/account_create.html
new file mode 100644
index 0000000000000000000000000000000000000000..c8e1724a0ccde01b8634e0f9f2cf9466c941f9c5
--- /dev/null
+++ b/src/templates/admin/memberdb/account_create.html
@@ -0,0 +1,40 @@
+{% extends "admin/change_form.html" %}
+{% load i18n admin_static admin_modify %}
+
+{% block content %}
+<div id="content-main">
+<h1>Create Account for <i>{{ member.first_name }} {{ member.last_name }}</i></h1>
+<div class="ms-approve-summary">
+{% include "admin/memberdb/membership_summary.html" %}
+</div>
+<form action="" method="POST">
+    {% csrf_token %}
+
+    {% if form.non_field_errors|length > 0 %}
+      <p class="errornote">
+          Please correct the errors below.
+      </p>
+      {{ form.non_field_errors }}
+    {% endif %}
+
+    <fieldset class="module aligned">
+      {% for field in form %}
+        <div class="form-row">
+          {{ field.label_tag }}
+          {{ field }}
+          {{ field.errors }}
+          {% if field.field.help_text %}
+          <p class="help">
+            {{ field.field.help_text|safe }}
+          </p>
+          {% endif %}
+        </div>
+      {% endfor %}
+    </fieldset>
+    <div class="submit-row">
+        <input type="submit" class="default" value="Create">
+    </div>
+</form>
+</div>
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/templates/admin/memberdb/membership_actions.html b/src/templates/admin/memberdb/membership_actions.html
index 4d5c55b6260f06697a7b52f2e1f54462d599a608..ce12e156bda0e7749ef0d39781dacf4def36a385 100644
--- a/src/templates/admin/memberdb/membership_actions.html
+++ b/src/templates/admin/memberdb/membership_actions.html
@@ -4,5 +4,5 @@
     {% if not ms.approved %}
     <a class="button" href="{{ member_approve }}">Approve</a>&nbsp;
     {% endif %}
-    <a class="button" href="{{ account_create }}">Create Account</a>&nbsp;
+    <a class="button" href="{{ create_account }}">Create Account</a>&nbsp;
 </div>